From b61afb36ac8114075c12e3ee6fff8ed502208a6e Mon Sep 17 00:00:00 2001 From: Vivek Thrivikraman Date: Thu, 9 Sep 2021 17:25:30 +0530 Subject: [PATCH] Use self signed certificate --- go.sum | 3 ++ pkg/installer/installer.go | 90 +++++++++++++------------------------- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/go.sum b/go.sum index 77f42ce1..8ed77a94 100644 --- a/go.sum +++ b/go.sum @@ -208,13 +208,16 @@ github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5 github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/weppos/publicsuffix-go v0.4.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= +github.com/weppos/publicsuffix-go v0.5.0 h1:rutRtjBJViU/YjcI5d80t4JAVvDltS6bciJg2K1HrLU= github.com/weppos/publicsuffix-go v0.5.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= +github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e h1:mvOa4+/DXStR4ZXOks/UsjeFdn5O5JpLUtzqk9U8xXw= github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e/go.mod h1:w7kd3qXHh8FNaczNjslXqvFQiv5mMWRXlL9klTUAHc8= +github.com/zmap/zlint v0.0.0-20190806154020-fd021b4cfbeb h1:vxqkjztXSaPVDc8FQCdHTaejm2x747f6yPbnu1h2xkg= github.com/zmap/zlint v0.0.0-20190806154020-fd021b4cfbeb/go.mod h1:29UiAJNsiVdvTBFCJW8e3q6dcDbOoPkhMgttOSCIMMY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index 93af6cc1..015e7cf0 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -16,16 +16,19 @@ package installer import ( "context" + "fmt" "io/ioutil" "strings" - "time" "github.com/cloudflare/cfssl/csr" + "github.com/cloudflare/cfssl/helpers" + "github.com/cloudflare/cfssl/initca" + cfsigner "github.com/cloudflare/cfssl/signer" + "github.com/cloudflare/cfssl/signer/local" "github.com/golang/glog" "github.com/pkg/errors" arv1 "k8s.io/api/admissionregistration/v1" - "k8s.io/api/certificates/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -40,6 +43,7 @@ var ( ) const keyBitLength = 3072 +const CAExpiration = "630720000s" func generateCSR() ([]byte, []byte, error) { glog.Infof("generating Certificate Signing Request") @@ -55,66 +59,28 @@ func generateCSR() ([]byte, []byte, error) { return csr.ParseRequest(certRequest) } -func getSignedCertificate(request []byte) ([]byte, error) { - csrName := strings.Join([]string{prefix, "csr"}, "-") - csr, err := clientset.CertificatesV1beta1().CertificateSigningRequests().Get(context.TODO(), csrName, metav1.GetOptions{}) - if csr != nil || err == nil { - glog.Infof("CSR %s already exists, removing it first", csrName) - clientset.CertificatesV1beta1().CertificateSigningRequests().Delete(context.TODO(), csrName, metav1.DeleteOptions{}) - } - - glog.Infof("creating new CSR %s", csrName) - /* build Kubernetes CSR object */ - csr = &v1beta1.CertificateSigningRequest{} - csr.ObjectMeta.Name = csrName - csr.ObjectMeta.Namespace = namespace - csr.Spec.Request = request - csr.Spec.Groups = []string{"system:authenticated"} - csr.Spec.Usages = []v1beta1.KeyUsage{v1beta1.UsageDigitalSignature, v1beta1.UsageServerAuth, v1beta1.UsageKeyEncipherment} - - /* push CSR to Kubernetes API server */ - csr, err = clientset.CertificatesV1beta1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{}) +func generateCACertificate() (*local.Signer, []byte, error) { + certRequest := csr.New() + certRequest.KeyRequest = &csr.KeyRequest{A: "rsa", S: keyBitLength} + certRequest.CN = "Kubernetes NRI" + certRequest.CA = &csr.CAConfig{Expiry: CAExpiration} + cert, _, key, err := initca.New(certRequest) if err != nil { - return nil, errors.Wrap(err, "error creating CSR in Kubernetes API: %s") + return nil, nil, fmt.Errorf("creating CA certificate failed: %v", err) } - glog.Infof("CSR pushed to the Kubernetes API") - - if csr.Status.Certificate != nil { - glog.Infof("using already issued certificate for CSR %s", csrName) - return csr.Status.Certificate, nil + parsedKey, err := helpers.ParsePrivateKeyPEM(key) + if err != nil { + return nil, nil, fmt.Errorf("parsing private key pem failed: %v", err) } - /* approve certificate in K8s API */ - csr.ObjectMeta.Name = csrName - csr.ObjectMeta.Namespace = namespace - csr.Status.Conditions = append(csr.Status.Conditions, v1beta1.CertificateSigningRequestCondition{ - Type: v1beta1.CertificateApproved, - Reason: "Approved by net-attach-def admission controller installer", - Message: "This CSR was approved by net-attach-def admission controller installer.", - LastUpdateTime: metav1.Now(), - }) - _, err = clientset.CertificatesV1beta1().CertificateSigningRequests().UpdateApproval(context.TODO(), csr, metav1.UpdateOptions{}) - glog.Infof("certificate approval sent") + parsedCert, err := helpers.ParseCertificatePEM(cert) if err != nil { - return nil, errors.Wrap(err, "error approving CSR in Kubernetes API") + return nil, nil, fmt.Errorf("parse certificate failed: %v", err) } - - /* wait for the cert to be issued */ - glog.Infof("waiting for the signed certificate to be issued...") - start := time.Now() - for range time.Tick(time.Second) { - csr, err = clientset.CertificatesV1beta1().CertificateSigningRequests().Get(context.TODO(), csrName, metav1.GetOptions{}) - if err != nil { - return nil, errors.Wrap(err, "error getting signed ceritificate from the API server") - } - if csr.Status.Certificate != nil { - return csr.Status.Certificate, nil - } - if time.Since(start) > 60*time.Second { - break - } + signer, err := local.NewSigner(parsedKey, parsedCert, cfsigner.DefaultSigAlgo(parsedKey), nil) + if err != nil { + return nil, nil, fmt.Errorf("failed to create signer: %v", err) } - - return nil, errors.New("error getting certificate from the API server: request timed out - verify that Kubernetes certificate signer is setup, more at https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/#a-note-to-cluster-administrators") + return signer, cert, nil } func writeToFile(certificate, key []byte, certFilename, keyFilename string) error { @@ -256,6 +222,11 @@ func Install(k8sNamespace, namePrefix, failurePolicy string) { namespace = k8sNamespace prefix = namePrefix + signer, caCertificate, err := generateCACertificate() + if err != nil { + glog.Fatalf("Error generating CA certificate and signer: %s", err) + } + /* generate CSR and private key */ csr, key, err := generateCSR() if err != nil { @@ -263,8 +234,9 @@ func Install(k8sNamespace, namePrefix, failurePolicy string) { } glog.Infof("raw CSR and private key successfully created") - /* obtain signed certificate */ - certificate, err := getSignedCertificate(csr) + certificate, err := signer.Sign(cfsigner.SignRequest{ + Request: string(csr), + }) if err != nil { glog.Fatalf("error getting signed certificate: %s", err) } @@ -277,7 +249,7 @@ func Install(k8sNamespace, namePrefix, failurePolicy string) { glog.Infof("certificate and key written to files") /* create webhook configurations */ - err = createMutatingWebhookConfiguration(certificate, failurePolicy) + err = createMutatingWebhookConfiguration(caCertificate, failurePolicy) if err != nil { glog.Fatalf("error creating mutating webhook configuration: %s", err) }