-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
feat(seer-infra-telemetry): Add a PAT-only DatadogIdentityProvider #118072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,7 @@ | |
|
|
||
| from sentry.auth.exceptions import IdentityNotValid | ||
| from sentry.http import safe_urlopen, safe_urlread | ||
| from sentry.identity.base import Provider | ||
| from sentry.identity.mcp import McpIdentityProvider | ||
| from sentry.identity.oauth2 import ( | ||
| OAuth2CallbackView, | ||
|
|
@@ -401,3 +402,53 @@ def refresh_identity(self, identity: Identity | RpcIdentity, **kwargs: Any) -> N | |
| self.config["client_secret"] = client_secret | ||
|
|
||
| super().refresh_identity(identity, **kwargs) | ||
|
|
||
|
|
||
| class DatadogPatIdentityProvider(McpIdentityProvider, Provider): | ||
|
srest2021 marked this conversation as resolved.
|
||
| """Datadog identity backed by a user-supplied read-only personal access token. | ||
|
|
||
| An alternative to the OAuth flow for environments where Datadog's MCP OAuth | ||
| (loopback-only redirect URIs) cannot be used. The submitted token is used as | ||
| a Bearer token against the MCP server, identical to an OAuth access token. | ||
| """ | ||
|
|
||
| key = IntegrationProviderSlug.DATADOG_PAT | ||
| name = "Datadog (Personal Access Token)" | ||
|
|
||
| def get_pipeline_views(self) -> list[PipelineView[IdentityPipeline]]: | ||
| return [] | ||
|
|
||
| def build_mcp_url(self, identity_data: dict[str, Any]) -> str | None: | ||
| """Full MCP endpoint URL for a stored Datadog identity. | ||
| Returns None when the site is missing or invalid.""" | ||
| base = _mcp_base_url_for_site(identity_data.get("site")) | ||
| return f"{base}{MCP_ENDPOINT_PATH}" if base else None | ||
|
|
||
| def build_identity(self, data: dict[str, Any]) -> dict[str, Any]: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wondering if a lot of this could be consolidated with the existing datadog provider? Not sure how much overlap there is. I suppose it might not be worth it, since probably long term we'll only keep one of these providers.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, since we'll know (hopefully) soon whether we can go forward with the oauth version, probably easier to keep separate for clean deletion |
||
| access_token = data.get("access_token") | ||
| if not access_token: | ||
| raise ValueError("Datadog requires an 'access_token' parameter.") | ||
|
|
||
| site = data.get("site") | ||
| base = _mcp_base_url_for_site(site) | ||
| if not site: | ||
| raise ValueError("Datadog requires a 'site' parameter (e.g. 'datadoghq.com').") | ||
| elif base is None: | ||
| raise ValueError(f"Invalid Datadog site: {site}") | ||
|
|
||
| user = get_user_info(access_token, base) | ||
| if "user_uuid" not in user or "org_uuid" not in user: | ||
| raise IdentityNotValid( | ||
| "User info response missing required fields (user_uuid, org_uuid)" | ||
| ) | ||
|
|
||
| return { | ||
| "type": IntegrationProviderSlug.DATADOG_PAT, | ||
| "id": user["user_uuid"], | ||
| "idp_external_id": user["org_uuid"], | ||
| "idp_config": {"site": site}, | ||
| "email": user.get("user_email"), | ||
| "name": user.get("user_name"), | ||
| "scopes": [], | ||
| "data": {"access_token": access_token, "site": site}, | ||
| } | ||
|
srest2021 marked this conversation as resolved.
srest2021 marked this conversation as resolved.
|
||
Uh oh!
There was an error while loading. Please reload this page.