Cert-Manager Integration
The Cert-Manager backend is experimental, and subject to change. |
Cert-Manager is a common tool to manage certificates in Kubernetes, especially when backed by an external Certificate Authority (CA) such as Let's Encrypt.
The Stackable Secret Operator supports requesting certificates from Cert-Manager.
Caveats
Cert-Manager is designed to manage relatively long-lived certificates that are stored in Kubernetes Secrets. By contrast, the Stackable Secret Operator is designed to generate temporary short-lived certificates.
This has a couple of repercussions:
-
Longer-lived certificates mean that a leaked certificate has potential to be abused for longer.
-
Application teams may have access to read Secrets in their respective applications' Namespaces.
Where possible, we recommend using the autoTls
backend instead.
Configuring Cert-Manager
We recommend using the autoTls backend instead for self-signed PKIs. We use Cert-Manager’s CA issuer here to show the broader concepts.
|
To do this, you will first need to teach Cert-Manager how to create your certificates.
In a production setup this will likely use an external CA such as ACME or OpenBao/Vault. However, to make this guide self-contained, Cert-Manager will create a self-signed CA certificate instead.
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: secret-operator-demonstration (1)
spec:
ca:
secretName: secret-operator-demonstration-ca
# Create a self-signed CA for secret-operator-demonstration to use
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: secret-operator-demonstration-ca
spec:
secretName: secret-operator-demonstration-ca
isCA: true
commonName: Stackable Secret Operator/Cert-Manager Demonstration CA
issuerRef:
kind: Issuer
name: secret-operator-demonstration-ca
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: secret-operator-demonstration-ca
spec:
selfSigned: {}
1 | This is the Issuer that our created certificates will reference later |
Creating a SecretClass
The Stackable Secret Operator needs to know how to request the certificates from Cert-Manager. We do this by creating
a SecretClass
using the experimentalCertManager
backend.
---
apiVersion: secrets.stackable.tech/v1alpha1
kind: SecretClass
metadata:
name: tls-cert-manager (1)
spec:
backend:
experimentalCertManager:
issuer:
kind: Issuer (2)
name: secret-operator-demonstration (3)
1 | Both certificates and Pods will reference this name, to ensure that the correct certificates are found |
2 | This guide uses a namespaced Issuer, rather than a cluster-scoped ClusterIssuer |
3 | The Cert-Manager Issuer that should sign these certificates, as created before |
Using the certificate
Finally, we can create and expose a Pod that requests and uses the certificate!
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: tls
mountPath: /tls
- name: config
mountPath: /etc/nginx/conf.d
ports:
- name: https
containerPort: 443
volumes:
- name: tls (1)
ephemeral:
volumeClaimTemplate:
metadata:
annotations:
secrets.stackable.tech/class: tls-cert-manager (2)
secrets.stackable.tech/scope: node,service=my-app (3)
spec:
storageClassName: secrets.stackable.tech
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "1"
- name: config
configMap:
name: my-app
--- (4)
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app
data:
default.conf: |
server {
listen 443 ssl;
ssl_certificate /tls/tls.crt;
ssl_certificate_key /tls/tls.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
--- (5)
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
ports:
- name: https
port: 443
1 | A secret volume is created, where the certificate will be exposed to the app |
2 | The volume references the SecretClass defined before |
3 | The app requires the certificate to be valid for the scopes node and service=my-app |
4 | nginx is configured to use the mounted certificate |
5 | nginx is exposed as a Kubernetes Service |