1. Setting up ProviderConfig to use Kubernetes Service Account for authentication

    TypeScript

    To 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 the kubernetes.core.v1.Secret is used to access the token. We then pass this token to the kubernetes.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 and KUBERNETES_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 and process.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.