mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	docs/proposals: update kubelet tls bootstrap proposal
This commit is contained in:
		@@ -72,7 +72,7 @@ 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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -82,45 +82,70 @@ 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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user