Private CAs in Kubernetes with 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
-
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
-
Create the
cert-manager.values.yaml
for storing the configuration values:touch cert-manager.values.yaml
-
Update the configuration to have the CRDs installed and Gateway API enabled:
crds: enabled: true
-
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/
-
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
-
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
-
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
-
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.