---
title: certificates.k8s.io Adoption
authors:
- "@joshvanl"
reviewers:
- "@joshvanl"
approvers:
- "@munnerz"
- @jetstack/team-cert-manager
editor: "@joshvanl"
creation-date: 2021-02-09
last-updated: 2021-07-26
status: implemented
---
In Kubernetes v1.19 the
CertificateSigningRequest
resource graduated to certificates.k8s.io/v1
. This makes the concept of
requesting, signing, and consuming certificates in Kubernetes first-class
objects. cert-manager is well placed to serve this resource type as it becomes
more popular in the wider community, whilst preserving all the features and
extensions that cert-manager has to offer.
With the extensiveness of cert-manager’s ecosystem, it is well placed to manage the core Kubernetes resource type. This gives cert-manager the ability to integrate with components that it otherwise wouldn't have, without changes to the third-party project.
Having the "request" resource managed inside the API server has a better
security profile (i.e. UserInfo
fields are managed by the API server rather
than a configurable webhook,
see).
Consumers of the certificates.k8s.io CertificateRequest
do not require
cert-manager as a hard dependency. cert-manager can cause issues with the order
of operation scenarios during installation or upgrades. For example, the
CertificateRequest
resource needs to be installed and the webhook ready for
consumers/clients of this API to make requests.
In some set-ups, the cert-manager installation is handled by two separate teams:
- The cert-manager CRDs and webhook are installed and managed by the operations team, which allows the operations team to enforce cluster policies;
- The cert-manager controller, cainjector and acmesolver are installed and managed by the developer team.
By supporting the built-in CertificateSigningRequest
resource, we decrease the
coupling between the operations team and the developer team. Since the
CertificateSigningRequest
resource is built-in, it does not need any
CustomResourceDefinition
installation, and the webhook for this resource is
integrated to the API server.
Support for the CertificateSigningRequest
resource in cert-manager is a
stepping stone to migrating to this resource instead of the CertificateRequest
resource, if the project does indeed want to migrate.
- Add
CertificateSigningRequest
signer controllers to cert-manager for allIssuer
types - Pave a way for replacement of the
CertificateRequest
resource forCertificateSigningRequest
- Remove the
CertificateRequest
resource beforeCertificateSigningRequest
is fully supported and a migration path is in place
Below are a summary of properties of the CertificateSigningRequest
which
cause issues or caveats which need to be addressed when adding support for the
resource.
CertificateSigningRequests
are cluster scoped resources, whereas
CertificateRequests
are not. This means that in order for users to have the
same debugging and usage capabilities of the CertificateRequest
, users will
have the ability to list all requests in the cluster, rather than being scoped to
specific namespaces. This is a regression in certificate privacy.
Whilst this is a regression in privacy, it could be an accepted limitation where the real world consequences are minimal.
CertificateSigningRequests
are cluster scoped resources, whereas
CertificateRequests
are not. cert-manager has the concept of namespaced
issuers that may only be referenced by CertificateRequests
that reside in
the same namespace. Since CertificateSigningRequests
can reference any
namespaced Issuer
, there must be some mechanism to prevent privilege
escalation (Alice references an issuer in Bob's namespace).
cert-manager will enforce an
RBAC noun and
verb whereby the requester must have this role bound to them in order for the
CertificateSigningRequest
referencing a namespaced Issuer
be approved by the
cert-manager controller. See here.
This will be done via a
SubjectAccessReview
against the UserInfo
fields on the CertificateSigningRequest
. The user must
hold the following permissions to reference a namespaced signer:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-referencer:my-issuer
namespace: sandbox
rules:
- apiGroups: ["cert-manager.io"]
resources: ["signers"]
verbs: ["reference"]
resourceNames:
- "my-issuer" # To give permission to _only_ reference Issuers with the name 'my-issuer'
- "*" # To give permission to reference Issuers with any name in this namespace
Until 1.22
CertificateSigningRequests
did not include a duration
field. To have parity
with the CertificateRequest
resource, the duration field will be moved to the
annotation experimental.cert-manager.io/request-duration
who's value is a Go
time duration string.
When 1.22 is released, cert-manager can optimistically read the
expirationSeconds
CertificateSigningRequest
field to discover the requested
duration. If this field hasn't been set or the user is using an older version of
Kubernetes, cert-manager can fallback to this annotation.
CertificateSigningRequests
do not include a ca
field. This field has been
proven to be problematic in cert-manager and controversial as it can encourage
TLS anti-patterns. Attempting to add a ca
style field to
CertificateSigningRequests
in the form of an annotation also causes issues in
controller reconciliation, since updating the status and metadata fields are
separate endpoints; if a successful status update occurs but the annotation
update fails, the CertificateSigningRequest
is left in a bad state with no way
of recovery.
For these reasons, the ca
field has been omitted with no intention of
including it. Users are advised to share CA data out of band to the
CertificateSigningRequest
resource.
All current external
issuers are built for the
CertificateRequest
resource. The project should continue to support this
resource indefinitely, and provide an example project for creating external
signers if and when the migration to CertificateSigningRequests
occurs.
cert-manager will support both CertificateRequest
and
CertificateSigningRequest
types until, and if, the project completely migrates
to the CertificateSigningRequest
resource. The Certificates
controller will
continue to create CertificateRequest
resources. The Certificates
controller
could be changed in future to be optionally configured to create
CertificateSigningRequests
.
The cert-manager controller will not enable the CertificateSigningRequest
controllers unless the ExperimentalCertificateSigningRequestControllers=true
environment variable is present on the cert-manager controller. This could be
changed in future by optimistically discovering whether the
CertificateSigningRequest
resource is available and starting the controllers.
Instead of the concept of an IssuerRef
for CertificateRequests
,
CertificateSigningRequests
have the concept of a SignerName
. Since
CertificateSigningRequests
are cluster scoped resources, the signer name must
include the namespace if the referenced Issuer
is namespaced. The signer name
for cert-manager signers will be prefixed with cert-manager.io
to prevent
conflicts with other external signer projects.
# Namespaced issuer reference
# e.g. `issuers.cert-manager.io/my-namespace.my-issuer
signerName: issuers.cert-manager.io/<namespace>.<issuer-name>
# Cluster scoped issuer reference
# e.g. `clusterissuers.cert-manager.io/my-issuer
signerName: clusterissuers.cert-manager.io/<clusterissuer-name>
Using the same approach of referencing by just name, rather than issuer type
(e.g. CA, Vault etc.), keeps the behaviour of this resource in line with
CertificateRequests
for end users.
Each CertificateSigningRequest
controller will behave in the same way as the
existing CertificateRequest
resource, by getting the referenced signer, and
attempting to sign. If the issuer type is not managed by this controller, do
nothing, else sign.
Some special cases for some [Cluster]Issuers
that need to be addressed:
-
SelfSigned: The
experimental.cert-manager.io/private-key-secret-name
annotation is used to reference a secret containing the private key of the self-signed certificate. The Secret must reside in either the namespace of the reference Issuer, or the cluster resource namespace in the case of a ClusterIssuer. -
Venafi:
- The
venafi.experimental.cert-manager.io/custom-fields
annotation is set by the user to request a Venafi certificate with custom fields. - The
venafi.experimental.cert-manager.io/pickup-id
annotation is used by the cert-manager Venafi signer to keep track of the request against the Venafi API.
- The
-
ACME: The ACME controller creates sub-resources (
Orders
). SinceCertificateSigningRequests
are cluster scoped resources, when referencing a ClusterIssuer we should create Orders in the cluster resource namespace, else the namespace of the referenced Issuer.
The CertificateSigningRequest
has well-known condition
types
of Approved
, Denied
, and Failed
. CertificateSigningRequest
signer
controllers should not begin computation of the request until the resource has
the Approved
condition set to True
.
It was found that nearly all users testing out these signers forgot about
needing to manually add the Approved condition. An event is fired on
CertificateSigningRequest
which have neither a Denied or Approved condition.
This is to aid consumers in knowing that the resource has been observed, but
is waiting for the Approved condition.
If a signer fails when processing a CertificateSigningRequest
, the well-known
Failed
condition should be set to True
. No signer controllers should process
the request again.
When the request has been successfully signed, the status.Certificate
field
will be updated with the sign certificate.
-
IsCA: The
experimental.cert-manager.io/request-is-ca
annotation is used to request a certificate with the X.509IsCA
flag set. -
Duration: The
experimental.cert-manager.io/request-duration
annotation is used to request a certificate with a particular duration. Accepts a Go time duration string. -
Namespaced issuers: requesters must have the following RBAC in the same namespace to allow them to request from a namespaced issuer:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-referencer:my-issuer
namespace: sandbox
rules:
- apiGroups: ["cert-manager.io"]
resources: ["signers"]
verbs: ["reference"]
resourceNames:
- "my-issuer" # To give permission to _only_ reference Issuers with the name 'my-issuer'
- "*" # To give permission to reference Issuers with any name in this namespace
No effect to upgrades as only additional controllers added. No CRD API changes.
Below is each level of graduation for support of CertificateSigningRequest
in
cert-manager.
-
Create signer implementations for each cert-manager.io issuer types. These controllers are active in a default cert-manager installation, though
CertificateRequests
are the resource created fromCertificate
resources. -
[TBD] Swap
CertificateRequests
forCertificateSigningRequests
as the resource created fromCertificates
. -
[TBD] Remove the
CertificateRequest
resource from the cert-manager project, in favour of theCertificateSigningRequest
resource.