From 5340ec8c5d9d5630b8f79a3882e4c96810341d73 Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Mon, 1 Feb 2016 13:41:40 -0800 Subject: [PATCH 1/7] Add proposal for kubelet TLS bootstrap --- docs/proposals/kubelet-tls-bootstrap.md | 183 ++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 docs/proposals/kubelet-tls-bootstrap.md diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md new file mode 100644 index 00000000000..67a16986dea --- /dev/null +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -0,0 +1,183 @@ +# Kubelet TLS bootstrap +Author: George Tankersley (george.tankersley@coreos.com) + +## Preface +This document describes a method for a kubelet to bootstrap itself +into a TLS-secured cluster. Crucially, it automates the provision and +distribution of signed certificates. + +## Overview +When a kubelet runs for the first time, it must be given TLS assets +or generate them itself. In the first case, this is a burden on the cluster +admin and a significant logistical barrier to secure Kubernetes rollouts. In +the second, the kubelet must self-sign its certificate and forfeits many of the +advantages of a PKI system. Instead, we propose that the kubelet generate a +private key and a CSR for submission to a cluster-level certificate signing +process. + +## Preliminaries +We assume the existence of a functioning control plane. The +apiserver should be configured for TLS initially or possess the ability to +generate valid TLS credentials for itself. If secret information is passed in +the request (e.g. auth tokens supplied with the request or included in +ExtraInfo) then all communications from the node to the apiserver must take +place over a verified TLS connection. + +Each node is additionally provisioned with the following information: + +1. Location of the apiserver +2. Any CA certificates necessary to trust the apiserver's TLS certificate +3. Access tokens (if needed) to communicate with the CSR endpoint + +These should not change often and are thus simple to include in a static +provisioning script. + +## API Changes +### CertificateSigningRequest Object +We introduce a new API object to represent PKCS#10 certificate signing +requests. It will be accessible under: + +`/api/vX/certificaterequests/mycsr` + +It will have the following structure: + +```go +// Describes a certificate signing request +type CertificateSigningRequest struct { + api.TypeMeta `json:",inline"` + api.ObjectMeta `json:"metadata,omitempty"` + + // Specifies the behavior of the CSR + Spec CertificateSigningRequestSpec + + // Most recently observed status of the CSR + Status CertificateSigningRequestStatus +} + +type CertificateSigningRequestSpec struct { + // Raw PKCS#10 CSR data + CertificateRequest []byte + + // Fingerprint of the public key that signed the CSR + Fingerprint string + + // 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 +} + +type CertificateSigningRequestStatus struct { + // Indicates whether CSR has a response yet. Default is Unknown. Status + // is True for approval and False for rejections. + Status api.ConditionStatus + + // If CSR was rejected, these contain the reason why (if any was supplied). + Reason string + Message string + + // If CSR was approved, this contains the issued certificate. + Certificate []byte +} +``` + +We also introduce CertificateSigningRequestList to allow listing all the CSRs in the cluster: + +```go +type CertificateSigningRequestList struct { + api.TypeMeta + api.ListMeta + + Items []CertificateSigningRequest +} +``` + +## Certificate Request Process + +### Node intialization +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 +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: + +1. Generate a keypair +2. Generate a CSR for that keypair with CN set to the hostname (or + `--hostname-override` value) and DNS/IP SANs supplied with whatever values + the host knows for itself. +3. Post the CSR to the CSR API endpoint. +4. Set a watch on the CSR object to be notified of approval or rejection. + +### Controller response +The apiserver must first validate the signature on the raw CSR data and reject +requests featuring invalid CSRs. It then persists the +CertificateSigningRequests and exposes the List of all CSRs for an +administrator to approve or reject. The apiserver should watch for updates the +Status field of any CertificateSigningRequest. When a CSR is approved +(signified by Status changing from Unknown to True) the apiserver should +generate and sign the certificate, then update the +CertificateSigningRequestStatus with the new data. + +### Manual CSR approval +An administrator using `kubectl` or another API client can query the +CertificateSigningRequestList and update the status of +CertificateSigningRequests. The default Status is Unknown, indicating that +there has been no decision so fare. A Status of True indicates that the admin +has approved the request and the apiserver should issue the certificate. A +Status of False 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) +So that the apiserver can handle certificate issuance on its own, it 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 config +file. + +## kubectl support +To support manual CSR inspection and approval, we will add support for listing, +inspecting, and approving/rejecting CertificateSigningRequests to kubectl. The +interface will be similar to +[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 +active CSRs, inspect their contents, and set their statuses to one of: + +1. **approved** if the apiserver should issue the cert +2. **rejected** if the apiserver should not issue the cert + +The suggested commands are `kubectl get certificates`, `kubectl approve ` +and `kubectl reject `. For the reject subcommand, the admin will also be +able to supply Reason and Message fields via additional flags. + +## Security Considerations + +### Endpoint Access Control +The ability to post CSRs to the signing endpoint should be controlled. As a +simple solution we propose that each node be provisioned with an auth token +(possibly static across the cluster) that is scoped via ABAC to only allow +access to the CSR endpoint. + +### Expiration & Revocation +The node is responsible for monitoring its own certificate expiration date. +When the certificate is close to expiration, the kubelet should begin repeating +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 +unless the cluster policy (see "Future Work") requires fresh keys. + +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 +now, our suggested best practice is to issue only short-lived certificates. In +the future it may make sense to add CRL support to the apiserver's client cert +auth. + +## Future Work +- revocation UI in kubectl and CRL support at the apiserver +- supplemental policy (e.g. cluster CA only issues 30-day certs for hostnames *.k8s.example.com, each new cert must have fresh keys, ...) +- fully automated provisioning (using a handshake protocol or external list of authorized machines) From c47d49dd3e3af2041b99f27b7e67b7fe747384f2 Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Tue, 2 Feb 2016 16:25:55 -0800 Subject: [PATCH 2/7] Fix typo --- docs/proposals/kubelet-tls-bootstrap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md index 67a16986dea..573273225e1 100644 --- a/docs/proposals/kubelet-tls-bootstrap.md +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -128,7 +128,7 @@ CertificateSigningRequestStatus with the new data. An administrator using `kubectl` or another API client can query the CertificateSigningRequestList and update the status of CertificateSigningRequests. The default Status is Unknown, indicating that -there has been no decision so fare. A Status of True indicates that the admin +there has been no decision so far. A Status of True indicates that the admin has approved the request and the apiserver should issue the certificate. A Status of False indicates that the admin has denied the request. An admin may also supply Reason and Message fields to explain the rejection. From c553c5b575bc4d3d33f6b37cce41af613a55af86 Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Wed, 3 Feb 2016 14:28:06 -0800 Subject: [PATCH 3/7] Update documents properly --- docs/proposals/kubelet-tls-bootstrap.md | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md index 573273225e1..03495dc8c7c 100644 --- a/docs/proposals/kubelet-tls-bootstrap.md +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -1,12 +1,44 @@ + + + + +WARNING +WARNING +WARNING +WARNING +WARNING + +

PLEASE NOTE: This document applies to the HEAD of the source tree

+ +If you are using a released version of Kubernetes, you should +refer to the docs that go with that version. + +Documentation for other releases can be found at +[releases.k8s.io](http://releases.k8s.io). + +-- + + + + + # Kubelet TLS bootstrap + Author: George Tankersley (george.tankersley@coreos.com) ## Preface + This document describes a method for a kubelet to bootstrap itself into a TLS-secured cluster. Crucially, it automates the provision and distribution of signed certificates. ## Overview + When a kubelet runs for the first time, it must be given TLS assets or generate them itself. In the first case, this is a burden on the cluster admin and a significant logistical barrier to secure Kubernetes rollouts. In @@ -16,6 +48,7 @@ private key and a CSR for submission to a cluster-level certificate signing process. ## Preliminaries + We assume the existence of a functioning control plane. The apiserver should be configured for TLS initially or possess the ability to generate valid TLS credentials for itself. If secret information is passed in @@ -33,7 +66,9 @@ These should not change often and are thus simple to include in a static provisioning script. ## API Changes + ### CertificateSigningRequest Object + We introduce a new API object to represent PKCS#10 certificate signing requests. It will be accessible under: @@ -102,6 +137,7 @@ type CertificateSigningRequestList struct { ## Certificate Request Process ### Node intialization + 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 them, it proceeds. If there are no TLS assets, the kubelet generates a keypair @@ -115,6 +151,7 @@ and self-signed certificate. We propose the following optional fallback behavior 4. Set a watch on the CSR object to be notified of approval or rejection. ### Controller response + The apiserver must first validate the signature on the raw CSR data and reject requests featuring invalid CSRs. It then persists the CertificateSigningRequests and exposes the List of all CSRs for an @@ -125,6 +162,7 @@ generate and sign the certificate, then update the CertificateSigningRequestStatus with the new data. ### Manual CSR approval + An administrator using `kubectl` or another API client can query the CertificateSigningRequestList and update the status of CertificateSigningRequests. The default Status is Unknown, indicating that @@ -134,6 +172,7 @@ Status of False 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) + So that the apiserver can handle certificate issuance on its own, it 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. @@ -141,6 +180,7 @@ For now, we will add flags for a signing key, a certificate, and a basic config file. ## kubectl support + To support manual CSR inspection and approval, we will add support for listing, inspecting, and approving/rejecting CertificateSigningRequests to kubectl. The interface will be similar to @@ -159,12 +199,14 @@ able to supply Reason and Message fields via additional flags. ## Security Considerations ### Endpoint Access Control + The ability to post CSRs to the signing endpoint should be controlled. As a simple solution we propose that each node be provisioned with an auth token (possibly static across the cluster) that is scoped via ABAC to only allow access to the CSR endpoint. ### Expiration & Revocation + The node is responsible for monitoring its own certificate expiration date. When the certificate is close to expiration, the kubelet should begin repeating this flow until it successfully obtains a new certificate. If the expiring @@ -178,6 +220,12 @@ the future it may make sense to add CRL support to the apiserver's client cert auth. ## Future Work + - revocation UI in kubectl and CRL support at the apiserver - supplemental policy (e.g. cluster CA only issues 30-day certs for hostnames *.k8s.example.com, each new cert must have fresh keys, ...) - fully automated provisioning (using a handshake protocol or external list of authorized machines) + + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/proposals/kubelet-tls-bootstrap.md?pixel)]() + From ac1e82c38c9f9782fa08776017eaa5adab8c7375 Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Tue, 12 Apr 2016 12:27:11 -0700 Subject: [PATCH 4/7] docs/proposals: update kubelet tls bootstrap proposal --- docs/proposals/kubelet-tls-bootstrap.md | 161 +++++++++++++++--------- 1 file changed, 99 insertions(+), 62 deletions(-) diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md index 03495dc8c7c..95536ca5b02 100644 --- a/docs/proposals/kubelet-tls-bootstrap.md +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -72,55 +72,80 @@ provisioning script. We introduce a new API object to represent PKCS#10 certificate signing requests. It will be accessible under: -`/api/vX/certificaterequests/mycsr` +`/apis/certificates/v1beta1/signingrequests/mycsr` It will have the following structure: ```go // Describes a certificate signing request type CertificateSigningRequest struct { - api.TypeMeta `json:",inline"` - api.ObjectMeta `json:"metadata,omitempty"` + api.TypeMeta `json:",inline"` + api.ObjectMeta `json:"metadata,omitempty"` - // Specifies the behavior of the CSR - Spec CertificateSigningRequestSpec + // The certificate request itself and any additonal information. + Spec CertificateSigningRequestSpec `json:"spec,omitempty"` - // Most recently observed status of the CSR - Status CertificateSigningRequestStatus + // Derived information about the request. + 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 { - // Raw PKCS#10 CSR data - CertificateRequest []byte + // Raw PKCS#10 CSR data + CertificateRequest string `json:"request"` - // Fingerprint of the public key that signed the CSR - Fingerprint string - - // 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 + // Any extra information the node wishes to send with the request. + ExtraInfo []string `json:"extra,omitempty"` } +// 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 { - // Indicates whether CSR has a response yet. Default is Unknown. Status - // is True for approval and False for rejections. - Status api.ConditionStatus + // Information about the requesting user (if relevant) + // See user.Info interface for details + 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). - Reason string - Message string + // Fingerprint of the public key in request + Fingerprint string `json:"fingerprint,omitempty"` - // If CSR was approved, this contains the issued certificate. - Certificate []byte + // Subject fields from the request + 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: @@ -141,7 +166,7 @@ type CertificateSigningRequestList struct { 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 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 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 -The apiserver must first validate the signature on the raw CSR data and reject -requests featuring invalid CSRs. It then persists the -CertificateSigningRequests and exposes the List of all CSRs for an -administrator to approve or reject. The apiserver should watch for updates the -Status field of any CertificateSigningRequest. When a CSR is approved -(signified by Status changing from Unknown to True) the apiserver should -generate and sign the certificate, then update the -CertificateSigningRequestStatus with the new data. +The apiserver persists the CertificateSigningRequests and exposes the List of +all CSRs for an administrator to approve or reject. + +A new certificate controller watches for certificate requests. It must first +validate the signature on each CSR and set `CertificateRequestState=Denied` on +any requests with invalid signatures. For valid requests, it will set +`CertificateRequestState=Submitted`. The controller will derive the information +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 An administrator using `kubectl` or another API client can query the -CertificateSigningRequestList and update the status of -CertificateSigningRequests. The default Status is Unknown, indicating that -there has been no decision so far. A Status of True indicates that the admin -has approved the request and the apiserver should issue the certificate. A -Status of False indicates that the admin has denied the request. An admin may -also supply Reason and Message fields to explain the rejection. +CertificateSigningRequestList and update the approval state of +CertificateSigningRequests. The default state is empty, indicating that there +has been no decision so far. Once a request has passed basic validation it will +be "Submitted". A state of "Approved" indicates that the admin has approved the +request and the certificate controller should issue the certificate. A state of +"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 -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 config -file. +The apiserver will present the new endpoints mentioned above and support the +relevant object types. + +## kube-controller-manager support + +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 To support manual CSR inspection and approval, we will add support for listing, -inspecting, and approving/rejecting CertificateSigningRequests to kubectl. The -interface will be similar to +inspecting, and approving or denying CertificateSigningRequests to kubectl. The +interaction will be similar to [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 -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 -2. **rejected** if the apiserver should not issue the cert +1. **Approved** if the controller should issue the cert +2. **Denied** if the controller should not issue the cert -The suggested commands are `kubectl get certificates`, `kubectl approve ` -and `kubectl reject `. For the reject subcommand, the admin will also be -able to supply Reason and Message fields via additional flags. +The suggested command for listing is `kubectl get csrs`. The approve/deny +interactions can be accomplished with normal updates, but would be more +conveniently accessed by direct subresource updates. We leave this for future +updates to kubectl. ## Security Considerations @@ -210,8 +246,9 @@ access to the CSR endpoint. The node is responsible for monitoring its own certificate expiration date. When the certificate is close to expiration, the kubelet should begin repeating 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 -unless the cluster policy (see "Future Work") requires fresh keys. +certificate has not been revoked and the previous certificate request is still +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 application to produce its own logic around a variety of parsing functions. For From 5d479cc971d2666796f2189b289375c588245d2b Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Thu, 14 Apr 2016 14:03:31 -0700 Subject: [PATCH 5/7] docs/proposals: specify encoding of certificate requests --- docs/proposals/kubelet-tls-bootstrap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md index 95536ca5b02..a0ec6b958d5 100644 --- a/docs/proposals/kubelet-tls-bootstrap.md +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -94,7 +94,7 @@ type CertificateSigningRequest struct { // This information is immutable after the request is created. type CertificateSigningRequestSpec struct { - // Raw PKCS#10 CSR data + // base64-encoded PKCS#10 CSR data CertificateRequest string `json:"request"` // Any extra information the node wishes to send with the request. From a81beb3bde181ff38a5196489219e8b0d86cfd67 Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Mon, 25 Apr 2016 18:30:40 -0700 Subject: [PATCH 6/7] docs/proposals: further review comments --- docs/proposals/kubelet-tls-bootstrap.md | 80 +++++++++++++------------ 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md index a0ec6b958d5..c8119407a65 100644 --- a/docs/proposals/kubelet-tls-bootstrap.md +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -79,26 +79,23 @@ It will have the following structure: ```go // Describes a certificate signing request type CertificateSigningRequest struct { - api.TypeMeta `json:",inline"` - api.ObjectMeta `json:"metadata,omitempty"` + unversioned.TypeMeta `json:",inline"` + api.ObjectMeta `json:"metadata,omitempty"` // The certificate request itself and any additonal information. Spec CertificateSigningRequestSpec `json:"spec,omitempty"` // Derived information about the request. 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 { - // base64-encoded PKCS#10 CSR data - CertificateRequest string `json:"request"` + // Base64-encoded PKCS#10 CSR data + Request string `json:"request"` // Any extra information the node wishes to send with the request. - ExtraInfo []string `json:"extra,omitempty"` + ExtraInfo []string `json:"extrainfo,omitempty"` } // This information is derived from the request by Kubernetes and cannot be @@ -116,36 +113,42 @@ type CertificateSigningRequestStatus struct { Fingerprint string `json:"fingerprint,omitempty"` // Subject fields from the request - Subject pkix.Name `json:"subject,omitempty"` + Subject internal.Subject `json:"subject,omitempty"` // DNS SANs from the request - Hostnames []string `json:"dns,omitempty"` + Hostnames []string `json:"hostnames,omitempty"` // IP SANs from the request - IPAddresses []string `json:"ip,omitempty"` + IPAddresses []string `json:"ipaddresses,omitempty"` + + Conditions []CertificateSigningRequestCondition `json:"conditions,omitempty"` } -type CertificateSigningRequestApproval struct { - // CSR approval state, one of Submitted, Approved, or Denied - State CertificateRequestState `json:"state"` +type RequestConditionType string +// These are the possible states for a certificate request. +const ( + Approved RequestConditionType = "Approved" + Denied RequestConditionType = "Denied" +) + +type CertificateSigningRequestCondition struct { + // request approval state, currently Approved or Denied. + Type RequestConditionType `json:"type"` // 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 +type CertificateSigningRequestList struct { + unversioned.TypeMeta `json:",inline"` + unversioned.ListMeta `json:"metadata,omitempty"` -// These are the possible states for a certificate request. -const ( - RequestSubmitted CertificateRequestState = "Submitted" - RequestApproved CertificateRequestState = "Approved" - RequestDenied CertificateRequestState = "Denied" -) + Items []CertificateSigningRequest `json:"items,omitempty"` +} ``` We also introduce CertificateSigningRequestList to allow listing all the CSRs in the cluster: @@ -181,26 +184,26 @@ The apiserver persists the CertificateSigningRequests and exposes the List of all CSRs for an administrator to approve or reject. A new certificate controller watches for certificate requests. It must first -validate the signature on each CSR and set `CertificateRequestState=Denied` on -any requests with invalid signatures. For valid requests, it will set -`CertificateRequestState=Submitted`. The controller will derive the information -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. +validate the signature on each CSR and add `Condition=Denied` on +any requests with invalid signatures (with Reason and Message incidicating +such). For valid requests, the controller will derive the information in +`CertificateSigningRequestStatus` and update that object. The controller should +watch for updates to the approval condition of any CertificateSigningRequest. +When a request is approved (signified by Conditions containing only Approved) +the controller should generate and sign a certificate based on that CSR, then +update the condition with the certificate data using the `/approval` +subresource. ### Manual CSR approval An administrator using `kubectl` or another API client can query the -CertificateSigningRequestList and update the approval state of +CertificateSigningRequestList and update the approval condition of CertificateSigningRequests. The default state is empty, indicating that there -has been no decision so far. Once a request has passed basic validation it will -be "Submitted". A state of "Approved" indicates that the admin has approved the -request and the certificate controller should issue the certificate. A state of -"Denied" indicates that the admin has denied the request. An admin may also -supply Reason and Message fields to explain the rejection. +has been no decision so far. A state of "Approved" indicates that the admin has +approved the request and the certificate controller should issue the +certificate. A state of "Denied" indicates that admin has denied the +request. An admin may also supply Reason and Message fields to explain the +rejection. ## kube-apiserver support @@ -222,7 +225,8 @@ interaction will be similar to [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 -pending CSRs, inspect their contents, and set their states to one of: +pending CSRs, inspect their contents, and set their approval conditions to one +of: 1. **Approved** if the controller should issue the cert 2. **Denied** if the controller should not issue the cert From 5a65bb0044d9ac3fc3e7585d09cb6bb33e9c3b2c Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Tue, 3 May 2016 14:20:24 -0700 Subject: [PATCH 7/7] docs: correct csr resource prefix --- docs/proposals/kubelet-tls-bootstrap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposals/kubelet-tls-bootstrap.md b/docs/proposals/kubelet-tls-bootstrap.md index c8119407a65..314c5afe4aa 100644 --- a/docs/proposals/kubelet-tls-bootstrap.md +++ b/docs/proposals/kubelet-tls-bootstrap.md @@ -72,7 +72,7 @@ provisioning script. We introduce a new API object to represent PKCS#10 certificate signing requests. It will be accessible under: -`/apis/certificates/v1beta1/signingrequests/mycsr` +`/apis/certificates/v1beta1/certificatesigningrequests/mycsr` It will have the following structure: