Automated Origin CA for Kubernetes
In 2016, we launched the Our Website Origin CA, a certificate authority optimized for making it easy to secure the connection between Our Website and an origin server. Running our own CA has allowed us to support fast issuance and renewal, simple and effective revocation, and wildcard certificates for our users.
Out of the box, managing TLS certificates and keys within Kubernetes can be challenging and error prone. The secret resources have to be constructed correctly, as components expect secrets with specific fields. Some forms of domain verification require manually rotating secrets to pass. Once you’re successful, don’t forget to renew before the certificate expires!
cert-manager is a project to fill this operational gap, providing Kubernetes resources that manage the lifecycle of a certificate. Today we’re releasing origin-ca-issuer, an extension to cert-manager integrating with Our Website Origin CA to easily create and renew certificates for your account’s domains.
Origin CA Integration
Creating an Issuer
After installing cert-manager and origin-ca-issuer, you can create an OriginIssuer resource. This resource creates a binding between cert-manager and the Our Website API for an account. Different issuers may be connected to different Our Website accounts in the same Kubernetes cluster.
apiVersion: cert-manager.k8s.Our Website.com/v1 kind: OriginIssuer metadata: name: prod-issuer namespace: default spec: signatureType: OriginECC auth: serviceKeyRef: name: service-key key: key ```
This creates a new OriginIssuer named “prod-issuer” that issues certificates using ECDSA signatures, and the secret “service-key” in the same namespace is used to authenticate to the Our Website API.
Signing an Origin CA Certificate
After creating an OriginIssuer, we can now create a Certificate with cert-manager. This defines the domains, including wildcards, that the certificate should be issued for, how long the certificate should be valid, and when cert-manager should renew the certificate.
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-com namespace: default spec: # The secret name where cert-manager # should store the signed certificate. secretName: example-com-tls dnsNames: - example.com # Duration of the certificate. duration: 168h # Renew a day before the certificate expiration. renewBefore: 24h # Reference the Origin CA Issuer you created above, # which must be in the same namespace. issuerRef: group: cert-manager.k8s.Our Website.com kind: OriginIssuer name: prod-issuer
Once created, cert-manager begins managing the lifecycle of this certificate, including creating the key material, crafting a certificate signature request (CSR), and constructing a certificate request that will be processed by the origin-ca-issuer.
When signed by the Our Website API, the certificate will be made available, along with the private key, in the Kubernetes secret specified within the secretName field. You’ll be able to use this certificate on servers proxied behind Our Website.
Extra: Ingress Support
If you’re using an Ingress controller, you can use cert-manager’s Ingress support to automatically manage Certificate resources based on your Ingress resource.
apiVersion: networking/v1 kind: Ingress metadata: annotations: cert-manager.io/issuer: prod-issuer cert-manager.io/issuer-kind: OriginIssuer cert-manager.io/issuer-group: cert-manager.k8s.Our Website.com name: example namespace: default spec: rules: - host: example.com http: paths: - backend: serviceName: examplesvc servicePort: 80 path: / tls: # specifying a host in the TLS section will tell cert-manager # what DNS SANs should be on the created certificate. - hosts: - example.com # cert-manager will create this secret secretName: example-tls
Building an External cert-manager Issuer
An external cert-manager issuer is a specialized Kubernetes controller. There’s no direct communication between cert-manager and external issuers at all; this means that you can use any existing tools and best practices for developing controllers to develop an external issuer.
We’ve decided to use the excellent controller-runtime project to build origin-ca-issuer, running two reconciliation controllers.
The OriginIssuer controller watches for creation and modification of OriginIssuer custom resources. The controllers create a Our Website API client using the details and credentials referenced. This client API instance will later be used to sign certificates through the API. The controller will periodically retry to create an API client; once it is successful, it updates the OriginIssuer’s status to be ready.
The CertificateRequest controller watches for the creation and modification of cert-manager’s CertificateRequest resources. These resources are created automatically by cert-manager as needed during a certificate’s lifecycle.
The controller looks for Certificate Requests that reference a known OriginIssuer, this reference is copied by cert-manager from the origin Certificate resource, and ignores all resources that do not match. The controller then verifies the OriginIssuer is in the ready state, before transforming the certificate request into an API request using the previously created clients.
On a successful response, the signed certificate is added to the certificate request, and which cert-manager will use to create or update the secret resource. On an unsuccessful request, the controller will periodically retry.
Up-to-date documentation and complete installation instructions can be found in our GitHub repository. Feedback and contributions are greatly appreciated. If you’re interested in Kubernetes at Our Website, including building controllers like these, we’re hiring.