deploy_feedback icon indicating copy to clipboard operation
deploy_feedback copied to clipboard

Consider issuing OIDC tokens, for hardened AWS/Google/etc access

Open danopia opened this issue 4 years ago • 1 comments

OpenID Connect (OIDC) is a technology that's getting adopted by numerous cloud providers for machine-to-machine, cloud-to-cloud authentication. OIDC support would allow a Deno Deploy program to access AWS resources such as DynamoDB without the app having any 'secrets' configured at all!

How the flow works

A JWT can be issued by the provider (e.g. Deno Deploy) for an arbitrary audience (e.g. AWS) and given to the deployment on request. The deployment can then send its new JWT in a request to the other service. Usually the JWT is used to get a new token from that third-party platform which expires after maybe 1 hour.

Because the provider platform issues the JWT, it contains strong assertions about the 'subject' of the token, such as a repository name or a deployment ID. The third-party platform can then be configured to check the token's issuer and subject to determine whether to allow the access. So in AWS you could create an IAM role that can only be assumed by a particular Deno Deploy deployment ID, if deployment ID is in Deno Deploy's JWT.

What is involved

  • Setting up some sort of key management and publishing the public keys to a static URL as a JWKS. And maybe rotating the keys on a schedule :)
  • Picking an 'issuer' URL and hosting a .well-known/openid-configuration file there.
  • Surfacing some way for Deploy apps to get up-to-date tokens.
    • The aud of the JWT should be customizable per-token, and tokens expire, so just environment variables isn't good enough.
    • The tokens should include the deployment ID somwhere in sub, as well as any additional fields that might be relevant to allowing access.

Who implements this already

JWT audiences

These are services I know of that could immediately work with Deno Deploy tokens if it introduced them today.

JWT issuers

These are providers that have prior art on giving tokens to running code.
  • Kubernetes can issue OIDC JWTs to pods. These are issued by the cluster itself and include Namespace, Pod, and ServiceAccount info. They are stored in temporary files and get rotated every hour by default. The pod's configuration includes token requests, so they are available as soon as the pod is started.
    • Sample openid-configuration from my own cluster.
    • Amazon enables this by default for their 'IRSA' solution, which is used with a pod config like so:
        containers:
        - .....
          env:
          - name: AWS_REGION
            value: us-west-2
          - name: AWS_ROLE_ARN
            value: "arn:aws:iam::111122223333:role/s3-reader"
          - name: AWS_WEB_IDENTITY_TOKEN_FILE # The AWS SDK watches this file
            value: "/var/run/secrets/eks.amazonaws.com/serviceaccount/token"
          volumeMounts:
          - mountPath: "/var/run/secrets/eks.amazonaws.com/serviceaccount/"
            name: aws-token
        volumes:
        - name: aws-token
          projected:
            sources:
            - serviceAccountToken:
                audience: "sts.amazonaws.com"
                expirationSeconds: 86400 # AWS configures a longer 24-hour expiration
                path: token
      
      The AWS SDKs automatically find and use these tokens, so the user's code does not need any adjustments to work.
    • Google GKE enables this if the cluster has Workload Identity toggled to on.
  • Github Actions now has an API endpoint that can issue JWTs. The workload is given environment variables that point to an issuing URL, including a random secret. The tokens contain verbose details like trigger type, branch, githash, relevant user, and workflow ID.
  • Gitlab CI issues a default token $CI_JOB_JWT_V2 as of 14.6.
  • CircleCI similarly has a $CIRCLE_OIDC_TOKEN environment variable, docs here. They're creating an issuer/JWKS per organization instead of one central signing key for everybody.

Also all kinds of OAuth sign-in providers are OIDC-compliant, like Google Accounts, Cloudflare Access, Auth0, Keycloak, ....

Downsides

  • The setup is more complex than static tokens.
  • Needing to fetch a token and redeem it with the third party will introduce some latency on the first request served by an isolate if it requires the credentials to serve that request.
    • AWS operates a token redemption endpoint in every AWS region, so the closest region could be used instead of us-east-1, but this is a very specific optimization that the application/SDK would need to be configured for.

For those reasons, JWTs won't entirely replace static credentials, especially for users just getting started. However it is an excellent tool for hardened access and provides stronger API trust with less credential upkeep.

danopia avatar Jan 14 '22 13:01 danopia

Huge fan of Workload Identity Federation, it feels like OATH2 for CI/CD. I would love to see this as a new user using Deno Deploy.

MiguelRipoll23 avatar May 29 '22 14:05 MiguelRipoll23