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:
@@ -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 %}}
|
||||
|
||||
Reference in New Issue
Block a user