1. Configuring Vault to sign Kubernetes CSR for mTLS

    TypeScript

    Mutual TLS (mTLS) is an authentication method that ensures that traffic between two parties is both secure and trusted in both directions. To set up mTLS in Kubernetes, you may want to use Vault by HashiCorp as a certificate manager to issue and sign certificates.

    The general steps to configure Vault to sign Kubernetes Certificate Signing Requests (CSRs) for mTLS typically involve:

    1. Setting up a Certificate Authority (CA) in Vault.
    2. Configuring Kubernetes to use Vault as a CA.
    3. Creating roles in Vault that define the permissions and policies for certificate signing.
    4. Generating CSR in Kubernetes and sending it to Vault for signing.
    5. Applying the signed certificate back in Kubernetes.

    Here's how you can use Pulumi to automate these steps:

    1. Vault PKI Secret Engine: Enables and configures the PKI secret engine in Vault to issue certificates.

    2. Vault Roles for CSR Signing: Creates the roles in Vault’s PKI engine with specific roles that include policies defining which domains and common names may be signed.

    3. Kubernetes Certificates: Using Pulumi’s Kubernetes provider, you can automate the process of creating CSRs and managing certificates within the cluster.

    4. Pulumi Vaults Provider: To interact with Vault, you'll use the Pulumi Vault provider which allows you to manage Vault resources.

    The Pulumi program example below demonstrates how to use Pulumi's Vault provider to set up a PKI secret engine and how to use the Kubernetes provider to create a CSR. Note that this example assumes you have already set up and configured Vault with the appropriate policies and access, and that you're familiar with Vault’s authentication mechanisms.

    import * as vault from "@pulumi/vault"; import * as kubernetes from "@pulumi/kubernetes"; // Step 1: Enable and configure the PKI secret engine const pkiSecretBackend = new vault.Mount("pki", { path: "pki", type: "pki", description: "PKI backend to issue certificates", }); // Tune the PKI secret engine. const pkiSecretBackendConfig = new vault.pkiSecret.BackendConfig("pkiConfig", { backend: pkiSecretBackend.path, defaultLeaseTtlSeconds: 31536000, // 1 year maxLeaseTtlSeconds: 63072000, // 2 years }); // Step 2: Configure roles that define policies for certificate signing const roleName = "example-role"; const certRole = new vault.pkiSecret.SecretBackendRole(roleName, { backend: pkiSecretBackend.path, allowedDomains: ["example.com"], allowSubdomains: true, maxTtlSeconds: 31536000, name: roleName, }); // Step 3: Create a CSR in Kubernetes const privateKey = new kubernetes.certificates.v1.CertificateSigningRequest("privateKey", { metadata: { name: "example-csr" }, spec: { request: "<base64-encoded-csr>", // Base-64 encode your CSR data signerName: "kubernetes.io/kubelet-serving", usages: ["digital signature", "key encipherment", "server auth"], }, }); // Assume the CSR is approved elsewhere and the status is set to 'Approved'. Now we can use Vault to sign the CSR. // Using the `vault.pkiSecret.SecretBackendSign` resource, you can sign CSR by using 'vault.pkiSecret.SecretBackendSign' /* You would need to extract the CSR status from the above resource and use it for the signing process. Currently, it's manual due to the lack of imperative logic in Pulumi, so the CSR needs to be approved and its status fetched before this part can be executed. */ const signedCert = new vault.pkiSecret.SecretBackendSign(roleName, { backend: pkiSecretBackend.path, commonName: "example.com", // Common name to be signed csr: "<base64-encoded-csr>", name: roleName, // Role name that we created for signing format: "pem", ttl: "24h", }); // The above CSR needs to be Base-64 encoded and the signing request is sent to Vault. // Once signed, you can then use the resulting certificate in your Kubernetes configuration. /* Important: The code above is not a complete working example. You need to replace placeholders with actual values, such as "<base64-encoded-csr>" with your actual CSR data. Additionally, certificate signing involves sensitive operations, so make sure you have proper error handling and security measures in place. The example focuses on illustrating the Pulumi resources interaction and may require adjustments for real-world scenarios. */ // Export the name of the certificate role export const certificateRoleName = certRole.name;

    The code above outlines how to configure a Vault backend for PKI, create a role for signing, and initiate a certificate signing request using Pulumi. You will need to ensure that necessary authentication to Vaults and Kubernetes APIs is handled outside of this code snippet, for example by setting up the correct environment variables or kubeconfig files that Pulumi can use to authenticate.

    You should replace <base64-encoded-csr> with the actual base64-encoded CSR that you have generated according to your needs. Also, this is a simplified version of the actual process and assumes you have already had a signed and approved CSR within Kubernetes.

    Let's go over the resources being used:

    • vault.Mount: This enables a new secret backend at the specified path and of the type 'pki'. This provides a space in Vault where the PKI engine can store and sign certificates.

    • vault.pkiSecret.BackendConfig: Configures default and max TTLs for the tokens/certificates issued from the PKI backend.

    • vault.pkiSecret.SecretBackendRole: Defines a role that sets the permissions and domains for signing. You'd authorize specific common names and domains that this role can sign.

    • kubernetes.certificates.v1.CertificateSigningRequest: Represents a CSR in Kubernetes. You're creating such a request that needs to be signed by Vault to be used in the mTLS communication within Kubernetes.

    • vault.pkiSecret.SecretBackendSign: A resource for signing a pre-created CSR that matches Vault policies for the specified role.

    Remember, this is an infrastructure as code approach to setting up mTLS on Kubernetes using Vault. This means that once you've written the Pulumi code, you can apply it across your environments consistently, with version control, automated testing, and more benefits of a software development workflow.