Add Datadog API key validity check

What does this MR do and why?

This adds a validity check for Datadog API keys.

A user can then tell whether the exposed credential is still live rather than only that it was leaked.

Implementation

This follows ADR-006 and uses the registry directly to map the token straight to the verifier class/client, i.e. DatadogClient.

The verifier calls GET https://api.datadoghq.com/api/v1/validate, sending the key in the DD-API-KEY header. Unlike the other vendors in this stack, Datadog provides an endpoint whose only job is to answer whether a key is valid.

We map the responses to the following statuses/outcomes:

Response Outcome
200 active
403 inactive
429 RateLimitError
500, 502, 503, 504 NetworkError
anything else unknown

Reporting a live token as dead is worse than reporting nothing, so unmapped statuses are always unknown.

Why 403 means inactive here

403 maps to inactive for this vendor and no other, because Datadog documents it as the invalid-key answer for this endpoint rather than as a permission problem. From the Validate API key reference:

Check if the API key (not the APP key) is valid. If invalid, a 403 is returned.

That reference documents exactly three codes — 200 valid, 403 authentication error, 429 too many requests. The 5xx mappings above are therefore defensive rather than documented, and anything else falls through to unknown.

Generated, not hand-written

The client and its spec are the output of the Challenge #6 (closed) AI-assisted workflow rather than hand-written code. An LLM reads the vendor's API documentation and emits a vendor spec — plain data: endpoint, auth style, token pattern, status map — a human reviews that data, and a deterministic generator turns it into the verifier and its spec. Keeping the model's output as data instead of code is what makes the review tractable.

The generator itself is not on master yet (it is part of the Challenge #6 (closed) PoC), so only its output lands here. The reviewed vendor spec for Datadog needed no corrections.

Stack Position

We have 8 MRs for all new validity checks generated during Sec Challenge #6, with the base targeting master.

Each MR in the stack adds exactly one validity check: the client class, its spec, the registry entry, and the rate limit rule.

Stack (in review order)
# Check Token type
1 GitHub PAT Github Personal Access Token
2 OpenAI project key OpenAiProjectKey
3 Anthropic API key anthropic_key
4 Slack access tokens Slack token
5 Stripe live secret key StripeLiveSecretKey
6 Datadog API key DataDogAPIKey
7 SendGrid API token Sendgrid API token
8 Heroku API key Heroku API Key

Notes

How to set up and validate locally

  1. Run the specs:

    bundle exec rspec ee/spec/lib/security/secret_detection/partner_tokens/datadog_client_spec.rb \
      ee/spec/services/security/secret_detection/partner_tokens/registry_spec.rb
  2. Confirm the registry resolves the token type and that the rate limit rule exists:

    Security::SecretDetection::PartnerTokens::Registry.client_for('DataDogAPIKey')
    # => #<Security::SecretDetection::PartnerTokens::DatadogClient>
    Gitlab::ApplicationRateLimiter.period_for(:partner_datadog_api)
    # => 60 seconds
  3. Optional, with a real credential — a revoked token should come back inactive and a live one active:

    Security::SecretDetection::PartnerTokens::Registry
      .client_for('DataDogAPIKey').verify_token(ENV['TOKEN']).status

MR acceptance checklist

I have evaluated this MR against the MR acceptance checklist.

Edited by Ahmed Hemdan

Merge request reports

Loading
Loading