Using external issuer certificates

As already explained in theAutomatic mTLS section, Linkerdstores the trust root, certificate and private key in a Kubernetes secret.The contents of this secret are used by the identity service to sign thecertificate signing requests (CSR)that are issued by the proxy. The trust root, certificates and private keycan either be generated automatically by the CLI upon installation or canbe supplied by the user. If the latter is true, the necessity for providingthe user with more control over the life cycle of these credential arises.In order to do that Linkerd edge-19.10.5introduces the functionality to read and continuously monitor Kubernetessecrets for certificates change and to auto-reload the identity component'sin-memory issuer certificate. In the following lines, we will demonstrate howthis allows integration with the external certificate management solutioncert-manager.

Prerequisites

You need to have cert-manager installed and running on your cluster. Thisis the software that will take care of creating and updating the certificatesand writing them into a secret of your choice. In order to install that on yourcluster follow theInstalling on Kubernetessection of the docs. You also need to have a signing key pair that will be usedby the cert manager Issuer to generate signed certificates. SeeGenerating the certificates with stepfor examples on how to create the CA trust root. All certificates must use theECDSA P-256 algorithm.

Create the namespace that Linkerd will reside in

As cert-manager issuers are namespace based, the linkerd namespace needs toexist beforehand. This is where the rest of the cert-manager specific toLinkerd (but not part of its installation) resources need to live. For thatpurpose you can execute the following command:

  1. kubectl create namespace linkerd

Save the signing key pair as a Secret

To allow the Issuer to reference the signing key pair, it needs to be stored ina Kubernetes secret, created in the linkerd namespace. Let's name itlinkerd-trust-anchor and use step to generate certificates and store themin the secret:

  1. step certificate create identity.linkerd.cluster.local ca.crt ca.key \
  2. --profile root-ca --no-password --insecure &&
  3. kubectl create secret tls \
  4. linkerd-trust-anchor \
  5. --cert=ca.crt \
  6. --key=ca.key \
  7. --namespace=linkerd

Create an Issuer referencing the secret

Now that we have the secret in place, we can create an Issuer thatreferences it:

  1. cat <<EOF | kubectl apply -f -
  2. apiVersion: cert-manager.io/v1alpha2
  3. kind: Issuer
  4. metadata:
  5. name: linkerd-trust-anchor
  6. namespace: linkerd
  7. spec:
  8. ca:
  9. secretName: linkerd-trust-anchor
  10. EOF

As an alternative to Issuer you can use a ClusterIssuer. In order to avoidover-permissive RBAC settings we recommend to use the former.

Issuing certificates and writing them to a secret

We can now create a Certificate resource which will specify the desiredcertificate:

  1. cat <<EOF | kubectl apply -f -
  2. apiVersion: cert-manager.io/v1alpha2
  3. kind: Certificate
  4. metadata:
  5. name: linkerd-identity-issuer
  6. namespace: linkerd
  7. spec:
  8. secretName: linkerd-identity-issuer
  9. duration: 24h
  10. renewBefore: 1h
  11. issuerRef:
  12. name: linkerd-trust-anchor
  13. kind: Issuer
  14. commonName: identity.linkerd.cluster.local
  15. isCA: true
  16. keyAlgorithm: ecdsa
  17. usages:
  18. - cert sign
  19. - crl sign
  20. - server auth
  21. - client auth
  22. EOF

Once this resource is in place cert-manager will attempt to use it to obtaina certificate. If successful this operation will result in the certificatebeing stored in a secret named linkerd-identity-issuer. This certificate willbe valid for 24 hours as specified by the duration key. The renewBefore keyindicates that cert-manager will attempt to issue a new certificate one hourbefore expiration of the current one. In order to see your newly issuedcertificate, you can execute:

  1. kubectl get secret linkerd-identity-issuer -o yaml -n linkerd

Using the certificate in Linkerd

In order to use the externally managed certificates you need to install Linkerdwith the —identity-external-issuer flag. Upon installation instead ofgenerating the trust root and certificates or reading them from a file, the CLIwill fetch them from the linkerd-identity-issuer secret. Furthermore,whenever cert-manager updates the certificate and key stored in the secret, theidentity service will automatically detect this change and reload the newlycreated credentials. In order to monitor this process you can check theIssuerUpdatedevents emitted by the service:

  1. kubectl get events --field-selector reason=IssuerUpdated -n linkerd

NoteLinkerd will work with any secret of type kubernetes.io/tls, containingthe ca.crt, tls.crt and tls.key data fields. The secret must be namedlinkerd-identity-issuer. This allows for the use of other certificatemanagement solutions such as Vault.

Using Helm

Alternatively if you want to install through Helm, you need to make sure thatcert-manager is installed and configured in the linkerd namespace. You canconsult the Customizing the Namespacesection in order to ensure your namespace has all the required labels.When all of that is in place simply supply the trust root that is in yourlinkerd-identity-issuer secret:

  1. helm install \
  2. --name=linkerd2 \
  3. --set-file global.identityTrustAnchorsPEM=<your-trust-roots> \
  4. --set identity.issuer.scheme=kubernetes.io/tls \
  5. --set installNamespace=false \
  6. linkerd/linkerd2

NoteIts important that global.identityTrustAnchorsPEM matches the value ofca.crt in your linkerd-identity-issuer secret