mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	add an option to controller-manager to auto approve all CSRs
This commit is contained in:
		@@ -468,6 +468,7 @@ func StartControllers(s *options.CMServer, kubeClient *client.Client, kubeconfig
 | 
				
			|||||||
				resyncPeriod,
 | 
									resyncPeriod,
 | 
				
			||||||
				s.ClusterSigningCertFile,
 | 
									s.ClusterSigningCertFile,
 | 
				
			||||||
				s.ClusterSigningKeyFile,
 | 
									s.ClusterSigningKeyFile,
 | 
				
			||||||
 | 
									s.ApproveAllKubeletCSRsForGroup,
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				glog.Errorf("Failed to start certificate controller: %v", err)
 | 
									glog.Errorf("Failed to start certificate controller: %v", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -159,6 +159,7 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet) {
 | 
				
			|||||||
	fs.StringVar(&s.ServiceAccountKeyFile, "service-account-private-key-file", s.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA key used to sign service account tokens.")
 | 
						fs.StringVar(&s.ServiceAccountKeyFile, "service-account-private-key-file", s.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA key used to sign service account tokens.")
 | 
				
			||||||
	fs.StringVar(&s.ClusterSigningCertFile, "cluster-signing-cert-file", s.ClusterSigningCertFile, "Filename containing a PEM-encoded X509 CA certificate used to issue cluster-scoped certificates")
 | 
						fs.StringVar(&s.ClusterSigningCertFile, "cluster-signing-cert-file", s.ClusterSigningCertFile, "Filename containing a PEM-encoded X509 CA certificate used to issue cluster-scoped certificates")
 | 
				
			||||||
	fs.StringVar(&s.ClusterSigningKeyFile, "cluster-signing-key-file", s.ClusterSigningKeyFile, "Filename containing a PEM-encoded RSA or ECDSA private key used to sign cluster-scoped certificates")
 | 
						fs.StringVar(&s.ClusterSigningKeyFile, "cluster-signing-key-file", s.ClusterSigningKeyFile, "Filename containing a PEM-encoded RSA or ECDSA private key used to sign cluster-scoped certificates")
 | 
				
			||||||
 | 
						fs.StringVar(&s.ApproveAllKubeletCSRsForGroup, "insecure-experimental-approve-all-kubelet-csrs-for-group", s.ApproveAllKubeletCSRsForGroup, "The group for which the controller-manager will auto approve all CSRs for kubelet client certificates.")
 | 
				
			||||||
	fs.BoolVar(&s.EnableProfiling, "profiling", true, "Enable profiling via web interface host:port/debug/pprof/")
 | 
						fs.BoolVar(&s.EnableProfiling, "profiling", true, "Enable profiling via web interface host:port/debug/pprof/")
 | 
				
			||||||
	fs.StringVar(&s.ClusterName, "cluster-name", s.ClusterName, "The instance prefix for the cluster")
 | 
						fs.StringVar(&s.ClusterName, "cluster-name", s.ClusterName, "The instance prefix for the cluster")
 | 
				
			||||||
	fs.StringVar(&s.ClusterCIDR, "cluster-cidr", s.ClusterCIDR, "CIDR Range for Pods in cluster.")
 | 
						fs.StringVar(&s.ClusterCIDR, "cluster-cidr", s.ClusterCIDR, "CIDR Range for Pods in cluster.")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -229,6 +229,7 @@ include-extended-apis
 | 
				
			|||||||
included-types-overrides
 | 
					included-types-overrides
 | 
				
			||||||
input-base
 | 
					input-base
 | 
				
			||||||
input-dirs
 | 
					input-dirs
 | 
				
			||||||
 | 
					insecure-experimental-approve-all-kubelet-csrs-for-group
 | 
				
			||||||
insecure-bind-address
 | 
					insecure-bind-address
 | 
				
			||||||
insecure-port
 | 
					insecure-port
 | 
				
			||||||
insecure-skip-tls-verify
 | 
					insecure-skip-tls-verify
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -591,6 +591,12 @@ type KubeControllerManagerConfiguration struct {
 | 
				
			|||||||
	// clusterSigningCertFile is the filename containing a PEM-encoded
 | 
						// clusterSigningCertFile is the filename containing a PEM-encoded
 | 
				
			||||||
	// RSA or ECDSA private key used to issue cluster-scoped certificates
 | 
						// RSA or ECDSA private key used to issue cluster-scoped certificates
 | 
				
			||||||
	ClusterSigningKeyFile string `json:"clusterSigningKeyFile"`
 | 
						ClusterSigningKeyFile string `json:"clusterSigningKeyFile"`
 | 
				
			||||||
 | 
						// approveAllKubeletCSRs tells the CSR controller to approve all CSRs originating
 | 
				
			||||||
 | 
						// from the kubelet bootstrapping group automatically.
 | 
				
			||||||
 | 
						// WARNING: this grants all users with access to the certificates API group
 | 
				
			||||||
 | 
						// the ability to create credentials for any user that has access to the boostrapping
 | 
				
			||||||
 | 
						// user's credentials.
 | 
				
			||||||
 | 
						ApproveAllKubeletCSRsForGroup string `json:"approveAllKubeletCSRsForGroup"`
 | 
				
			||||||
	// enableProfiling enables profiling via web interface host:port/debug/pprof/
 | 
						// enableProfiling enables profiling via web interface host:port/debug/pprof/
 | 
				
			||||||
	EnableProfiling bool `json:"enableProfiling"`
 | 
						EnableProfiling bool `json:"enableProfiling"`
 | 
				
			||||||
	// clusterName is the instance prefix for the cluster.
 | 
						// clusterName is the instance prefix for the cluster.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,12 +17,11 @@ limitations under the License.
 | 
				
			|||||||
package certificates
 | 
					package certificates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/cloudflare/cfssl/config"
 | 
					 | 
				
			||||||
	"github.com/cloudflare/cfssl/signer"
 | 
					 | 
				
			||||||
	"github.com/cloudflare/cfssl/signer/local"
 | 
					 | 
				
			||||||
	"github.com/golang/glog"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api"
 | 
						"k8s.io/kubernetes/pkg/api"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/certificates"
 | 
						"k8s.io/kubernetes/pkg/apis/certificates"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/client/cache"
 | 
						"k8s.io/kubernetes/pkg/client/cache"
 | 
				
			||||||
@@ -32,10 +31,16 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/controller"
 | 
						"k8s.io/kubernetes/pkg/controller"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/controller/framework"
 | 
						"k8s.io/kubernetes/pkg/controller/framework"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/runtime"
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						utilcertificates "k8s.io/kubernetes/pkg/util/certificates"
 | 
				
			||||||
	utilruntime "k8s.io/kubernetes/pkg/util/runtime"
 | 
						utilruntime "k8s.io/kubernetes/pkg/util/runtime"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/wait"
 | 
						"k8s.io/kubernetes/pkg/util/wait"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/workqueue"
 | 
						"k8s.io/kubernetes/pkg/util/workqueue"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/watch"
 | 
						"k8s.io/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cloudflare/cfssl/config"
 | 
				
			||||||
 | 
						"github.com/cloudflare/cfssl/signer"
 | 
				
			||||||
 | 
						"github.com/cloudflare/cfssl/signer/local"
 | 
				
			||||||
 | 
						"github.com/golang/glog"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CertificateController struct {
 | 
					type CertificateController struct {
 | 
				
			||||||
@@ -49,12 +54,14 @@ type CertificateController struct {
 | 
				
			|||||||
	updateHandler func(csr *certificates.CertificateSigningRequest) error
 | 
						updateHandler func(csr *certificates.CertificateSigningRequest) error
 | 
				
			||||||
	syncHandler   func(csrKey string) error
 | 
						syncHandler   func(csrKey string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						approveAllKubeletCSRsForGroup string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	signer *local.Signer
 | 
						signer *local.Signer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	queue *workqueue.Type
 | 
						queue *workqueue.Type
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCertificateController(kubeClient clientset.Interface, syncPeriod time.Duration, caCertFile, caKeyFile string) (*CertificateController, error) {
 | 
					func NewCertificateController(kubeClient clientset.Interface, syncPeriod time.Duration, caCertFile, caKeyFile string, approveAllKubeletCSRsForGroup string) (*CertificateController, error) {
 | 
				
			||||||
	// Send events to the apiserver
 | 
						// Send events to the apiserver
 | 
				
			||||||
	eventBroadcaster := record.NewBroadcaster()
 | 
						eventBroadcaster := record.NewBroadcaster()
 | 
				
			||||||
	eventBroadcaster.StartLogging(glog.Infof)
 | 
						eventBroadcaster.StartLogging(glog.Infof)
 | 
				
			||||||
@@ -74,6 +81,7 @@ func NewCertificateController(kubeClient clientset.Interface, syncPeriod time.Du
 | 
				
			|||||||
		kubeClient: kubeClient,
 | 
							kubeClient: kubeClient,
 | 
				
			||||||
		queue:      workqueue.New(),
 | 
							queue:      workqueue.New(),
 | 
				
			||||||
		signer:     ca,
 | 
							signer:     ca,
 | 
				
			||||||
 | 
							approveAllKubeletCSRsForGroup: approveAllKubeletCSRsForGroup,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Manage the addition/update of certificate requests
 | 
						// Manage the addition/update of certificate requests
 | 
				
			||||||
@@ -181,6 +189,11 @@ func (cc *CertificateController) maybeSignCertificate(key string) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	csr := obj.(*certificates.CertificateSigningRequest)
 | 
						csr := obj.(*certificates.CertificateSigningRequest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csr, err = cc.maybeAutoApproveCSR(csr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("error auto approving csr: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// At this point, the controller needs to:
 | 
						// At this point, the controller needs to:
 | 
				
			||||||
	// 1. Check the approval conditions
 | 
						// 1. Check the approval conditions
 | 
				
			||||||
	// 2. Generate a signed certificate
 | 
						// 2. Generate a signed certificate
 | 
				
			||||||
@@ -198,3 +211,47 @@ func (cc *CertificateController) maybeSignCertificate(key string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return cc.updateCertificateRequestStatus(csr)
 | 
						return cc.updateCertificateRequestStatus(csr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cc *CertificateController) maybeAutoApproveCSR(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, error) {
 | 
				
			||||||
 | 
						// short-circuit if we're not auto-approving
 | 
				
			||||||
 | 
						if cc.approveAllKubeletCSRsForGroup == "" {
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// short-circuit if we're already approved or denied
 | 
				
			||||||
 | 
						if approved, denied := getCertApprovalCondition(&csr.Status); approved || denied {
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isKubeletBootstrapGroup := false
 | 
				
			||||||
 | 
						for _, g := range csr.Spec.Groups {
 | 
				
			||||||
 | 
							if g == cc.approveAllKubeletCSRsForGroup {
 | 
				
			||||||
 | 
								isKubeletBootstrapGroup = true
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !isKubeletBootstrapGroup {
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x509cr, err := utilcertificates.ParseCertificateRequestObject(csr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Errorf("unable to parse csr %q: %v", csr.ObjectMeta.Name, err)
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !reflect.DeepEqual([]string{"system:nodes"}, x509cr.Subject.Organization) {
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !strings.HasPrefix(x509cr.Subject.CommonName, "system:node:") {
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(x509cr.DNSNames)+len(x509cr.EmailAddresses)+len(x509cr.IPAddresses) != 0 {
 | 
				
			||||||
 | 
							return csr, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csr.Status.Conditions = append(csr.Status.Conditions, certificates.CertificateSigningRequestCondition{
 | 
				
			||||||
 | 
							Type:    certificates.CertificateApproved,
 | 
				
			||||||
 | 
							Reason:  "AutoApproved",
 | 
				
			||||||
 | 
							Message: "Auto approving of all kubelet CSRs is enabled on the controller manager",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return cc.kubeClient.Certificates().CertificateSigningRequests().UpdateApproval(csr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,9 +21,18 @@ import "k8s.io/kubernetes/pkg/apis/certificates"
 | 
				
			|||||||
// IsCertificateRequestApproved returns true if a certificate request has the
 | 
					// IsCertificateRequestApproved returns true if a certificate request has the
 | 
				
			||||||
// "Approved" condition and no "Denied" conditions; false otherwise.
 | 
					// "Approved" condition and no "Denied" conditions; false otherwise.
 | 
				
			||||||
func IsCertificateRequestApproved(csr *certificates.CertificateSigningRequest) bool {
 | 
					func IsCertificateRequestApproved(csr *certificates.CertificateSigningRequest) bool {
 | 
				
			||||||
	status := csr.Status
 | 
						approved, denied := getCertApprovalCondition(&csr.Status)
 | 
				
			||||||
	var approved, denied bool
 | 
						return approved && !denied
 | 
				
			||||||
	// TODO: incorporate timestamps
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsCertificateRequestDenied returns true if a certificate request has the
 | 
				
			||||||
 | 
					// "Denied" conditions; false otherwise.
 | 
				
			||||||
 | 
					func IsCertificateRequestDenied(csr *certificates.CertificateSigningRequest) bool {
 | 
				
			||||||
 | 
						_, denied := getCertApprovalCondition(&csr.Status)
 | 
				
			||||||
 | 
						return denied
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCertApprovalCondition(status *certificates.CertificateSigningRequestStatus) (approved bool, denied bool) {
 | 
				
			||||||
	for _, c := range status.Conditions {
 | 
						for _, c := range status.Conditions {
 | 
				
			||||||
		if c.Type == certificates.CertificateApproved {
 | 
							if c.Type == certificates.CertificateApproved {
 | 
				
			||||||
			approved = true
 | 
								approved = true
 | 
				
			||||||
@@ -32,5 +41,5 @@ func IsCertificateRequestApproved(csr *certificates.CertificateSigningRequest) b
 | 
				
			|||||||
			denied = true
 | 
								denied = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return approved && !denied
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user