Skip to content

Use Workload Identity

Last updated on

Managing credentials for workloads is a critical security challenge. STACKIT Workload Identity eliminates the need for long-lived, static secrets (like API keys or OAuth client secrets) by federating Kubernetes workload identities via OIDC federation, securing access with short-lived, auto-rotated tokens.

For SKE clusters, this feature is natively integrated. A managed stackit-pod-identity-webhook intercepts pod creation to automatically inject Kubernetes projected service account tokens into your workloads. The workload then utilizes this OIDC token to perform a token exchange with an external Identity Provider (IdP) for short-lived access tokens. For example, if the workload application uses the functions of a STACKIT SDK, it accesses the STACKIT IdP via the STACKIT API.

  • A STACKIT project.
  • A STACKIT Service Account with the appropriate permissions for your application.
  • An SKE cluster.

This flow shows how Kubernetes workload identity is exchanged for a short-lived STACKIT access token:

  1. The stackit-pod-identity-webhook intercepts the Pod’s creation request and, based on ServiceAccount annotations, injects a projected volume containing a signed JWT (the ServiceAccount token) and corresponding environment variables into the Pod spec.

  2. The application’s SDK reads this injected token volume and sends the K8s ServiceAccount token to the STACKIT IdP.

  3. The STACKIT IdP validates the token signature using the cluster’s Public OIDC Discovery endpoint (JWKS) and checks the configured assertions (for example, if the cluster identity is allowed to federate the requested IdP identity).

  4. If the validation is successful the IdP returns a temporary scoped STACKIT access token.

  5. The application uses the returned temporary access token to call the STACKIT API.

In practice, this keeps credentials short-lived and avoids static secrets in your workloads.

To use Workload Identity, you must establish a trust relationship between your SKE cluster and the STACKIT Identity Provider (IdP).

  • Navigate to the STACKIT Portal to configure Service Account Federation. Refer to the STACKIT IdP documentation Create, manage and delete federated identity providers.

  • Provide your clusters serviceAccountIssuer URL. You can obtain the URL from your cluster status via the SKE API, the STACKIT CLI or by inspecting your clusters status in the STACKIT Portal.

  • Create an assertion mapping using the sub (subject) claim to limit the usage of the STACKIT Service Account to a specific Kubernetes ServiceAccount.

  • Format the sub claim exactly as system:serviceaccount:<namespace>:<k8s-serviceaccount>.

For more details about the claims of the cluster’s JWT see the Kubernetes docs about Schema for service account private claims.

Once the trust relationship is established, you can enable Workload Identity for specific Pods by annotating their associated Kubernetes ServiceAccount.

  • Set the workload-identity.stackit.cloud/service-account-email annotation on your Kubernetes ServiceAccount.
  • Ensure the annotation matches the STACKIT Service Account email configured in the Portal.
  • The webhook automatically injects the necessary environment variables (like STACKIT_SERVICE_ACCOUNT_EMAIL) and projected volume mounts for the STACKIT SDK to use.

For details, see the example workload provided in the stackitcloud/stackit-pod-identity-webhook GitHub repo.

The following annotations can be applied to a Kubernetes ServiceAccount to configure the identity injection:

You can also skip token injection for specific resources using labels:

  • Add the label workload-identity.stackit.cloud/skip-pod-identity-webhook: "true" to a Pod to skip mutation.
  • Add the label workload-identity.stackit.cloud/skip-pod-identity-webhook: "true" to a namespace to ignore all Pods within it.

Step 3: Consider security aspects and follow best practices

Section titled “Step 3: Consider security aspects and follow best practices”

When operating workloads using Workload Identity in SKE, keep the following behaviors and security best practices in mind.

If a ServiceAccount is used only for Workload Identity, set automountServiceAccountToken: false in the Pod spec. This prevents the ServiceAccount token from being mounted for generic API server communication, reducing the impact radius of a potential compromise.

Secure the VM metadata service with a network policy

Section titled “Secure the VM metadata service with a network policy”

By default, IaaS virtual machines can obtain their own ServiceAccount tokens, and Pods running on these VMs can also retrieve these tokens by reaching the underlying VM’s metadata service. This behavior is intentional and aligns with how other major cloud providers operate.

However, if you want to strictly isolate your cluster workloads and prevent them from assuming the VM’s infrastructure identity, you can deploy a Kubernetes NetworkPolicy to block egress traffic to the metadata server.

The standard IP address for the cloud instance metadata service is 169.254.169.254. You can restrict access to this IP by applying a default deny policy for that specific egress destination.

Here is an example NetworkPolicy that blocks egress traffic to the metadata service for all Pods in a namespace:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-metadata-access
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32
  • podSelector: {}: This empty selector applies the policy to all Pods in the namespace where the policy is deployed.
  • cidr: 0.0.0.0/0: This allows egress traffic to all destinations globally.
  • except: [169.254.169.254/32]: This explicitly carves out the metadata IP address, dropping any outgoing requests from your Pods attempting to reach it.

The process of rotating the cluster’s signing key is automated by the SKE API.

  • The IdP caches the JWKS response per URI for 1 hour. As long as the kid (key ID) used to sign the token is present on the cached keys, the IdP accepts the token.
  • After a successful key rotation, old tokens signed by the previous key remain valid for up to 1 hour.

When using the STACKIT SDK for Go, the SDK automatically detects the injected environment variables and handles the token exchange with the STACKIT IdP behind the scenes.

For details, see the example workload provided in the stackitcloud/stackit-pod-identity-webhook GitHub repo.