Provider Identity with OIDC

Crossplane providers use a ProviderConfig Kubernetes object to supply credentials to authenticate with external services. For example, Upbound’s AWS provider offers a ProviderConfig that supports supplying credentials via a Kubernetes Secret, environment variable, file, and more. Users can create multiple ProviderConfig instances and reference them from the spec.providerConfigRef field of any managed resource.

Providers in Upbound managed control planes can also use an Upbound credential source called Provider Identity.

The Upbound credential source uses OpenID Connect (OIDC) to authenticate to providers without requiring users to store credentials on Upbound.

This authentication method is comparable to “workload identity” offered by some managed Kubernetes providers.

OpenID Connect

OpenID Connect (OIDC) is a protocol that’s built on top of OAuth 2.0. It serves to establish the identity of an entity in one environment that’s attempting to access resources in another.

OIDC calls the two parties the OpenID Providers (OPs) and Relying Parties (RPs). Managed control planes define these roles as follows:

  • OpenID Provider: Upbound
  • Relying Party: an external service that supports OIDC, for example, AWS, Azure or GCP

Users set up a trust relationship between Upbound and the external service. Upbound uses the trust relationship instead of storing credentials for an external service in the managed control plane.

Upbound injects an identity token into the file system of every provider Pod. Upbound sends the token to the external service and exchanges it for a short-lived credential. Upbound uses the short-lived credential to perform operations against the external service.

Creating trust relationships

Every OIDC relying party implements its own mechanism for establishing a trust relationship and associating permissions. Typically, the process involves the following broad steps:

  1. Specifying the issuer. For Upbound, this is https://proidc.upbound.io.
  2. Specifying an audience. This may vary by relying party.
  3. Creating a role or service account that an entity possessing a valid identity token can assume.
  4. Associating permissions with the role or service account.

Different OIDC relaying parties may define valid tokens differently. Typically it involves writing a policy that restricts what subject can assume the role or service account.

Warning
Authoring a policy with appropriate access controls is critical to ensure that only your provider in your managed control plane is able to assume the role or service account.

Identity tokens are JSON Web Tokens (JWTs). The OIDC claims supported by Upbound are available in the OIDC metadata endpoint at https://proidc.upbound.io/.well-known/openid-configuration.

 1{
 2  "issuer": "https://proidc.upbound.io",
 3  "jwks_uri": "https://proidc.upbound.io/.well-known/jwks",
 4  "response_types_supported": [
 5    "id_token"
 6  ],
 7  "subject_types_supported": [
 8    "public"
 9  ],
10  "id_token_signing_alg_values_supported": [
11    "RS256"
12  ],
13  "claims_supported": [
14    "sub",
15    "aud",
16    "exp",
17    "iat",
18    "iss",
19    "jti",
20    "nbf"
21  ]
22}

OIDC relying parties use this information to validate identity tokens. Relying parties use the jwks_uri to ensure that the OIDC provider signed the identity token with their private key. The private key must correspond to one of the public keys from https://proidc.upbound.io/.well-known/jwks.

The iss and aud claims of an identity token should match the issuer and audience configured for the relying party. The sub should be a valid subject based on the authored policy. For providers running in Upbound managed control planes, the subject adheres to the following format.

mcp:<account>/<mcp-name>:provider:<provider-name>

For example, the following would be a valid subject for provider-aws in a managed control plane named prod-1 in the my-org account.

mcp:my-org/prod-1:provider:provider-aws

The claims for an identity token injected into the file system of a provider in a managed control plane looks like the following.

 1{
 2  "iss": "https://proidc.upbound.io",
 3  "sub": "mcp:my-org/prod1:provider:provider-aws",
 4  "aud": [
 5    "sts.amazonaws.com"
 6  ],
 7  "exp": 1680124165,
 8  "nbf": 1680120565,
 9  "iat": 1680120565,
10  "jti": "YL1ouQ5KJiTY2QShIRczqQ=="
11}
Tip
Identity tokens injected into a provider Pod are valid for 1 hour. They are automatically refreshed before expiration to ensure there is no interruption in service.

Using Upbound OIDC as a credential source

The Upbound console allows for creating instances of a ProviderConfig via the console, instead of manually authoring a YAML manifest. Users may also connect to their managed control planes directly and apply a ProviderConfig YAML manifest.

Each Provider defines their own ProviderConfig schema and values.

Tip
Proividers in the Upbound Marketplace contain examples of how to use source: Upbound to enable OIDC authentication.

For example, Upbound’s GCP provider includes the following manifest for using the Upbound OIDC identity source.

 1apiVersion: gcp.upbound.io/v1beta1
 2kind: ProviderConfig
 3metadata:
 4  name: default
 5spec:
 6  credentials:
 7    source: Upbound
 8    upbound:
 9      federation:
10        providerID: projects/<project-id>/locations/global/workloadIdentityPools/<identity-pool>/providers/<identity-provider>
11        serviceAccount: <service-account-name>@<project-name>.iam.gserviceaccount.com
12  projectID: my-org-gcp-project

Applying this manifest in a managed control plane causes provider-gcp to fetch its identity token from the file system and use it to authenticate to GCP.

Adding Upbound OIDC to a Provider

Any provider that can run in a managed control plane can support the Upbound credential source. Upbound injects identity tokens into the file system of every provider Pod whether they support OIDC or not. A provider wishing to support OIDC can access its identity token in the /var/run/secrets/upbound.io/provider/token file. This Pull Request provides a reference implementation.