Private CAs in Kubernetes with cert-manager

cert-manager
cert-manager

Introduction

In some cases, you might want to have certificates that cannot be issued by public CAs to use internally, e.g., for database encryption and authentication. You have come to the right place. This tutorial will guide you through creating such private CAs in your Kubernetes cluster.

Prerequisites

  • A Kubernetes cluster.
  • Helm v3.
  • Basic k8s knowledge.

Step-by-step Guide

  1. Create the cert-manager namespace and configure Helm's repository:

    kubectl create ns cert-manager
    namespace/cert-manager created
    
    helm repo add jetstack https://charts.jetstack.io
    "jetstack" has been added to your repositories
    
  2. Create the cert-manager.values.yaml for storing the configuration values:

    touch cert-manager.values.yaml
    
  3. Update the configuration to have the CRDs installed and Gateway API enabled:

    crds:
      enabled: true
    
  4. Release the Helm chart for cert-manager installation:

    helm install cert-manager jetstack/cert-manager \
      --namespace cert-manager \
      --values cert-manager.values.yaml
      
    NAME: cert-manager
    LAST DEPLOYED: Wed Jul 24 10:56:59 2024
    NAMESPACE: cert-manager
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    cert-manager v1.15.1 has been deployed successfully!
    
    In order to begin issuing certificates, you will need to set up a ClusterIssuer
    or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).
    
    More information on the different types of issuers and how to configure them
    can be found in our documentation:
    
    https://cert-manager.io/docs/configuration/
    
    For information on how to configure cert-manager to automatically provision
    Certificates for Ingress resources, take a look at the `ingress-shim`
    documentation:
    
    https://cert-manager.io/docs/usage/ingress/      
    
  5. Create a YAML file (ca.yaml) for the private CA cluster issuers with a Root CA and an intermediate CA:

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: selfsigned-cluster-issuer
    spec:
      selfSigned: {}
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: my-root-ca
      namespace: cert-manager
    spec:
      isCA: true
      duration: 175200h # 20y
      renewBefore: 720h # 30d
      subject:
        organizations:
          - MyOrg
        countries:
          - FI
      commonName: My Root R1
      secretName: my-root-ca-secret
      privateKey:
        algorithm: ECDSA
        size: 384
        rotationPolicy: Always
      issuerRef:
        kind: ClusterIssuer
        name: selfsigned-cluster-issuer
        group: cert-manager.io
    ---
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: my-root-ca-cluster-issuer
    spec:
      ca:
        secretName: my-root-ca-secret
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: my-ca
      namespace: cert-manager
    spec:
      isCA: true
      duration: 87600h # 10 years
      renewBefore: 720h # 30 days
      subject:
        organizations:
          - MyOrg
        countries:
          - FI
      commonName: My CA ECDSA
      secretName: my-ca-secret
      privateKey:
        algorithm: ECDSA
        size: 384
        rotationPolicy: Always
      issuerRef:
        kind: ClusterIssuer
        name: my-root-ca-cluster-issuer
        group: cert-manager.io
    ---
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: my-ca-cluster-issuer
    spec:
      ca:
        secretName: my-ca-secret
    
  6. Apply the private CAs:

    kubectl apply -f ca.yaml
    clusterissuer.cert-manager.io/selfsigned-cluster-issuer created
    certificate.cert-manager.io/my-root-ca created
    clusterissuer.cert-manager.io/my-root-ca-cluster-issuer created
    certificate.cert-manager.io/my-ca created
    clusterissuer.cert-manager.io/my-ca-cluster-issuer created    
    
  7. Now you can use the intermediate CA to issue certificates, e.g mongo.yaml certificate:

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: mongodb
      namespace: cert-manager
    spec:
      secretName: mongodb-tls
      commonName: MongoDB
      duration: 87600h # 10y
      renewBefore: 720h # 30d
      dnsNames:
        - '*.mongodb.svc.cluster.local'
        - '*.mongodb.svc.cluster'
        - '*.mongodb.svc'
        - '*.mongodb'
      issuerRef:
        name: my-ca-cluster-issuer
        kind: ClusterIssuer
    
  8. Create the mongodb certificate:

    kubectl apply -f mongo.yaml 
    certificate.cert-manager.io/mongodb created
    

Conclusion

Private Certificate Authorities (CAs) are essential for internal encryption and authentication in Kubernetes cluster. I hope you find this guide helpful.

References

Comments