mirror of https://github.com/k3s-io/k3s
docs/proposals: update kubelet tls bootstrap proposal
parent
c553c5b575
commit
ac1e82c38c
|
@ -72,55 +72,80 @@ provisioning script.
|
||||||
We introduce a new API object to represent PKCS#10 certificate signing
|
We introduce a new API object to represent PKCS#10 certificate signing
|
||||||
requests. It will be accessible under:
|
requests. It will be accessible under:
|
||||||
|
|
||||||
`/api/vX/certificaterequests/mycsr`
|
`/apis/certificates/v1beta1/signingrequests/mycsr`
|
||||||
|
|
||||||
It will have the following structure:
|
It will have the following structure:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Describes a certificate signing request
|
// Describes a certificate signing request
|
||||||
type CertificateSigningRequest struct {
|
type CertificateSigningRequest struct {
|
||||||
api.TypeMeta `json:",inline"`
|
api.TypeMeta `json:",inline"`
|
||||||
api.ObjectMeta `json:"metadata,omitempty"`
|
api.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
// Specifies the behavior of the CSR
|
// The certificate request itself and any additonal information.
|
||||||
Spec CertificateSigningRequestSpec
|
Spec CertificateSigningRequestSpec `json:"spec,omitempty"`
|
||||||
|
|
||||||
// Most recently observed status of the CSR
|
// Derived information about the request.
|
||||||
Status CertificateSigningRequestStatus
|
Status CertificateSigningRequestStatus `json:"status,omitempty"`
|
||||||
|
|
||||||
|
// The current approval state of the request.
|
||||||
|
Approve CertificateSigningRequestApproval `json:"approve,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This information is immutable after the request is created.
|
||||||
type CertificateSigningRequestSpec struct {
|
type CertificateSigningRequestSpec struct {
|
||||||
// Raw PKCS#10 CSR data
|
// Raw PKCS#10 CSR data
|
||||||
CertificateRequest []byte
|
CertificateRequest string `json:"request"`
|
||||||
|
|
||||||
// Fingerprint of the public key that signed the CSR
|
// Any extra information the node wishes to send with the request.
|
||||||
Fingerprint string
|
ExtraInfo []string `json:"extra,omitempty"`
|
||||||
|
|
||||||
// Subject fields from the CSR
|
|
||||||
Subject pkix.Name
|
|
||||||
|
|
||||||
// DNS SANs from the CSR
|
|
||||||
Hostnames []string
|
|
||||||
|
|
||||||
// IP SANs from the CSR
|
|
||||||
IPAddresses []string
|
|
||||||
|
|
||||||
// Extra information the node wishes to send with the request
|
|
||||||
ExtraInfo []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This information is derived from the request by Kubernetes and cannot be
|
||||||
|
// modified by users. All information is optional since it might not be
|
||||||
|
// available in the underlying request. This is intented to aid approval
|
||||||
|
// decisions.
|
||||||
type CertificateSigningRequestStatus struct {
|
type CertificateSigningRequestStatus struct {
|
||||||
// Indicates whether CSR has a response yet. Default is Unknown. Status
|
// Information about the requesting user (if relevant)
|
||||||
// is True for approval and False for rejections.
|
// See user.Info interface for details
|
||||||
Status api.ConditionStatus
|
Username string `json:"username,omitempty"`
|
||||||
|
UID string `json:"uid,omitempty"`
|
||||||
|
Groups []string `json:"groups,omitempty"`
|
||||||
|
|
||||||
// If CSR was rejected, these contain the reason why (if any was supplied).
|
// Fingerprint of the public key in request
|
||||||
Reason string
|
Fingerprint string `json:"fingerprint,omitempty"`
|
||||||
Message string
|
|
||||||
|
|
||||||
// If CSR was approved, this contains the issued certificate.
|
// Subject fields from the request
|
||||||
Certificate []byte
|
Subject pkix.Name `json:"subject,omitempty"`
|
||||||
|
|
||||||
|
// DNS SANs from the request
|
||||||
|
Hostnames []string `json:"dns,omitempty"`
|
||||||
|
|
||||||
|
// IP SANs from the request
|
||||||
|
IPAddresses []string `json:"ip,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CertificateSigningRequestApproval struct {
|
||||||
|
// CSR approval state, one of Submitted, Approved, or Denied
|
||||||
|
State CertificateRequestState `json:"state"`
|
||||||
|
|
||||||
|
// brief reason for the request state
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
|
// human readable message with details about the request state
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
|
||||||
|
// If request was approved, the controller will place the issued certificate here.
|
||||||
|
Certificate []byte `json:"certificate,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateRequestState string
|
||||||
|
|
||||||
|
// These are the possible states for a certificate request.
|
||||||
|
const (
|
||||||
|
RequestSubmitted CertificateRequestState = "Submitted"
|
||||||
|
RequestApproved CertificateRequestState = "Approved"
|
||||||
|
RequestDenied CertificateRequestState = "Denied"
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
We also introduce CertificateSigningRequestList to allow listing all the CSRs in the cluster:
|
We also introduce CertificateSigningRequestList to allow listing all the CSRs in the cluster:
|
||||||
|
@ -141,7 +166,7 @@ type CertificateSigningRequestList struct {
|
||||||
When the kubelet executes it checks a location on disk for TLS assets
|
When the kubelet executes it checks a location on disk for TLS assets
|
||||||
(currently `/var/run/kubernetes/kubelet.{key,crt}` by default). If it finds
|
(currently `/var/run/kubernetes/kubelet.{key,crt}` by default). If it finds
|
||||||
them, it proceeds. If there are no TLS assets, the kubelet generates a keypair
|
them, it proceeds. If there are no TLS assets, the kubelet generates a keypair
|
||||||
and self-signed certificate. We propose the following optional fallback behavior:
|
and self-signed certificate. We propose the following optional behavior:
|
||||||
|
|
||||||
1. Generate a keypair
|
1. Generate a keypair
|
||||||
2. Generate a CSR for that keypair with CN set to the hostname (or
|
2. Generate a CSR for that keypair with CN set to the hostname (or
|
||||||
|
@ -152,49 +177,60 @@ and self-signed certificate. We propose the following optional fallback behavior
|
||||||
|
|
||||||
### Controller response
|
### Controller response
|
||||||
|
|
||||||
The apiserver must first validate the signature on the raw CSR data and reject
|
The apiserver persists the CertificateSigningRequests and exposes the List of
|
||||||
requests featuring invalid CSRs. It then persists the
|
all CSRs for an administrator to approve or reject.
|
||||||
CertificateSigningRequests and exposes the List of all CSRs for an
|
|
||||||
administrator to approve or reject. The apiserver should watch for updates the
|
A new certificate controller watches for certificate requests. It must first
|
||||||
Status field of any CertificateSigningRequest. When a CSR is approved
|
validate the signature on each CSR and set `CertificateRequestState=Denied` on
|
||||||
(signified by Status changing from Unknown to True) the apiserver should
|
any requests with invalid signatures. For valid requests, it will set
|
||||||
generate and sign the certificate, then update the
|
`CertificateRequestState=Submitted`. The controller will derive the information
|
||||||
CertificateSigningRequestStatus with the new data.
|
in `CertificateSigningRequestStatus` and update that object. The controller
|
||||||
|
should watch for updates the approval state of any CertificateSigningRequest.
|
||||||
|
When a request is approved (signified by CertificateRequestState changing from
|
||||||
|
Submitted to Approved) the controller should generate and sign a certificate
|
||||||
|
based on that CSR, then update the approval subresource with the certificate
|
||||||
|
data.
|
||||||
|
|
||||||
### Manual CSR approval
|
### Manual CSR approval
|
||||||
|
|
||||||
An administrator using `kubectl` or another API client can query the
|
An administrator using `kubectl` or another API client can query the
|
||||||
CertificateSigningRequestList and update the status of
|
CertificateSigningRequestList and update the approval state of
|
||||||
CertificateSigningRequests. The default Status is Unknown, indicating that
|
CertificateSigningRequests. The default state is empty, indicating that there
|
||||||
there has been no decision so far. A Status of True indicates that the admin
|
has been no decision so far. Once a request has passed basic validation it will
|
||||||
has approved the request and the apiserver should issue the certificate. A
|
be "Submitted". A state of "Approved" indicates that the admin has approved the
|
||||||
Status of False indicates that the admin has denied the request. An admin may
|
request and the certificate controller should issue the certificate. A state of
|
||||||
also supply Reason and Message fields to explain the rejection.
|
"Denied" indicates that the admin has denied the request. An admin may also
|
||||||
|
supply Reason and Message fields to explain the rejection.
|
||||||
|
|
||||||
## kube-apiserver support (CA assets)
|
## kube-apiserver support
|
||||||
|
|
||||||
So that the apiserver can handle certificate issuance on its own, it will need
|
The apiserver will present the new endpoints mentioned above and support the
|
||||||
access to CA signing assets. This could be as simple as a private key and a
|
relevant object types.
|
||||||
config file or as complex as a PKCS#11 client and supplementary policy system.
|
|
||||||
For now, we will add flags for a signing key, a certificate, and a basic config
|
## kube-controller-manager support
|
||||||
file.
|
|
||||||
|
To handle certificate issuance, the controller-manager will need access to CA
|
||||||
|
signing assets. This could be as simple as a private key and a config file or
|
||||||
|
as complex as a PKCS#11 client and supplementary policy system. For now, we
|
||||||
|
will add flags for a signing key, a certificate, and a basic policy file.
|
||||||
|
|
||||||
## kubectl support
|
## kubectl support
|
||||||
|
|
||||||
To support manual CSR inspection and approval, we will add support for listing,
|
To support manual CSR inspection and approval, we will add support for listing,
|
||||||
inspecting, and approving/rejecting CertificateSigningRequests to kubectl. The
|
inspecting, and approving or denying CertificateSigningRequests to kubectl. The
|
||||||
interface will be similar to
|
interaction will be similar to
|
||||||
[salt-key](https://docs.saltstack.com/en/latest/ref/cli/salt-key.html).
|
[salt-key](https://docs.saltstack.com/en/latest/ref/cli/salt-key.html).
|
||||||
|
|
||||||
Specifically, the admin will have the ability to retrieve the full list of
|
Specifically, the admin will have the ability to retrieve the full list of
|
||||||
active CSRs, inspect their contents, and set their statuses to one of:
|
pending CSRs, inspect their contents, and set their states to one of:
|
||||||
|
|
||||||
1. **approved** if the apiserver should issue the cert
|
1. **Approved** if the controller should issue the cert
|
||||||
2. **rejected** if the apiserver should not issue the cert
|
2. **Denied** if the controller should not issue the cert
|
||||||
|
|
||||||
The suggested commands are `kubectl get certificates`, `kubectl approve <csr>`
|
The suggested command for listing is `kubectl get csrs`. The approve/deny
|
||||||
and `kubectl reject <csr>`. For the reject subcommand, the admin will also be
|
interactions can be accomplished with normal updates, but would be more
|
||||||
able to supply Reason and Message fields via additional flags.
|
conveniently accessed by direct subresource updates. We leave this for future
|
||||||
|
updates to kubectl.
|
||||||
|
|
||||||
## Security Considerations
|
## Security Considerations
|
||||||
|
|
||||||
|
@ -210,8 +246,9 @@ access to the CSR endpoint.
|
||||||
The node is responsible for monitoring its own certificate expiration date.
|
The node is responsible for monitoring its own certificate expiration date.
|
||||||
When the certificate is close to expiration, the kubelet should begin repeating
|
When the certificate is close to expiration, the kubelet should begin repeating
|
||||||
this flow until it successfully obtains a new certificate. If the expiring
|
this flow until it successfully obtains a new certificate. If the expiring
|
||||||
certificate has not been revoked then it may do so using the same keypair
|
certificate has not been revoked and the previous certificate request is still
|
||||||
unless the cluster policy (see "Future Work") requires fresh keys.
|
approved, then it may do so using the same keypair unless the cluster policy
|
||||||
|
(see "Future Work") requires fresh keys.
|
||||||
|
|
||||||
Revocation is for the most part an unhandled problem in Go, requiring each
|
Revocation is for the most part an unhandled problem in Go, requiring each
|
||||||
application to produce its own logic around a variety of parsing functions. For
|
application to produce its own logic around a variety of parsing functions. For
|
||||||
|
|
Loading…
Reference in New Issue