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
|
[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
|
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).
|
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
|
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
|
by a denoted signer, after which the request may be approved or denied before
|
||||||
finally being signed.
|
finally being signed.
|
||||||
@@ -25,29 +26,33 @@ finally being signed.
|
|||||||
{{% capture body %}}
|
{{% capture body %}}
|
||||||
## Request signing process
|
## Request signing process
|
||||||
|
|
||||||
The _CertificateSigningRequest_ resource type allows a client to submit an x509 CSR (`spec.request`)
|
The _CertificateSigningRequest_ resource type allows a client to ask for an X.509 certificate
|
||||||
and request it be signed by a specific _signer_, denoted by the `spec.signerName` field.
|
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.
|
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
|
Depending on the signer selected, a CertificateSigningRequest may be automatically approved
|
||||||
{{< glossary_tooltip text="controller" term_id="controller" >}}.
|
by a {{< glossary_tooltip text="controller" term_id="controller" >}}.
|
||||||
Otherwise, a CertificateSigningRequest must be manually approved either via the REST API (or client-go)
|
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
|
or by running `kubectl certificate approve`. Likewise, a CertificateSigningRequest may also be denied,
|
||||||
case the configured signer must not sign the request.
|
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
|
For certificates that have been approved, the next step is signing. The relevant signing controller
|
||||||
restrictions, similar to the approval process, on the request to ensure it never signs an invalid request.
|
first validates that the signing conditions are met and then creates a certificate.
|
||||||
There is currently not a mechanism for a signer implementation to report its inability to sign a request.
|
The signing controller then updates the CertificateSigningRequest, storing the new certificate into
|
||||||
Once the signer has determined that a request should be signed, it must sign the request and store the
|
the `status.certificate` field of the existing CertificateSigningRequest object. The
|
||||||
resulting certificate (and if appropriate, certificate chain) in the `status.certificate` field as PEM-encoded
|
`status.certificate` field is either empty or contains a X.509 certificate, encoded in PEM format.
|
||||||
certificates.
|
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
|
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.
|
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
|
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
|
controller runs periodically. The garbage collection removes CertificateSigningRequests that have not changed
|
||||||
than a specified duration:
|
state for some duration:
|
||||||
|
|
||||||
* Approved requests: automatically deleted after 1 hour
|
* Approved requests: automatically deleted after 1 hour
|
||||||
* Denied requests: automatically deleted after 1 hour
|
* Denied requests: automatically deleted after 1 hour
|
||||||
@@ -55,8 +60,6 @@ than a specified duration:
|
|||||||
|
|
||||||
## Signers
|
## Signers
|
||||||
|
|
||||||
### Signers should define...
|
|
||||||
|
|
||||||
All signers should provide information about how they work so that clients can predict what will happen to their CSRs.
|
All signers should provide information about how they work so that clients can predict what will happen to their CSRs.
|
||||||
This includes:
|
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 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. **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. **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. **CA bit allowed/disallowed**: and behavior if a CSR contains a request a for a CA certificate 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.
|
|
||||||
|
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
|
### 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 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 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. 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. 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
|
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 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 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. 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. CA bit allowed/disallowed - not allowed.
|
||||||
|
|
||||||
1. `kubernetes.io/kubelet-serving`: signs serving certificates that are honored as a valid kubelet serving certificate
|
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 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 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. 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. 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
|
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" >}}.
|
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 subjects - any
|
||||||
1. Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
|
1. Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
|
||||||
1. Permitted key usages - any
|
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.
|
1. CA bit allowed/disallowed - not allowed.
|
||||||
|
|
||||||
{{< note >}}
|
{{< note >}}
|
||||||
@@ -222,16 +226,17 @@ rules:
|
|||||||
- sign
|
- 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
|
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
|
a signerName of `kubernetes.io/kube-apiserver-client-kubelet` that delegates various
|
||||||
permissions on CSRs for node credentials to authorization.
|
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
|
A Kubernetes administrator (with appropriate permissions) can manually approve
|
||||||
(or deny) CertificateSigningRequests by using the `kubectl certificate
|
(or deny) CertificateSigningRequests by using the `kubectl certificate
|
||||||
@@ -249,15 +254,15 @@ Likewise, to deny a CSR:
|
|||||||
kubectl certificate deny <certificate-signing-request-name>
|
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`
|
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
|
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
|
{{< glossary_tooltip term_id="operator-pattern" text="operator" >}} that watches for a particular
|
||||||
kind of CSR and then sends an UPDATE to approve them.
|
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
|
When you make an approval or rejection request, set either the `Approved` or `Denied`
|
||||||
desired state:
|
status condition based on the state you determine:
|
||||||
|
|
||||||
For `Approved` CSRs:
|
For `Approved` CSRs:
|
||||||
|
|
||||||
@@ -269,7 +274,7 @@ status:
|
|||||||
conditions:
|
conditions:
|
||||||
- lastUpdateTime: "2020-02-08T11:37:35Z"
|
- lastUpdateTime: "2020-02-08T11:37:35Z"
|
||||||
message: Approved by my custom approver controller
|
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
|
type: Approved
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -283,13 +288,18 @@ status:
|
|||||||
conditions:
|
conditions:
|
||||||
- lastUpdateTime: "2020-02-08T11:37:35Z"
|
- lastUpdateTime: "2020-02-08T11:37:35Z"
|
||||||
message: Denied by my custom approver controller
|
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
|
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
|
## 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),
|
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.
|
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.
|
were marked as approved.
|
||||||
{{< /note >}}
|
{{< /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`
|
Users of the REST API can sign CSRs by submitting an UPDATE request to the `status`
|
||||||
subresource of the CSR to be signed.
|
subresource of the CSR to be signed.
|
||||||
@@ -311,8 +321,10 @@ signed certificate.
|
|||||||
|
|
||||||
{{% capture whatsnext %}}
|
{{% capture whatsnext %}}
|
||||||
|
|
||||||
* kube-controller-manager built in [signer](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/signer/cfssl_signer.go)
|
* Read [Manage TLS Certificates in a Cluster](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/)
|
||||||
* kube-controller-manager built in [approver](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/approver/sarapprove.go)
|
* 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)
|
||||||
* [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 [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 %}}
|
{{% /capture %}}
|
||||||
|
|||||||
Reference in New Issue
Block a user