Skip to content

Conversation

@JacobsonMT
Copy link
Contributor

This PR introduces OAuth2 client_credentials grant type support for HTTP client configurations in webhook receivers.

Current vs Future Work

This PR introduces HTTPClientConfig with a single field OAuth2 containing the new OAuth2 configuration options. This setup intentionally mimics upstream alertmanager's common http_config as the intention is to bring this change to all relevant integrations and eventually include other common http client configuration options in a standardized way between notifier types.

All added configuration fields:

http_config:
  oauth2:
    client_id: "test-client-id"
    client_secret: "test-client-secret"
    token_url: "https://localhost/auth/token"
    scopes:
      - "scope1"
      - "scope2"
    endpoint_params:
      param1: "value1"
      param2: "value2"
    tls_config:
      insecureSkipVerify: false
      caCertificate: "-----BEGIN CERTIFICATE..."
      clientCertificate: "-----BEGIN CERTIFICATE..."
      clientKey: "-----BEGIN EC PRIVATE KEY..."
    proxy_config:
      proxy_url: "http://localproxy:8080"
      no_proxy: "localhost,1.2.3.4"
      proxy_from_environment: false
      proxy_connect_header:
        X-Proxy-Header: "proxy-value"

Notable differences from upstream

  • oauth2: Does not add support for:
    • client_secret_file
    • client_secret_ref
  • oauth2.tls_config:
    • Does not add support for:
      • ca_file
      • cert_file
      • key_file
      • ca_ref
      • cert_ref
      • key_ref
      • server_name
      • min_version
      • max_version
    • Uses the existing TLSConfig struct. This means out json fields does not match. Ex: cert vs clientCertificate. I'm on the fence here on whether it's worth defining a new struct to keep the field namings the same, thoughts?
  • oauth2.tls_config:
    • proxy_connect_header values are not secured in Grafana as secure map values are not supported. We can consider breaking similar with upstream and adding a field specifically for Proxy-Authorization, thoughts?
    • Proxying is enabled (compared to Mimir AM) as we apply to firewall dialer to the oauth2 client.

Implementation Notes

  • OAuth2 config validation is done during client creation. This is for two reasons:
    • The tokenSource needs to be stored outside Notify as the token is re-used until expiration.
    • Prefer failing invalid configuration early when creating the contact point, instead of silently failing to send notifications afterwards.
  • BuildReceiverIntegrations: The above change means this function needs to return an error again (it was recently removed).
  • It will make sense to move/extend various existing configs to the new common http_config, but this is not done yet. For example, the webhook notifer already has tlsConfig and hmacConfig and it would make sense to move these to http_config. This will require a migration though, as the config path will change and the current implementation of these options fail on Send instead of on Create.
  • Since this is not the simplest feature to test/validate I added vairly comprehensive unit tests. Local testing can be done with your choice of local or cloud oauth2 provider (ex. Keycloak, Ory Hydra, Auth0, ...)

Copilot Summary 🤖

OAuth2 Integration:

  • Added support for OAuth2 in http/client.go, including a new oauth2.TokenSource field in the Client struct and validation for OAuth2 configurations during client initialization. ([[1]](https://github.com/grafana/alerting/pull/338/files#diff-db6dcd51441efbbef50fb4f0e52a2a24d0207a8cf997c2c2d18f1345e0b4b255R28-R39), [[2]](https://github.com/grafana/alerting/pull/338/files#diff-db6dcd51441efbbef50fb4f0e52a2a24d0207a8cf997c2c2d18f1345e0b4b255L50-R71))
  • Introduced the WithHTTPClientConfig option to pass HTTP client configurations, including OAuth2 settings. ([http/client.goR88-R95](https://github.com/grafana/alerting/pull/338/files#diff-db6dcd51441efbbef50fb4f0e52a2a24d0207a8cf997c2c2d18f1345e0b4b255R88-R95))
  • Enhanced the SendWebhook method to include OAuth2 token handling via an OAuth2 round-tripper. ([http/client.goR149-R153](https://github.com/grafana/alerting/pull/338/files#diff-db6dcd51441efbbef50fb4f0e52a2a24d0207a8cf997c2c2d18f1345e0b4b255R149-R153))

Proxy Configuration:

  • Added a new ProxyConfig struct in http/config.go to manage proxy settings, including support for proxy URLs, no-proxy addresses, and headers for CONNECT requests. ([http/config.goR1-R128](https://github.com/grafana/alerting/pull/338/files#diff-9cd5b98b32603671d06faab6568b1be0d3f2790b8ee426270cb20cb91824997aR1-R128))
  • Implemented validation logic for proxy configurations to ensure proper usage of proxy-related fields. ([http/config.goR1-R128](https://github.com/grafana/alerting/pull/338/files#diff-9cd5b98b32603671d06faab6568b1be0d3f2790b8ee426270cb20cb91824997aR1-R128))

Test Coverage Enhancements:

  • Updated tests in http/client_test.go to validate OAuth2 integration, including scenarios for valid and invalid configurations, token reuse, and proxy interactions. ([[1]](https://github.com/grafana/alerting/pull/338/files#diff-0a04f5d21c1d2223648ce05c57de7f0e6b9be9be2da51184c5b441a3602845e6R5-R81), [[2]](https://github.com/grafana/alerting/pull/338/files#diff-0a04f5d21c1d2223648ce05c57de7f0e6b9be9be2da51184c5b441a3602845e6R234-R531))
  • Added a comprehensive test suite for OAuth2, covering various configurations such as scopes, endpoint parameters, and custom dialers. ([http/client_test.goR234-R531](https://github.com/grafana/alerting/pull/338/files#diff-0a04f5d21c1d2223648ce05c57de7f0e6b9be9be2da51184c5b441a3602845e6R234-R531))

@JacobsonMT JacobsonMT requested a review from a team as a code owner June 2, 2025 21:17
@github-project-automation github-project-automation bot moved this to In review in Alerting Jun 2, 2025
@JacobsonMT JacobsonMT force-pushed the jacobsonmt/oauth2-webhooks branch from f30d496 to 5bf1217 Compare June 2, 2025 21:18
@JacobsonMT JacobsonMT force-pushed the jacobsonmt/oauth2-webhooks branch from 77ba656 to af1d9f8 Compare June 2, 2025 21:42
Copy link
Collaborator

@yuri-tceretian yuri-tceretian left a comment

Choose a reason for hiding this comment

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

Still looking into it. Comments so far

http/config.go Outdated

type ProxyConfig struct {
// ProxyURL is the HTTP proxy server to use to connect to the targets.
ProxyURL string `yaml:"proxy_url,omitempty" json:"proxy_url,omitempty"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if it should be masked i.e. overridden .String() so we do not accidentally expose any urls

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Possibly, though it's unclear at a glance where we'd want to redact the information. I can tackle in a followup.

// ProxyFromEnvironment uses environment HTTP_PROXY, HTTPS_PROXY and NO_PROXY to determine proxies.
ProxyFromEnvironment bool `yaml:"proxy_from_environment,omitempty" json:"proxy_from_environment,omitempty"`
// ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests.
ProxyConnectHeader map[string]string `yaml:"proxy_connect_header,omitempty" json:"proxy_connect_header,omitempty"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

WDYT about making all header's values secure?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd like to, but this is tougher than it seems. We don't really have a way to secure arbitrary map[string]string fields in grafana/grafana backend or a way to display that kind of component in the FE right now. I'll see what I can do in a followup.

Copy link
Collaborator

@yuri-tceretian yuri-tceretian left a comment

Choose a reason for hiding this comment

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

LGTM 👍🏻

…configurations.

Mimics upstream configuration so that json config remains similar.

- Added proxy settings, including `ProxyURL`, `NoProxy`, and `ProxyConnectHeader`, and ensured validation.
- Updated OAuth2 configuration to support proxy usage.
- Added tests for HTTP client, proxy configuration, and OAuth2 validation.
@JacobsonMT JacobsonMT force-pushed the jacobsonmt/oauth2-webhooks branch from 85ce077 to cabc784 Compare June 10, 2025 04:12
@JacobsonMT JacobsonMT merged commit 3e20fda into main Jun 10, 2025
6 checks passed
@JacobsonMT JacobsonMT deleted the jacobsonmt/oauth2-webhooks branch June 10, 2025 04:34
@github-project-automation github-project-automation bot moved this from In review to Done in Alerting Jun 10, 2025
@saurabhb-dev
Copy link

Hi Team,

Can you please tell the estimate for UI to be released for this feature? In the current Grafana OSS there does not exists an UI for using this contact point.

Thanks,
Saurabh

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

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants