expand result code in pagerduty detector (#5230)
This now handles all documented response codes: 200 Valid key, has access 401 Invalid token 403 Valid key, insufficient permissions 402 Valid key, account plan limitation 429 Transient, rate limit 400 Permanent, malformed request 404 Permanent, resource not found
This commit is contained in:
@@ -86,8 +86,35 @@ func verifyPagerdutyapikey(ctx context.Context, client *http.Client, token strin
|
||||
case http.StatusOK:
|
||||
return true, nil
|
||||
case http.StatusUnauthorized:
|
||||
// Token is missing, malformed, or invalid.
|
||||
// Note that revoked (disabled) keys are treated as invalid.
|
||||
return false, nil
|
||||
case http.StatusForbidden:
|
||||
// PagerDuty returns 403 when the token authenticated successfully but
|
||||
// lacks permission for the requested resource -- e.g. a user token for
|
||||
// a restricted-role user, or a scoped OAuth token missing users.read.
|
||||
// This confirms the credential is live.
|
||||
return true, nil
|
||||
case http.StatusTooManyRequests:
|
||||
// Rate-limited. Can't determine validity; keep indeterminate for retry.
|
||||
return false, fmt.Errorf("PagerDuty rate limit reached")
|
||||
case http.StatusBadRequest:
|
||||
// Malformed request parameters. Shouldn't happen for our simple GET.
|
||||
// Not transient -- the same request will always produce the same result.
|
||||
return false, nil
|
||||
case http.StatusPaymentRequired:
|
||||
// Account lacks the pricing-plan abilities for this endpoint. PagerDuty
|
||||
// must have authenticated the token before checking plan features, so
|
||||
// the credential is live.
|
||||
return true, nil
|
||||
case http.StatusNotFound:
|
||||
// Resource not found. Unusual on the /users collection endpoint.
|
||||
// Not transient -- retrying won't make the endpoint appear.
|
||||
// Shouldn't happen in practice.
|
||||
return false, nil
|
||||
default:
|
||||
// Unknown status codes (including 5xx server errors) are potentially
|
||||
// transient, so return an error to keep the result indeterminate.
|
||||
return false, fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestPagerDutyApiKey_FromChunk(t *testing.T) {
|
||||
wantVerificationErr: true,
|
||||
},
|
||||
{
|
||||
name: "found, verified but unexpected api surface",
|
||||
name: "found, unverified due to not found (404)",
|
||||
s: Scanner{client: common.ConstantResponseHttpClient(404, "")},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -86,9 +86,73 @@ func TestPagerDutyApiKey_FromChunk(t *testing.T) {
|
||||
Verified: false,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "found, verified via 403 (valid key, insufficient permissions)",
|
||||
s: Scanner{client: common.ConstantResponseHttpClient(403, `{"error":{"message":"Access Denied","code":2010}}`)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte(fmt.Sprintf("You can find a pagerdutyapikey secret %s within", secret)),
|
||||
verify: true,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detector_typepb.DetectorType_PagerDutyApiKey,
|
||||
Verified: true,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "found, indeterminate due to rate limiting (429)",
|
||||
s: Scanner{client: common.ConstantResponseHttpClient(429, "")},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte(fmt.Sprintf("You can find a pagerdutyapikey secret %s within", secret)),
|
||||
verify: true,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detector_typepb.DetectorType_PagerDutyApiKey,
|
||||
Verified: false,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
wantVerificationErr: true,
|
||||
},
|
||||
{
|
||||
name: "found, unverified due to bad request (400)",
|
||||
s: Scanner{client: common.ConstantResponseHttpClient(400, "")},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte(fmt.Sprintf("You can find a pagerdutyapikey secret %s within", secret)),
|
||||
verify: true,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detector_typepb.DetectorType_PagerDutyApiKey,
|
||||
Verified: false,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "found, verified via 402 (valid key, account plan limitation)",
|
||||
s: Scanner{client: common.ConstantResponseHttpClient(402, "")},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte(fmt.Sprintf("You can find a pagerdutyapikey secret %s within", secret)),
|
||||
verify: true,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detector_typepb.DetectorType_PagerDutyApiKey,
|
||||
Verified: true,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "found, unverified",
|
||||
s: Scanner{},
|
||||
|
||||
Reference in New Issue
Block a user