Setting up ProviderConfig to use Kubernetes Service Account for authentication
TypeScriptTo set up ProviderConfig to use a Kubernetes Service Account for authentication in Pulumi, you need to follow a few steps that involve creating a Service Account within your Kubernetes cluster, granting the necessary roles and permissions to it, and configuring your Pulumi program to use this Service Account for deploying resources to the cluster.
Below is a program written in TypeScript that demonstrates this process. First, a Service Account is created in Kubernetes. Then, a secret token that's automatically created for the Service Account is retrieved. Finally, the Kubernetes Provider is configured to use this token for authentication.
The
kubernetes.core.v1.ServiceAccount
resource is used to create a new Service Account, and thekubernetes.core.v1.Secret
is used to access the token. We then pass this token to thekubernetes.Provider
as part of its configuration.Example Program
import * as pulumi from "@pulumi/pulumi"; import * as k8s from "@pulumi/kubernetes"; // Create a Service Account in Kubernetes const serviceAccount = new k8s.core.v1.ServiceAccount("my-service-account", { metadata: { name: "my-service-account" } }); // A Service Account is automatically assigned a secret token. We need to get this secret. const serviceAccountSecret = serviceAccount.secrets.apply(secrets => { // Since a Service Account can have multiple secrets associated with it (e.g., pull secrets), // we need to locate the one that is of type "kubernetes.io/service-account-token". // This is typically the first secret in the list. const saSecret = secrets[0]; const secret = k8s.core.v1.Secret.get("service-account-secret", saSecret.name); return secret; }); // The secret contains a token that we can use to authenticate with the Kubernetes API. // We'll use this token to configure the Kubernetes provider. const kubeconfig = pulumi.all([serviceAccountSecret.data, serviceAccountSecret.type]).apply(([data, type]) => { if (type !== "kubernetes.io/service-account-token") { throw new Error("Expected token type kubernetes.io/service-account-token"); } // Decode the token from base64. Service Account tokens are stored in secrets base64-encoded. const token = Buffer.from(data.token, 'base64').toString(); // Construct a kubeconfig that uses this token for authentication return `apiVersion: v1 clusters: - cluster: server: https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT} certificate-authority-data: ${data["ca.crt"]} name: k8s contexts: - context: cluster: k8s user: pulumi-service-account name: pulumi-service-account-context current-context: pulumi-service-account-context kind: Config preferences: {} users: - name: pulumi-service-account user: token: ${token}`; }); // Use the kubeconfig for deploying resources const provider = new k8s.Provider("provider", { kubeconfig: kubeconfig, }); // You can use the provider to manage Kubernetes resources. For example, let's create a namespace. const ns = new k8s.core.v1.Namespace("app-namespace", { metadata: { name: "my-app" } }, { provider }); // Export the namespace name export const namespaceName = ns.metadata.name;
In this program, we're creating a Kubernetes Service Account and then using the service account's token to set up the Pulumi Kubernetes Provider. The
kubeconfig
is built programmatically, which includes the service account token to authenticate API requests.Make sure your environment has
KUBERNETES_SERVICE_HOST
andKUBERNETES_SERVICE_PORT
set correctly, which are usually provided when running within a pod in the cluster.Important details to note:
serviceAccount.secrets
: This is an array of secret names associated with the service account, where typically the first item is the JWT token used to authenticate with the Kubernetes API.data.token
: This is the JWT provided by Kubernetes for the service account, which you'll use to authenticate your requests.process.env.KUBERNETES_SERVICE_HOST
andprocess.env.KUBERNETES_SERVICE_PORT
: These are environment variables available inside a Kubernetes cluster that provide the API server address. When running this outside of the cluster, you should replace these with the appropriate values for your Kubernetes API server.
The program concludes by exporting the namespace name, demonstrating how you could deploy further resources using the
provider
with service account-based authentication.