Skip to content

Conversation

@MuneebUllahKhan222
Copy link
Contributor

Description:

Datadog token verification previously relied on an App-key–dependent endpoint (/api/v2/users) to validate the Application Key + API Key combination. If this endpoint returned an error (for example, due to insufficient App Key permissions), the detector would mark the token as unverified and skip API key validation entirely.

This behavior caused valid Datadog API keys to be reported as unverified, resulting in false negatives.

To resolve this issue I have done the following changes:

  • Treat /api/v2/users as the primary verification path for App + API key combinations

  • Add a fallback verification step using the API-key–only validation endpoint when App key verification fails

  • Avoid calling the fallback endpoint when App key verification succeeds

  • Ensure valid API keys are marked verified even when the App key lacks required permissions

Checklist:

  • Tests passing (make test-community)?
  • Lint passing (make lint this requires golangci-lint)?

@MuneebUllahKhan222 MuneebUllahKhan222 requested a review from a team December 24, 2025 07:13
@MuneebUllahKhan222 MuneebUllahKhan222 requested review from a team as code owners December 24, 2025 07:13
@MuneebUllahKhan222 MuneebUllahKhan222 changed the title Datadog detector verification fix [INS-240] Datadog detector verification fix Dec 24, 2025
@MuneebUllahKhan222 MuneebUllahKhan222 changed the base branch from main to datadog-detector-multi-endpoint December 24, 2025 08:58
@MuneebUllahKhan222 MuneebUllahKhan222 changed the base branch from datadog-detector-multi-endpoint to main December 24, 2025 11:55
Comment on lines +115 to +124
if len(uniqueFoundUrls) == 0 {
// In case no endpoints were found in data, use the default cloud endpoint
s.UseCloudEndpoint(true)
endpoints = s.Endpoints()
} else {
// In case endpoints were found in data, use them
// also add cloud endpoint at the end so if not validated against found endpoints, try cloud endpoint as well
endpoints = s.configureEndpoints(uniqueFoundUrls)
endpoints = append(endpoints, s.CloudEndpoint())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UseCloudEndpoint defaults to true when no endpoints are configured. I think it’s clearer to reverse the condition and explicitly disable it only when we find endpoints in the data:

// If we found any endpoints in the data, disable the cloud endpoint
// and validate only against the found endpoints.
if len(uniqueFoundUrls) > 0 {
	s.UseCloudEndpoint(false)
}

// Endpoints behavior:
// A) If the user configured endpoints, only those will be returned.
// B) If endpoints were found in the data, only those will be returned.
// C) If neither applies, it will return only cloud endpoint.
endpoints = s.Endpoints(uniqueFoundUrls...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this, we can drop the configureEndpoints function and normalize the endpoints:

for i, endpoint := range endpoints {
	// Normalize endpoints so they all share the same format.
	// - User-configured endpoints may be missing "https://"
	// - Discovered endpoints also omit the scheme
	if !strings.HasPrefix(endpoint, "https://") {
		endpoint = "https://" + endpoint
	}

	// Ensure all endpoints end with "/api"
	// (user-configured and cloud endpoints may omit it)
	if !strings.HasSuffix(endpoint, "/api") {
		endpoint = endpoint + "/api"
	}

	endpoints[i] = endpoint
}

// At this point, all endpoints start with "https://" and end with "/api",
// so they’re ready for direct use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be normalized even more I believe but this seems like a reasonable good approach to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants