Secure HTTP communication is popularly achieved through TLS certificates. These certificates can be to validate the server (https://your-bank.com) or both parties involved in the communication (https://amount-sender.com and https://amount-receiver.com) which is commonly known as Mutual TLS (mTLS). mTLS is not common in web browsers but is used in service-to-service communication models.
To keep things secure, these certificates have a life-time and needs renewal upon expiry
In kubernetes for example kublet
authenticates with kube-api-server
through mTLS. The certificates come from within kubernetes control plane itself and a new one is issued for every new node that joins. For it's internal purposes there is a CertificateSigningRequest object provided, but it is not flexible enough to be used by workloads themselves.
Cert-manager
Cert-manager is a general purpose x509 certificate management tool for Kubernetes.
- It can be used as a standard Certificate Authority (CA).
- It can also work with other well known CAs like Hashicorp Vault and LetsEncrypt.
- It can generate self-signed certificates
- It can inject certificates into workloads automatically through annotations
- It can handle certificate rotation
Installation
❯ helm repo add jetstack https://charts.jetstack.io "jetstack" has been added to your repositories ❯ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "jetstack" chart repository Update Complete. ⎈Happy Helming!⎈ ❯ helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.9.1 \ --set installCRDs=true NAME: cert-manager LAST DEPLOYED: Mon Sep 19 08:45:10 2022 NAMESPACE: cert-manager STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: cert-manager v1.9.1 has been deployed successfully! ... ❯ kubectl get all -n cert-manager NAME READY STATUS RESTARTS AGE pod/cert-manager-85f68f95f-k9f6q 1/1 Running 0 2m19s pod/cert-manager-cainjector-7d9668978d-lrtgn 1/1 Running 0 2m19s pod/cert-manager-webhook-66c8f6c75-hq7lj 1/1 Running 0 2m19s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/cert-manager ClusterIP 10.96.27.186 <none> 9402/TCP 2m19s service/cert-manager-webhook ClusterIP 10.96.27.27 <none> 443/TCP 2m19s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/cert-manager 1/1 1 1 2m19s deployment.apps/cert-manager-cainjector 1/1 1 1 2m19s deployment.apps/cert-manager-webhook 1/1 1 1 2m19s NAME DESIRED CURRENT READY AGE replicaset.apps/cert-manager-85f68f95f 1 1 1 2m19s replicaset.apps/cert-manager-cainjector-7d9668978d 1 1 1 2m19s replicaset.apps/cert-manager-webhook-66c8f6c75 1 1 1 2m19s
Concepts
- Issuer Objects representing CAs that generate certificates as requested through Certificate Signing Requests (CSRs). It is a namespace scoped resource - can issue certifcates valid in the operating namespace scope
- ClusterIssuer Issuer with cluster scope - can issue certificate valid throughout the cluster
- Certificate an object defining a X.509 certificate. This certificate is issued, kept up-to-date through renewal with cert-manager. A certificate issued through
Issuer
is namespace scoped, while the one issued throughClusterIssuer
is valid through the cluster - CertificateRequest a namespaced resource used to request certificate from
Issuer
. It contains a base-64 encoded CSR sent toIssuer
. Upon success, it will return a valid, signed certificate based on the CSR more info
cert-manager supports requesting certificates from ACME servers, including from Let's Encrypt, with use of the ACME Issuer. These certificates are typically trusted on the public Internet by most computers. To successfully request a certificate, cert-manager must solve ACME Challenges which are completed in order to prove that the client owns the DNS addresses that are being requested.
- Order are resources used by the ACME issuer to manage the lifecycle of an ACME 'order' for a signed TLS certificate. It represents a single CSR.
- Challenge are resources are used by the ACME issuer to manage the lifecycle of an ACME 'challenge' that must be completed in order to complete an 'authorization' for a single DNS name/identifier. It is created and managed by the
challenge-controller
more info - cainjector helps fetch CA certificates for webhooks and other API services. It populates the
caBundle
field of four API types:ValidatingWebhookConfiguration
,MutatingWebhookConfiguration
CustomResourceDefinition
andAPIService
. It copies CA data from one of three sources: a KubernetesSecret
, a cert-managerCertificate
, or from the Kubernetes API server CA certificate. Note: If the source is a KubernetesSecret
, that resource MUST also have ancert-manager.io/allow-direct-injection: "true"
annotation.
Example with a self-signed certificate
# assumption: cert-manager is installed and configured as described above # Prepare a namespace ❯ kubectl create ns demo-ns namespace/demo-ns created # Prepare an issuer ❯ cat issuer.yaml --- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-issuer namespace: demo-ns spec: selfSigned: {} # Create ❯ kubectl create -f issuer.yaml issuer.cert-manager.io/selfsigned-issuer created # Verify ❯ kubectl get issuers.cert-manager.io -n demo-ns NAME READY AGE selfsigned-issuer True 17s # Create a Certificate object ❯ cat certificate.yaml --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: sample-certificate namespace: demo-ns spec: secretName: sample-certificate dnsNames: - sample.demo-ns issuerRef: name: selfsigned-issuer # Request for certificate ❯ kubectl create -f certificate.yaml certificate.cert-manager.io/sample-certificate created # Verify ❯ kubectl get certificate -n demo-ns NAME READY SECRET AGE sample-certificate True sample-certificate 10s # Describe the secret ❯ kubectl get secrets/sample-certificate -n demo-ns -o yaml | cut -c -80 apiVersion: v1 data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lRWjFCcU tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lRWjFCc tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBNEdQT kind: Secret metadata: annotations: cert-manager.io/alt-names: sample.demo-ns cert-manager.io/certificate-name: sample-certificate cert-manager.io/common-name: "" cert-manager.io/ip-sans: "" cert-manager.io/issuer-group: "" cert-manager.io/issuer-kind: Issuer cert-manager.io/issuer-name: selfsigned-issuer cert-manager.io/uri-sans: "" name: sample-certificate namespace: demo-ns type: kubernetes.io/tls # Inject secret to a validation webhook ❯ cat val-webhook.yaml --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: test-webhook annotations: cert-manager.io/inject-ca-from-secret: demo-ns/sample-certificate webhooks: - name: test-webhook.example.com admissionReviewVersions: - v1 clientConfig: service: name: test-webhook namespace: demo-ns path: /validate port: 443 sideEffects: None # Instantiate assuming test-webhook is a valid service in demo-ns pointing to port 443 to validate on /validate route ❯ kubectl create -f val-webhook.yaml validatingwebhookconfiguration.admissionregistration.k8s.io/test-webhook created # Verify ❯ kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io NAME WEBHOOKS AGE cert-manager-webhook 1 137m test-webhook 1 6s
Top comments (0)