13 KiB
certificates.k8s.io Adoption
Table of Contents
Summary
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.
Motivation
Third Party Projects
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.
Security
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).
cert-manager Webhook Dependency
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.
CertificateSigningRequest Migration Path
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.
Goals
- Add
CertificateSigningRequestsigner controllers to cert-manager for allIssuertypes - Pave a way for replacement of the
CertificateRequestresource forCertificateSigningRequest
Non-Goals
- Remove the
CertificateRequestresource beforeCertificateSigningRequestis fully supported and a migration path is in place
Reasons for Approach
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.
Read all access to CertificateSigningRequests
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.
Namespaced issuers referenced by CertificateSigningRequest
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
Duration Field
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 whose 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 fall back to this annotation.
CA Field
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.
External Issuers
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.
Proposal
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.
Signers
Some special cases for some [Cluster]Issuers that need to be addressed:
-
SelfSigned: The
experimental.cert-manager.io/private-key-secret-nameannotation 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-fieldsannotation is set by the user to request a Venafi certificate with custom fields. - The
venafi.experimental.cert-manager.io/pickup-idannotation 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). SinceCertificateSigningRequestsare cluster scoped resources, when referencing a ClusterIssuer we should create Orders in the cluster resource namespace, else the namespace of the referenced Issuer.
Conditions
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.
API Changes
-
IsCA: The
experimental.cert-manager.io/request-is-caannotation is used to request a certificate with the X.509IsCAflag set. -
Duration: The
experimental.cert-manager.io/request-durationannotation 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
Upgrading
No effect to upgrades as only additional controllers added. No CRD API changes.
Graduation
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
CertificateRequestsare the resource created fromCertificateresources. -
[TBD] Swap
CertificateRequestsforCertificateSigningRequestsas the resource created fromCertificates. -
[TBD] Remove the
CertificateRequestresource from the cert-manager project, in favour of theCertificateSigningRequestresource.