Skip to content

Allow scoping Datadog incident notifications - #69324

Open
Archonr wants to merge 1 commit into
gravitational:masterfrom
Archonr:datadog-scope-incident-notifications
Open

Allow scoping Datadog incident notifications#69324
Archonr wants to merge 1 commit into
gravitational:masterfrom
Archonr:datadog-scope-incident-notifications

Conversation

@Archonr

@Archonr Archonr commented Aug 4, 2026

Copy link
Copy Markdown

Problem

The Datadog Incident Management plugin creates an incident for every Access Request in the cluster, and no configuration narrows that down. Two mandatory settings guarantee that at least one recipient always resolves:

  • api/types/plugin.gofallback_recipient must be set on the plugin resource.
  • integrations/access/datadog/config.gorole_to_recipients and role_to_recipients["*"] are both required.

getMessageRecipients() creates an incident whenever the resolved recipient list is non-empty, and the Datadog FetchRecipient never returns an error, so an operator cannot empty the list by pointing the fallback at a non-existent handle either.

For deployments that adopt the plugin mainly for on-call auto-approval (teleport.dev/schedules) of a few production roles, this means every unrelated request also pages the fallback recipient. In our cluster the plugin produced 208 incidents in 11 days, while only 2 request policies actually rely on on-call auto-approval; the rest are non-production requests reviewed by a human, and Slack already notifies the reviewers.

The Opsgenie plugin does not have this problem: it imposes no recipient requirement, and its notifications are routed by the teleport.dev/notify-services annotation. This PR gives the Datadog plugin the same capability. Related: #65345.

Changes

  • role_to_recipients and its * entry are no longer required by the plugin config, matching the Opsgenie, PagerDuty, Jira and Mattermost plugins.
  • fallback_recipient is no longer required on the PluginDatadogAccessSettings resource.
  • teleport.dev/notify-services on the requesting role now routes Datadog notifications. When the annotation is present it is authoritative for that request (only the annotated team handles or user emails are notified); when it is absent, role_to_recipients and the suggested reviewers keep being used exactly as before.
  • The Helm chart exposes datadog.roleToRecipients and only renders the "*" entry when datadog.fallbackRecipient is set.
  • Docs: chart reference regenerated, and the plugin guide gains a section on scoping which requests create an incident.

A request that matches no Access Monitoring Rule, carries no annotation and has no recipient configured for its role now creates no incident.

Backwards compatibility

Existing deployments are unaffected. Every current configuration defines a catch-all recipient — the chart hardcodes "*" = [fallbackRecipient] and the hosted plugin requires the field — so recipients keep resolving for every request. The new behaviour only applies once an operator deliberately removes the catch-all.

Changelog: The Datadog Incident Management plugin can now scope incidents to specific roles: role_to_recipients, its * entry and fallback_recipient are optional, and the teleport.dev/notify-services annotation routes notifications.

Manual Test Plan

Test Environment

macOS, Go 1.26, in-process auth server (MinimalAuthHelper), helm unittest for the chart.

Test Cases

  • go test ./integrations/access/datadog/... — full OSS suite passes, including two new cases: TestIncidentCreationForNotifyServices (annotation routes the incident to the annotated team and suppresses suggested reviewers) and TestNoIncidentWithoutRecipients (no recipients, no incident).
  • go test ./integrations/access/accessrequest/... ./integrations/access/opsgenie/... ./integrations/access/common/... — other plugins unchanged.
  • go test ./api/types/PluginDatadogAccessSettings validation, including the updated case for an empty fallback recipient.
  • helm unittest examples/chart/access/datadog — existing configmap snapshot unchanged when fallbackRecipient is set; new cases cover a roleToRecipients map and the omission of the "*" entry.
  • Not verified: the enterprise test suite (no license locally) and the hosted plugin running with an empty fallback_recipient, which needs a Cloud tenant.

Made with Cursor

The Datadog plugin creates an incident for every Access Request, because
role_to_recipients and fallback_recipient are both mandatory and a
catch-all recipient therefore always resolves. Deployments that only use
the plugin for on-call auto-approval of a few production roles have no
way to narrow that down, so every request, including ones a human
reviews by hand, pages the fallback recipient.

Make the catch-all optional and let the requesting role decide:

- role_to_recipients and its "*" entry are no longer required, matching
  the Opsgenie, PagerDuty, Jira and Mattermost plugins.
- fallback_recipient is no longer required on the plugin resource.
- The teleport.dev/notify-services annotation now routes Datadog
  notifications, as it already does for Opsgenie. When present it is
  authoritative for that request; when absent, role_to_recipients and
  the suggested reviewers are used as before.
- The Helm chart exposes datadog.roleToRecipients and only renders the
  "*" entry when a fallback recipient is set.

Requests that match no Access Monitoring Rule, carry no annotation and
have no recipient for their role now create no incident.

Existing configurations are unaffected: they all define a catch-all
recipient, which keeps resolving for every request.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6638c26526

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +25 to +29
{{- with .Values.datadog.fallbackRecipient }}
"*" = [{{ . | quote }}]
{{- end }}
{{- range $role, $recipients := .Values.datadog.roleToRecipients }}
{{ $role | quote }} = {{ toJson $recipients }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid duplicate Datadog wildcard recipients

When an existing chart user keeps datadog.fallbackRecipient set and also adds datadog.roleToRecipients["*"] (documented as equivalent to the fallback), this template renders two "*" entries in the same [role_to_recipients] TOML table. The Datadog plugin loads this ConfigMap via toml.LoadFile, so the pod will fail to start with a duplicate-key config instead of using the requested routing; suppress one source when the other defines the wildcard, or reject the combination in the schema.

Useful? React with 👍 / 👎.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant