8000 Add JWT and OIDC to Sentry by jjcollinge · Pull Request #8662 · dapr/dapr · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add JWT and OIDC to Sentry #8662

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

Open
wants to merge 34 commits into
base: master
Choose a base branch
from

Conversation

jjcollinge
Copy link
Contributor
@jjcollinge jjcollinge commented Apr 13, 2025

Why?

Adds support for OIDC and JWTs in Dapr sentry so that the Dapr runtime can use OIDC to authenticate to component providers using JWTs. This allows resource providers to use identity federation (via OIDC) to authenticate the Dapr SPIFFE ID and thus allow access to their resources. This is supported in AWS, Azure and GCP along with other providers.

Description

This PR allows a user to configure Dapr sentry to issue workload identities as JWTs as well as x.509 certificates. It also extends Dapr sentry to host a partial OIDC compliant HTTP server that can be exposed to 3rd parties to fetch the JWKS and validate the JWTs. Both of these new behaviours are disabled by default and must be opted in to via configuration.

Once Dapr sentry is configured to issue JWTs, it becomes an additional field in the existing signing respon 8000 se from Sentry. No new APIs are added to Dapr sentry to issue JWTs. The JWT credential has the same lifecycle as the x.509 certificate and will be rotated via the same mechanism.

The default JWT signing key is a RSA 2048-bit private key using the PS256 algorithm as these are widely supported by OIDC providers unlike ECDSA and is preferred over basic RS256. The JWT keys are included in the existing dapr-trust-bundle secret and the JWKS is also distributed via the dapr-trust-bundle config map.

The OIDC server hosts the following endpoints

  • discovery @ /.well-known/openid-configuration
  • JWKS @ /jwks.json

The OIDC server is an unauthenticated HTTP server that must be exposed by the user to their OIDC providers to allow federation. It is the user's responsibility to ensure this server is exposed securely and it not something handled by Dapr.

Both the OIDC and JWT mechanism are customisable to allow users to setup their JWT infrastructure correctly. Responsibility for configuring Dapr sentry correctly for each use case is on the user as different integrations have different limitations e.g. which keys are supported etc. Currently Dapr sentry only supports 1 signing key and 1 signing algorithm at a time. The JWKS can include multiple signing algorithms to allow migrations. A single RSA or EC signing key can support multiple algorithms, so it is up to the user to configure Dapr to use the correct one when they provide their own signing key. No iss is set on the JWT if not issuer value has been provided by the user - this is not a required config on the JWT as it is not a requirement to use OIDC but is likely set when using any OIDC deployment.

New Flags

# JWT
--jwt-enabled: Enable JWT token issuance by Sentry
--jwt-key-filename: JWT signing key filename
--jwks-filename: JWKS (JSON Web Key Set) filename
--jwt-issuer: Issuer value for JWT tokens (no issuer if empty)
--jwt-audiences: List of audiences to include in JWT tokens
--jwt-signing-algorithm: Algorithm used for JWT signing (e.g., ES256, RS256) (defaults to PS256)
--jwt-key-id: Key ID (kid) used for JWT signing (defaults to dapr-sentry)

# OIDC
--oidc-http-port: The port for the OIDC HTTP server (disabled if 0)
--oidc-jwks-uri: Custom URI where the JWKS can be accessed externally
--oidc-path-prefix: Path prefix to add to all OIDC HTTP endpoints
--oidc-domains: List of allowed domains for OIDC HTTP endpoint requests
--oidc-tls-cert-file: TLS certificate file for the OIDC HTTP server (required when enabled)
--oidc-tls-key-file: TLS key file for the OIDC HTTP server (required when enabled)
--oidc-tls-insecure: Serve OIDC HTTP without TLS

sentry drawio

Dependencies

Kit

Changes to kit to support SPIFFE JWT
dapr/kit#118

Components contrib

Changes to components-contrib to use the JWT SVID provider in Azure components as a mechanism to authenticate via a Microsoft Federated Identity Credential
dapr/components-contrib#3797

Docs

Update for Azure authentication mechanism
dapr/docs#4650

Tests

Manual

I have manually used this build to write/read from a Dapr application to an Azure blob storage bucket by federating to Dapr sentry running in a local kind cluster. I have done this with provided keys and the default "generated" keys. This approach is documented in my docs PR.

Auto

I've added various unit tests around the JWT machinery. I've also extended the existing integration tests to validate the full flow of issuing a JWT and verifying against the OIDC endpoint.

--- PASS: Test_Integration (31.77s)
    --- PASS: Test_Integration/build_binaries (31.75s)
    --- PASS: Test_Integration/daprd/mtls/kubernetes/jwtvalidation (20.50s)
        --- PASS: Test_Integration/daprd/mtls/kubernetes/jwtvalidation/run (15.17s)
            --- PASS: Test_Integration/daprd/mtls/kubernetes/jwtvalidation/run/validate_JWT_token_issued_by_Sentry_service_in_kubernetes_mode (0.04

OIDC

curl -k https://localhost:9092/.well-known/openid-configuration
{
  "issuer": "https://localhost:9092",
  "jwks_uri": "https://localhost:9092/jwks.json",
  "response_types_supported": [
    "id_token"
  ],
  "subject_types_supported": [
    "public"
  ],
  "id_token_signing_alg_values_supported": [
    "ES256"
  ],
  "scopes_supported": [
    "openid"
  ],
  "claims_supported": [
    "sub",
    "iss",
    "aud",
    "exp",
    "iat",
    "nbf",
    "use"
  ]
}

curl -k https://localhost:9092/jwks.json | jq .
{
  "keys": [
    {
      "alg": "ES256",
      "crv": "P-256",
      "kid": "dapr-sentry",
      ...
    }
  ]
}

Issue reference

Please reference the issue this PR will close: #[issue number]

Checklist

Please make sure you've completed the relevant tasks for this PR, out of the following list:

@jjcollinge
Copy link
Contributor Author
jjcollinge commented Apr 22, 2025

Proven this works with Azure below

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: blob
spec:
  type: state.azure.blobstorage
  version: v2
  metadata:
  - name: accountName
    value: "spiffe"
  - name: containerName
    value: "demo"
  - name: clientId
    value: "xxxxx"
  - name: tenantId
    value: "xxxxx"

Screenshot 2025-05-12 at 12 14 11

@jjcollinge jjcollinge force-pushed the jjcollinge/sentry-jwt branch from 2ab0760 to 0f05837 Compare May 9, 2025 21:13
@jjcollinge jjcollinge marked this pull request as ready for review May 12, 2025 11:36
@jjcollinge jjcollinge requested review from a team as code owners May 12, 2025 11:36
@JoshVanL
Copy link
Contributor

@jjcollinge you can now rebase with the kit changes going into master 🙂

@jjcollinge jjcollinge force-pushed the jjcollinge/sentry-jwt branch from 2018d32 to d3e56a4 Compare May 23, 2025 06:49
Copy link
Contributor
@JoshVanL JoshVanL left a comment

Choose a reason for hiding this comment

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

Love this addition 😄 ❤️

Comment on lines 53 to 67
jwtKey, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err)

onemonth := time.Hour * 24 * 30
bundle, err := ca.GenerateBundle(rootKey, "integration.test.dapr.io", time.Second*5, &onemonth)
bundle, err := ca.GenerateBundle(rootKey, jwtKey, "integration.test.dapr.io", time.Second*5, &onemonth, ca.CredentialGenOptions{
RequireX509: true,
RequireJWT: true,
})
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there any metrics relating to JWT signing we should be testing?

@jjcollinge
Copy link
Contributor Author

Thanks for the review, still working through feedback and some improvements - will leave a comment when ready for a 2nd pass.

@jjcollinge jjcollinge force-pushed the jjcollinge/sentry-jwt branch 2 times, most recently from a9ccfe3 to 037a4ad Compare May 29, 2025 10:00
@jjcollinge jjcollinge force-pushed the jjcollinge/sentry-jwt branch from 037a4ad to 5cde5f1 Compare June 10, 2025 10:06
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Sig
67E6
ned-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
@jjcollinge jjcollinge force-pushed the jjcollinge/sentry-jwt branch from 5cde5f1 to c5d4ad4 Compare June 23, 2025 14:40
Signed-off-by: Jonathan Collinge <jonathancollinge@live.com>
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
0