github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/pki/cert-manager.go (about) 1 package pki 2 3 import ( 4 "github.com/jenkins-x/jx-logging/pkg/log" 5 "github.com/jenkins-x/jx/v2/pkg/kube" 6 "github.com/jenkins-x/jx/v2/pkg/util" 7 certmng "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1" 8 certclient "github.com/jetstack/cert-manager/pkg/client/clientset/versioned" 9 "github.com/pkg/errors" 10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 ) 12 13 const ( 14 // CertManagerNamespace indicates the namespace where is cert-manager deployed 15 CertManagerNamespace = "cert-manager" 16 // CertManagerDeployment indicates the name of the cert-manager deployment 17 CertManagerDeployment = "cert-manager" 18 // CertManagerReleaseName indicates the release name for cert-manager chart 19 CertManagerReleaseName = "cert-manager" 20 // CertManagerChartOwner is the owner of the cert-manager chart repo 21 CertManagerChartOwner = "jetstack" 22 // CertManagerChartURL is the URL for the repo containing the cert-manager chart 23 CertManagerChartURL = "https://charts.jetstack.io" 24 // CertManagerChart name of the cert-manager chart 25 CertManagerChart = "jetstack/cert-manager" 26 // CertManagerCRDsFile files which contains the cert-manager CRDs 27 CertManagerCRDsFile = "https://raw.githubusercontent.com/jetstack/cert-manager/v0.9.1/deploy/manifests/00-crds.yaml" 28 29 // CertManagerIssuerProd name of the production issuer 30 CertManagerIssuerProd = "letsencrypt-prod" 31 certManagerIssuerProdServer = "https://acme-v02.api.letsencrypt.org/directory" 32 33 // CertManagerIssuerStaging name of the staging issuer 34 CertManagerIssuerStaging = "letsencrypt-staging" 35 certManagerIssuerStagingServer = "https://acme-staging-v02.api.letsencrypt.org/directory" 36 ) 37 38 // CleanCertManagerResources removed the cert-manager resources from the given namespaces 39 func CleanCertManagerResources(certclient certclient.Interface, ns string, ic kube.IngressConfig) error { 40 if ic.Issuer == CertManagerIssuerProd { 41 _, err := certclient.CertmanagerV1alpha1().Issuers(ns).Get(CertManagerIssuerProd, metav1.GetOptions{}) 42 if err == nil { 43 err := certclient.CertmanagerV1alpha1().Issuers(ns).Delete(CertManagerIssuerProd, &metav1.DeleteOptions{}) 44 if err != nil { 45 return errors.Wrapf(err, "deleting cert-manager issuer %q", CertManagerIssuerProd) 46 } 47 } 48 _ = certclient.CertmanagerV1alpha1().Certificates(ns).Delete(CertManagerIssuerProd, &metav1.DeleteOptions{}) 49 } else { 50 _, err := certclient.CertmanagerV1alpha1().Issuers(ns).Get(CertManagerIssuerStaging, metav1.GetOptions{}) 51 if err == nil { 52 err := certclient.CertmanagerV1alpha1().Issuers(ns).Delete(CertManagerIssuerStaging, &metav1.DeleteOptions{}) 53 if err != nil { 54 return errors.Wrapf(err, "deleting cert-manager issuer %q", CertManagerIssuerStaging) 55 } 56 } 57 _ = certclient.CertmanagerV1alpha1().Certificates(ns).Delete(CertManagerIssuerStaging, &metav1.DeleteOptions{}) 58 } 59 return nil 60 } 61 62 // CreateIssuer creates a cert-manager issuer according with the ingress configuration 63 func CreateIssuer(certclient certclient.Interface, ns string, ic kube.IngressConfig) error { 64 if ic.Issuer == CertManagerIssuerProd { 65 _, err := certclient.CertmanagerV1alpha1().Issuers(ns).Get(CertManagerIssuerProd, metav1.GetOptions{}) 66 if err != nil { 67 _, err := certclient.CertmanagerV1alpha1().Issuers(ns).Create( 68 issuer(CertManagerIssuerProd, certManagerIssuerProdServer, ic.Email)) 69 if err != nil { 70 return errors.Wrapf(err, "creating cert-manager issuer %q", CertManagerIssuerProd) 71 } 72 } 73 } else { 74 _, err := certclient.CertmanagerV1alpha1().Issuers(ns).Get(CertManagerIssuerStaging, metav1.GetOptions{}) 75 if err != nil { 76 _, err := certclient.CertmanagerV1alpha1().Issuers(ns).Create( 77 issuer(CertManagerIssuerStaging, certManagerIssuerStagingServer, ic.Email)) 78 if err != nil { 79 return errors.Wrapf(err, "creating cert-manager issuer %q", CertManagerIssuerStaging) 80 } 81 } 82 } 83 84 return nil 85 } 86 87 func issuer(name string, server string, email string) *certmng.Issuer { 88 return &certmng.Issuer{ 89 ObjectMeta: metav1.ObjectMeta{ 90 Name: name, 91 }, 92 Spec: certmng.IssuerSpec{ 93 IssuerConfig: certmng.IssuerConfig{ 94 ACME: &certmng.ACMEIssuer{ 95 Email: email, 96 Server: server, 97 SkipTLSVerify: false, 98 PrivateKey: certmng.SecretKeySelector{ 99 LocalObjectReference: certmng.LocalObjectReference{ 100 Name: name, 101 }, 102 }, 103 HTTP01: &certmng.ACMEIssuerHTTP01Config{}, 104 }, 105 }, 106 }, 107 Status: certmng.IssuerStatus{ 108 Conditions: []certmng.IssuerCondition{}, 109 }, 110 } 111 } 112 113 // CreateCertManagerResources creates the cert-manager resources such as issuer in the target namespace 114 func CreateCertManagerResources(certclient certclient.Interface, targetNamespace string, ic kube.IngressConfig) error { 115 if !ic.TLS { 116 return nil 117 } 118 119 // do not recreate the issuer if it is already there and correctly configured 120 if alreadyConfigured(certclient, targetNamespace, ic) { 121 return nil 122 } 123 124 err := CleanCertManagerResources(certclient, targetNamespace, ic) 125 if err != nil { 126 return errors.Wrapf(err, "cleaning the cert-manager resources from namespace %q", targetNamespace) 127 } 128 129 err = CreateIssuer(certclient, targetNamespace, ic) 130 if err != nil { 131 return errors.Wrapf(err, "creating the cert-manager issuer %s/%s", targetNamespace, ic.Issuer) 132 } 133 134 return nil 135 } 136 137 // alreadyConfigured checks if cert-manager resources are already configured and match with the ingress configuration 138 func alreadyConfigured(certClient certclient.Interface, targetNamespace string, ingressConfig kube.IngressConfig) bool { 139 issuer, err := certClient.CertmanagerV1alpha1().Issuers(targetNamespace).Get(ingressConfig.Issuer, metav1.GetOptions{}) 140 if err != nil { 141 log.Logger().Infof("Certificate issuer %s does not exist. Creating...", util.ColorInfo(ingressConfig.Issuer)) 142 return false 143 } 144 // ingress and issuer email must match 145 if issuer.Spec.ACME.Email != ingressConfig.Email { 146 issuer.Spec.ACME.Email = ingressConfig.Email 147 _, err := certClient.CertmanagerV1alpha1().Issuers(targetNamespace).Update(issuer) 148 if err != nil { 149 // can not update the issuer, let's assume it needs recreation 150 log.Logger().Infof("Certificate issuer %s can not be updated. Recreating...", util.ColorInfo(ingressConfig.Issuer)) 151 return false 152 } 153 } 154 log.Logger().Infof("Certificate issuer %s already configured.", util.ColorInfo(ingressConfig.Issuer)) 155 return true 156 }