diff --git a/cmd/initContainer/main.go b/cmd/initContainer/main.go index aaf6ee8fce..aed5c4402d 100644 --- a/cmd/initContainer/main.go +++ b/cmd/initContainer/main.go @@ -6,6 +6,7 @@ package main import ( "context" "flag" + "fmt" "os" "sync" "time" @@ -15,6 +16,7 @@ import ( "github.com/kyverno/kyverno/pkg/leaderelection" "github.com/kyverno/kyverno/pkg/policyreport" "github.com/kyverno/kyverno/pkg/signal" + "github.com/kyverno/kyverno/pkg/tls" "github.com/kyverno/kyverno/pkg/utils" coord "k8s.io/api/coordination/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -119,8 +121,55 @@ func main() { failure := false run := func() { - _, err := kubeClientLeaderElection.CoordinationV1().Leases(getKyvernoNameSpace()).Get(ctx, "kyvernopre-lock", v1.GetOptions{}) + certProps, err := tls.GetTLSCertProps(clientConfig) + if err != nil { + log.Log.Info("failed to get cert properties: %v", err.Error()) + os.Exit(1) + } + depl, err := client.GetResource("", "Deployment", getKyvernoNameSpace(), config.KyvernoDeploymentName) + deplHash := "" + if err != nil { + log.Log.Info("failed to fetch deployment '%v': %v", config.KyvernoDeploymentName, err.Error()) + os.Exit(1) + } + deplHash = fmt.Sprintf("%v", depl.GetUID()) + + name := tls.GenerateRootCASecretName(certProps) + secretUnstr, err := client.GetResource("", "Secret", getKyvernoNameSpace(), name) + if err != nil { + log.Log.Info("failed to fetch secret '%v': %v", name, err.Error()) + + if !errors.IsNotFound(err) { + os.Exit(1) + } + } else if tls.CanAddAnnotationToSecret(deplHash, secretUnstr) { + secretUnstr.SetAnnotations(map[string]string{tls.MasterDeploymentUID: deplHash}) + _, err = client.UpdateResource("", "Secret", certProps.Namespace, secretUnstr, false) + if err != nil { + log.Log.Info("failed to update cert: %v", err.Error()) + os.Exit(1) + } + } + + name = tls.GenerateTLSPairSecretName(certProps) + secretUnstr, err = client.GetResource("", "Secret", getKyvernoNameSpace(), name) + if err != nil { + log.Log.Info("failed to fetch secret '%v': %v", name, err.Error()) + + if !errors.IsNotFound(err) { + os.Exit(1) + } + } else if tls.CanAddAnnotationToSecret(deplHash, secretUnstr) { + secretUnstr.SetAnnotations(map[string]string{tls.MasterDeploymentUID: deplHash}) + _, err = client.UpdateResource("", "Secret", certProps.Namespace, secretUnstr, false) + if err != nil { + log.Log.Info("failed to update cert: %v", err.Error()) + os.Exit(1) + } + } + + _, err = kubeClientLeaderElection.CoordinationV1().Leases(getKyvernoNameSpace()).Get(ctx, "kyvernopre-lock", v1.GetOptions{}) if err != nil { log.Log.Info("Lease 'kyvernopre-lock' not found. Starting clean-up...") } else { diff --git a/pkg/tls/certRenewer.go b/pkg/tls/certRenewer.go index 95dd3cb971..380891f704 100644 --- a/pkg/tls/certRenewer.go +++ b/pkg/tls/certRenewer.go @@ -117,7 +117,7 @@ func (c *CertRenewer) buildTLSPemPairAndWriteToSecrets(props CertificateProps, s // WriteCACertToSecret stores the CA cert in secret func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps) error { logger := c.log.WithName("CAcert") - name := generateRootCASecretName(props) + name := GenerateRootCASecretName(props) depl, err := c.client.GetResource("", "Deployment", props.Namespace, config.KyvernoDeploymentName) @@ -126,16 +126,7 @@ func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps deplHash = fmt.Sprintf("%v", depl.GetUID()) } - var deplHashSec string = "default" - var ok, managedByKyverno bool - secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name) - if err == nil { - if label, ok := secretUnstr.GetLabels()[ManagedByLabel]; ok { - managedByKyverno = label == "kyverno" - } - deplHashSec, ok = secretUnstr.GetAnnotations()[MasterDeploymentUID] - } secret := &v1.Secret{ TypeMeta: metav1.TypeMeta{ @@ -167,7 +158,7 @@ func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps } } return err - } else if managedByKyverno && (!ok || deplHashSec != deplHash) { + } else if CanAddAnnotationToSecret(deplHash, secretUnstr) { _, err = c.client.UpdateResource("", "Secret", props.Namespace, secret, false) if err == nil { logger.Info("secret updated", "name", name, "namespace", props.Namespace) @@ -199,7 +190,7 @@ func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps func (c *CertRenewer) WriteTLSPairToSecret(props CertificateProps, pemPair *PemPair) error { logger := c.log.WithName("WriteTLSPair") - name := generateTLSPairSecretName(props) + name := GenerateTLSPairSecretName(props) depl, err := c.client.GetResource("", "Deployment", props.Namespace, config.KyvernoDeploymentName) @@ -208,16 +199,7 @@ func (c *CertRenewer) WriteTLSPairToSecret(props CertificateProps, pemPair *PemP deplHash = fmt.Sprintf("%v", depl.GetUID()) } - var deplHashSec string = "default" - var ok, managedByKyverno bool - secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name) - if err == nil { - if label, ok := secretUnstr.GetLabels()[ManagedByLabel]; ok { - managedByKyverno = label == "kyverno" - } - deplHashSec, ok = secretUnstr.GetAnnotations()[MasterDeploymentUID] - } secretPtr := &v1.Secret{ TypeMeta: metav1.TypeMeta{ @@ -249,7 +231,7 @@ func (c *CertRenewer) WriteTLSPairToSecret(props CertificateProps, pemPair *PemP } } return err - } else if managedByKyverno && (!ok || deplHashSec != deplHash) { + } else if CanAddAnnotationToSecret(deplHash, secretUnstr) { _, err = c.client.UpdateResource("", "Secret", props.Namespace, secretPtr, false) if err == nil { logger.Info("secret updated", "name", name, "namespace", props.Namespace) @@ -337,8 +319,8 @@ func (c *CertRenewer) ValidCert() (bool, error) { return false, nil } var managedByKyverno bool - snameTLS := generateTLSPairSecretName(certProps) - snameCA := generateRootCASecretName(certProps) + snameTLS := GenerateTLSPairSecretName(certProps) + snameCA := GenerateRootCASecretName(certProps) unstrSecret, err := c.client.GetResource("", "Secret", certProps.Namespace, snameTLS) if err != nil { return false, nil @@ -444,10 +426,22 @@ func IsKyvernoInRollingUpdate(deploy map[string]interface{}, logger logr.Logger) return false } -func generateTLSPairSecretName(props CertificateProps) string { +func GenerateTLSPairSecretName(props CertificateProps) string { return generateInClusterServiceName(props) + ".kyverno-tls-pair" } -func generateRootCASecretName(props CertificateProps) string { +func GenerateRootCASecretName(props CertificateProps) string { return generateInClusterServiceName(props) + ".kyverno-tls-ca" } + +func CanAddAnnotationToSecret(deplHash string, secret *unstructured.Unstructured) bool { + var deplHashSec string = "default" + var ok, managedByKyverno bool + + if label, ok := secret.GetLabels()[ManagedByLabel]; ok { + managedByKyverno = label == "kyverno" + } + deplHashSec, ok = secret.GetAnnotations()[MasterDeploymentUID] + + return managedByKyverno && (!ok || deplHashSec != deplHash) +} diff --git a/pkg/tls/reader.go b/pkg/tls/reader.go index d2ea96612e..25c6a9843d 100644 --- a/pkg/tls/reader.go +++ b/pkg/tls/reader.go @@ -32,7 +32,7 @@ func ReadRootCASecret(restConfig *rest.Config, client *client.Client) (result [] var deplHashSec string = "default" var ok, managedByKyverno bool - sname := generateRootCASecretName(certProps) + sname := GenerateRootCASecretName(certProps) stlsca, err := client.GetResource("", "Secret", certProps.Namespace, sname) if err != nil { return nil, err @@ -76,7 +76,7 @@ func ReadTLSPair(restConfig *rest.Config, client *client.Client) (*PemPair, erro var deplHashSec string = "default" var ok, managedByKyverno bool - sname := generateTLSPairSecretName(certProps) + sname := GenerateTLSPairSecretName(certProps) unstrSecret, err := client.GetResource("", "Secret", certProps.Namespace, sname) if err != nil { return nil, fmt.Errorf("failed to get secret %s/%s: %v", certProps.Namespace, sname, err) @@ -93,7 +93,7 @@ func ReadTLSPair(restConfig *rest.Config, client *client.Client) (*PemPair, erro // As the root CA used to sign the certificate is required for webhook configuration, check if the corresponding secret is created annotations := unstrSecret.GetAnnotations() if _, ok := annotations[SelfSignedAnnotation]; ok { - sname := generateRootCASecretName(certProps) + sname := GenerateRootCASecretName(certProps) _, err := client.GetResource("", "Secret", certProps.Namespace, sname) if err != nil { return nil, fmt.Errorf("rootCA secret is required while using self-signed certificate TLS pair, defaulting to generating new TLS pair %s/%s", certProps.Namespace, sname)