Revise CertificateSigningRequest documentation (#19698)

* Revise CertificateSigningRequest approval & rejection details

API clients can deny CSRs. Document this and tidy the page.
"There is currently not a mechanism for a signer implementation to report
its inability to sign a request." seemed misleading; clients can set
status.

* Tidy page

Co-Authored-By: Jordan Liggitt <jordan@liggitt.net>

Co-authored-by: Jordan Liggitt <jordan@liggitt.net>
This commit is contained in:
Tim Bannister
2020-03-19 13:35:23 +00:00
committed by GitHub
parent dac40167ce
commit 0ad51f71e1
@@ -16,6 +16,7 @@ The Certificates API enables automation of
[X.509](https://www.itu.int/rec/T-REC-X.509) credential provisioning by providing
a programmatic interface for clients of the Kubernetes API to request and obtain
X.509 {{< glossary_tooltip term_id="certificate" text="certificates" >}} from a Certificate Authority (CA).
A CertificateSigningRequest (CSR) resource is used to request that a certificate be signed
by a denoted signer, after which the request may be approved or denied before
finally being signed.
@@ -25,29 +26,33 @@ finally being signed.
{{% capture body %}}
## Request signing process
The _CertificateSigningRequest_ resource type allows a client to submit an x509 CSR (`spec.request`)
and request it be signed by a specific _signer_, denoted by the `spec.signerName` field.
The _CertificateSigningRequest_ resource type allows a client to ask for an X.509 certificate
be issued, based on a signing request.
The CertificateSigningRequest object includes a PEM-encoded PKCS#10 signing request in
the `spec.request` field. The CertificateSigningRequest denotes the _signer_ (the
recipient that the request is being made to) using the `spec.signerName` field.
Once created, a CertificateSigningRequest must be approved before it can be signed.
Depending on the signer requested, a CertificateSigningRequest may be auto-approved by a
{{< glossary_tooltip text="controller" term_id="controller" >}}.
Depending on the signer selected, a CertificateSigningRequest may be automatically approved
by a {{< glossary_tooltip text="controller" term_id="controller" >}}.
Otherwise, a CertificateSigningRequest must be manually approved either via the REST API (or client-go)
or via `kubectl certificate approve`. Likewise, a CertificateSigningRequest may also be denied, in which
case the configured signer must not sign the request.
or by running `kubectl certificate approve`. Likewise, a CertificateSigningRequest may also be denied,
which tells the configured signer that it must not sign the request.
Once approved, a signing controller must attempt to sign the request. A signer should apply its own policy
restrictions, similar to the approval process, on the request to ensure it never signs an invalid request.
There is currently not a mechanism for a signer implementation to report its inability to sign a request.
Once the signer has determined that a request should be signed, it must sign the request and store the
resulting certificate (and if appropriate, certificate chain) in the `status.certificate` field as PEM-encoded
certificates.
For certificates that have been approved, the next step is signing. The relevant signing controller
first validates that the signing conditions are met and then creates a certificate.
The signing controller then updates the CertificateSigningRequest, storing the new certificate into
the `status.certificate` field of the existing CertificateSigningRequest object. The
`status.certificate` field is either empty or contains a X.509 certificate, encoded in PEM format.
The CertificateSigningRequest `status.certificate` field is empty until the signer does this.
Once the `status.certificate` field has been populated, the request has been completed and clients can now
fetch the signed certificate PEM data from the CertificateSigningRequest resource.
Signers can instead deny certificate signing if the approval conditions are not met.
In order to reduce the number of old CertificateSigningRequest resources left in a cluster, a garbage collection
controller runs periodically. Depending on the state of the request, it will automatically delete requests older
than a specified duration:
controller runs periodically. The garbage collection removes CertificateSigningRequests that have not changed
state for some duration:
* Approved requests: automatically deleted after 1 hour
* Denied requests: automatically deleted after 1 hour
@@ -55,8 +60,6 @@ than a specified duration:
## Signers
### Signers should define...
All signers should provide information about how they work so that clients can predict what will happen to their CSRs.
This includes:
@@ -65,8 +68,9 @@ This includes:
1. **Permitted x509 extensions**: including IP subjectAltNames, DNS subjectAltNames, Email subjectAltNames, URI subjectAltNames etc, and behavior when a disallowed extension is requested.
1. **Permitted key usages / extended key usages**: any restrictions on and behavior when usages different than the signer-determined usages are specified in the CSR.
1. **Expiration/certificate lifetime**: whether it is fixed by the signer, configurable by the admin, determined by the CSR object etc and behavior if an expiration different than the signer-determined expiration is specified in the CSR.
1. **CA bit allowed/disallowed**: and behavior if a CSR contains a request a for a CA cert when the signer does not permit it.
1. **optional**: Information about the meaning of additional `CERTIFICATE` PEM blocks in `status.certificate`, if different from the standard behavior of treating the additional certificates as intermediates, and presenting them in TLS handshakes.
1. **CA bit allowed/disallowed**: and behavior if a CSR contains a request a for a CA certificate when the signer does not permit it.
Commonly, the `status.certificate` field contains a single PEM-encoded X.509 certificate once the CSR is approved and the certificate is issued. Some signers store multiple certificates into the `status.certificate` field. In that case, the documentation for the signer should specify the meaning of additional certificates; for example, this might be certificate plus intermediates to be presented during TLS handshakes.
### Kubernetes signers
@@ -78,7 +82,7 @@ Kubernetes provides built-in signers that each have a well-known `signerName`:
1. Permitted subjects - no subject restrictions, but approvers and signers may choose not to approve or sign. Certain subjects like cluster-admin level users or groups vary between distributions and installations, but deserve additional scrutiny before approval and signing. The `CertificateSubjectRestriction` admission plugin is available and enabled by default to restrict `system:masters`, but it is often not the only cluster-admin subject in a cluster.
1. Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
1. Permitted key usages - must include []string{"client auth"}. Must not include key usages beyond []string{"digital signature", "key encipherment", "client auth"}
1. Expiration/cert lifetime - minimum of CSR signer or request. Sanity of the time is the concern of the signer.
1. Expiration/certificate lifetime - minimum of CSR signer or request. The signer is responsible for checking that the certificate lifetime is valid and permissible.
1. CA bit allowed/disallowed - not allowed.
1. `kubernetes.io/kube-apiserver-client-kubelet`: signs client certificates that will be honored as client-certs by the
@@ -89,7 +93,7 @@ Kubernetes provides built-in signers that each have a well-known `signerName`:
1. Permitted subjects - organizations are exactly `[]string{"system:nodes"}`, common name starts with `"system:node:"`
1. Permitted x509 extensions - honors key usage extensions, forbids subjectAltName extensions, drops other extensions.
1. Permitted key usages - exactly `[]string{"key encipherment", "digital signature", "client auth"}`
1. Expiration/cert lifetime - minimum of CSR signer or request. Sanity of the time is the concern of the signer.
1. Expiration/certificate lifetime - minimum of CSR signer or request. Sanity of the time is the concern of the signer.
1. CA bit allowed/disallowed - not allowed.
1. `kubernetes.io/kubelet-serving`: signs serving certificates that are honored as a valid kubelet serving certificate
@@ -100,17 +104,17 @@ Kubernetes provides built-in signers that each have a well-known `signerName`:
1. Permitted subjects - organizations are exactly `[]string{"system:nodes"}`, common name starts with `"system:node:"`
1. Permitted x509 extensions - honors key usage and DNSName/IPAddress subjectAltName extensions, forbids EmailAddress and URI subjectAltName extensions, drops other extensions. At least one DNS or IP subjectAltName must be present.
1. Permitted key usages - exactly `[]string{"key encipherment", "digital signature", "server auth"}`
1. Expiration/cert lifetime - minimum of CSR signer or request.
1. Expiration/certificate lifetime - minimum of CSR signer or request.
1. CA bit allowed/disallowed - not allowed.
1. `kubernetes.io/legacy-unknown`: has no guarantees for trust at all. Some distributions may honor these as client
certs, but that behavior is not standard kubernetes behavior.
certs, but that behavior is not standard Kubernetes behavior.
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
1. Trust distribution: None. There is no standard trust or distribution for this signer in a kubernetes cluster.
1. Trust distribution: None. There is no standard trust or distribution for this signer in a Kubernetes cluster.
1. Permitted subjects - any
1. Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
1. Permitted key usages - any
1. Expiration/cert lifetime - minimum of CSR signer or request. Sanity of the time is the concern of the signer.
1. Expiration/certificate lifetime - minimum of CSR signer or request. Sanity of the time is the concern of the signer.
1. CA bit allowed/disallowed - not allowed.
{{< note >}}
@@ -222,16 +226,17 @@ rules:
- sign
```
## Approval/Rejection
## Approval & rejection
### kube-controller-manager auto-approval
### Control plane automated approval {#approval-rejection-control-plane}
The kube-controller-manager ships with a built-in approver for certificates with
a signerName of `kubernetes.io/kube-apiserver-client-kubelet` that delegates various
permissions on CSRs for node credentials to authorization.
It does this by posting SubjectAccessReview resources to the API server.
The kube-controller-manager POSTs SubjectAccessReview resources to the API server
in order to check authorization for certificate approval.
### kubectl-based approver
### Approval & rejection using `kubectl` {#approval-rejection-kubectl}
A Kubernetes administrator (with appropriate permissions) can manually approve
(or deny) CertificateSigningRequests by using the `kubectl certificate
@@ -249,15 +254,15 @@ Likewise, to deny a CSR:
kubectl certificate deny <certificate-signing-request-name>
```
### API-based approver
### Approval & rejection using the Kubernetes API {#approval-rejection-api-client}
Users of the REST API can approve CSRs by submitting an UPDATE request to the `approval`
subresource of the CSR to be approved. For example, you could write an
{{< glossary_tooltip term_id="operator-pattern" text="operator" >}} that watches for a particular
kind of CSR and then sends an UPDATE to approve them.
As part of this request, the `Approved` or `Denied` status condition should be set to the
desired state:
When you make an approval or rejection request, set either the `Approved` or `Denied`
status condition based on the state you determine:
For `Approved` CSRs:
@@ -269,7 +274,7 @@ status:
conditions:
- lastUpdateTime: "2020-02-08T11:37:35Z"
message: Approved by my custom approver controller
reason: ApprovedByMyPolicy # this can be set to anything
reason: ApprovedByMyPolicy # You can set this to any string
type: Approved
```
@@ -283,13 +288,18 @@ status:
conditions:
- lastUpdateTime: "2020-02-08T11:37:35Z"
message: Denied by my custom approver controller
reason: DeniedByMyPolicy # this can be set to anything
reason: DeniedByMyPolicy # You can set this to any string
type: Denied
```
It's usual to set `status.condtions.reason` to a machine-friendly reason
code using TitleCase; this is a convention but you can set it to anything
you like. If you want to add a note just for human consumption, use the
`status.condtions.message` field.
## Signing
### Control plane signer
### Control plane signer {#signer-control-plane}
The Kubernetes control plane implements each of the [Kubernetes signers](/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers),
as part of the kube-controller-manager.
@@ -299,7 +309,7 @@ Prior to Kubernetes v1.18, the kube-controller-manager would sign any CSRs that
were marked as approved.
{{< /note >}}
### API-based signers
### API-based signers {#signer-api}
Users of the REST API can sign CSRs by submitting an UPDATE request to the `status`
subresource of the CSR to be signed.
@@ -311,8 +321,10 @@ signed certificate.
{{% capture whatsnext %}}
* kube-controller-manager built in [signer](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/signer/cfssl_signer.go)
* kube-controller-manager built in [approver](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/approver/sarapprove.go)
* [Manage TLS Certificates in a Cluster](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/)
* Read [Manage TLS Certificates in a Cluster](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/)
* View the source code for the kube-controller-manager built in [signer](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/signer/cfssl_signer.go)
* View the source code for the kube-controller-manager built in [approver](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/approver/sarapprove.go)
* For details of X.509 itself, refer to [RFC 5280](https://tools.ietf.org/html/rfc5280#section-3.1) section 3.1
* For information on the syntax of PKCS#10 certificate signing requests, refer to [RFC 2986](https://tools.ietf.org/html/rfc2986)
{{% /capture %}}