title | authors | reviewers | approvers | editor | creation-date | last-updated | status | |||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Certificate Renewal |
|
|
|
@joshvanl |
2019-09-14 |
2019-09-20 |
implementable |
The goal of the cert-manager-csi driver is to provide a seamless integration of cert-manager with deployments in Kubernetes. Instead of specifying additional cert-manager resources alongside deployments, cert-manager-csi facilitates specifying in-line volume mount certificate attributes that are honoured by the driver. This reduces complexity for end users and moves cert-manager resource management onto the driver itself.
Certificates expire and a well defined PKI infrastructure expects rotation of these certificates reliably, when necessary.
Since certificates do and should expire, a certificate management tool is reasonably expected to handle certificate rotation. It is the responsibility of the cert-manager-csi driver to implement renewal of certificates that have been created through the in-line volume mount.
- Specify a standard for the directory tree of the target data directory that is used to mount volumes to pods.
- Specify a metadata file that is used to discover existing certificates.
- Implement watchers to wait for a specified period before marking these certificates for renewal.
- Implement a renewal process for rotating certificates for the target pod.
- Reliably rediscover node certificates in the event of a driver restart on a node.
- Expose options for configuring the renewal process on a volume by volume basis (disabling rotation, use the same private key, renew before duration).
- Require additional changes to upstream cert-manager to facilitate renewal.
- Rely on the use of cert-manager's
Certificate
resource to facilitate renewal functionality.
In order to reliably discover and manage certificates for writing and watching, the directory structure needs to be consistent and deterministic for the driver. The main data directory will house multiple directories, each responsible for housing volume metadata as well as the mount point itself. It is possible that this main data directory contains other data created which should be successfully ignored by the driver.
Each volume directory is named using the format of:
cert-manager-csi-$POD_NAMESPACE-$POD_NAME-$VOLUME_ID
This naming scheme ensures full namespacing of directory names whereby even if a single pod contains multiple cert-manager-csi volume mounts, each volume ID is ensured to be unique in this location. If anything external has created a directory name and causes a conflict, the driver should fail to create the volume until it has been resolved.
Inside the pod directory contains the metadata file of the volume as well as the mount directory. Although the mount directory can have any child directory structure since a user can specify the key and certificate location, typically the directory will only contain 3 files at its root containing the key, certificate, and CA if available.
/cert-manager-csi-$POD_NAMESPACE-$POD_NAME-$VOLUME_ID/
-- /metadata.json
-- /data/
---- /ca.pem
---- /crt.pem
---- /key.pem
In order to retain information about the volume attributes, even if the driver has been restarted, data needs to be persisted on local storage. If this method was not taken, we would require to query the API server for all pods in the cluster, then sort the pods that have a cert-manager-csi volume attached and match by node. By keeping a local store, we eliminate our need for API server accesses to pods and reduce complexity. Volume mount attributes are immutable so the data shall not change during a pod's life cycle.
The contents of the meta data includes the volume attributes
map[string]string
, the volume ID and target path. With this a full recreation
of the information for each volume can be made.
The file will be stored as a .json
file type. This is a widely used and
understood file type and Go has good support for converting to and from Go
structs and Json string.
Each volume on the driver node will have its own long running Go routine that
waits for the certificate to be ready for renewal. The default renew before
duration will be the same used as in the cert-manager API (30 days). This
option can be changed using a volume attribute
csi.certmanager.k8s.io/renew-before
that takes a Go time duration string.
Once the Go routine has reached this duration, the certificate should be marked for renewal and trigger a re-fetch of a certificate.
If the volume is unpublished (pod deleted), then the corresponding Go routine should also be killed.
The Go routine can be prevented, and as such renewal not to take place, via the
volume attribute csi.certmanager.k8s.io/disbale-auto-renew
set to true
.
Once a certificate has been marked for renewal, the driver will attempt to
discover if an existing cert-manger CertificateRequest
exists. If so, the
driver should delete it. A new private key will not be created if the volume
attribute csi.certmanager.k8s.io/reuse-private-key
is set to true
.
The driver then creates the CertificateRequest
the same way and retrieves the
new signed certificate. Once complete, the files are written to the mount
directory, overriding the previous files.
On start, the driver should perform a local discovery on the data directory to find any existing volume mounts. Upon finding each meta data file, the Go routine watchers should be rebuilt to be ready to mark them for renewal.
Attribute | Description | Default | Example |
---|---|---|---|
csi.certmanager.k8s.io/renew-before | Time duration to attempt a renewal of the certificate. | 30d | 24h |
csi.certmanager.k8s.io/disable-auto-renew | Disable auto-renewing this certificate. | false | true |
csi.certmanager.k8s.io/reuse-private-key | Reuse the same private key when renewing the certificate. | false | true |
With the inclusion of more volume attribute options, more validation needs to be written to ensure they are sane and compatible values.
Implement end to end tests to ensure renewal is successful and complient with this design document.
- If other data exists in the data directory then the driver should be able to successfully ignore this data.
- If requesting the certificate was successful but the volume has not yet been mounted, the driver should be able to detect this and attempt to mount the volume.