1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

Fix TLS inconsitency in HA (#2910)

* Fix TLS inconsitency in HA

Signed-off-by: Kumar Mallikarjuna <kumar@nirmata.com>

* Add error checks

Signed-off-by: Kumar Mallikarjuna <kumar@nirmata.com>

* Remove rendundant err definitions

Signed-off-by: Kumar Mallikarjuna <kumar@nirmata.com>

* Handle all Secret errors

Signed-off-by: Kumar Mallikarjuna <kumar@nirmata.com>
This commit is contained in:
Kumar Mallikarjuna 2022-01-06 14:41:16 +05:30 committed by GitHub
parent 1208e51b68
commit 214f338ec3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 142 additions and 51 deletions

View file

@ -14,6 +14,7 @@ import (
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
k8errors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/rest"
@ -21,7 +22,8 @@ import (
const (
// ManagedByLabel is added to Kyverno managed secrets
ManagedByLabel string = "cert.kyverno.io/managed-by"
ManagedByLabel string = "cert.kyverno.io/managed-by"
MasterDeploymentUID string = "cert.kyverno.io/master-deployment-uid"
SelfSignedAnnotation string = "self-signed-cert"
RootCAKey string = "rootCA.crt"
@ -117,32 +119,58 @@ func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps
logger := c.log.WithName("CAcert")
name := generateRootCASecretName(props)
secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name)
if err != nil {
secret := &v1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: props.Namespace,
Annotations: map[string]string{
SelfSignedAnnotation: "true",
},
Labels: map[string]string{
ManagedByLabel: "kyverno",
},
},
Data: map[string][]byte{
RootCAKey: caPEM.Certificate,
},
Type: v1.SecretTypeOpaque,
}
depl, err := c.client.GetResource("", "Deployment", props.Namespace, config.KyvernoDeploymentName)
_, err := c.client.CreateResource("", "Secret", props.Namespace, secret, false)
deplHash := ""
if err == nil {
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{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: props.Namespace,
Annotations: map[string]string{
SelfSignedAnnotation: "true",
MasterDeploymentUID: deplHash,
},
Labels: map[string]string{
ManagedByLabel: "kyverno",
},
},
Data: map[string][]byte{
RootCAKey: caPEM.Certificate,
},
Type: v1.SecretTypeOpaque,
}
if err != nil {
if k8errors.IsNotFound(err) {
_, err = c.client.CreateResource("", "Secret", props.Namespace, secret, false)
if err == nil {
logger.Info("secret created", "name", name, "namespace", props.Namespace)
}
}
return err
} else if managedByKyverno && (!ok || deplHashSec != deplHash) {
_, err = c.client.UpdateResource("", "Secret", props.Namespace, secret, false)
if err == nil {
logger.Info("secret created", "name", name, "namespace", props.Namespace)
logger.Info("secret updated", "name", name, "namespace", props.Namespace)
}
return err
}
@ -154,7 +182,7 @@ func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps
dataMap := map[string]interface{}{
RootCAKey: base64.StdEncoding.EncodeToString(caPEM.Certificate)}
if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
if err = unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
return err
}
@ -172,30 +200,59 @@ func (c *CertRenewer) WriteTLSPairToSecret(props CertificateProps, pemPair *PemP
logger := c.log.WithName("WriteTLSPair")
name := generateTLSPairSecretName(props)
secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name)
if err != nil {
secret := &v1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: props.Namespace,
Labels: map[string]string{
ManagedByLabel: "kyverno",
},
},
Data: map[string][]byte{
v1.TLSCertKey: pemPair.Certificate,
v1.TLSPrivateKeyKey: pemPair.PrivateKey,
},
Type: v1.SecretTypeTLS,
}
_, err := c.client.CreateResource("", "Secret", props.Namespace, secret, false)
depl, err := c.client.GetResource("", "Deployment", props.Namespace, config.KyvernoDeploymentName)
deplHash := ""
if err == nil {
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{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: props.Namespace,
Annotations: map[string]string{
MasterDeploymentUID: deplHash,
},
Labels: map[string]string{
ManagedByLabel: "kyverno",
},
},
Data: map[string][]byte{
v1.TLSCertKey: pemPair.Certificate,
v1.TLSPrivateKeyKey: pemPair.PrivateKey,
},
Type: v1.SecretTypeTLS,
}
if err != nil {
if k8errors.IsNotFound(err) {
_, err = c.client.CreateResource("", "Secret", props.Namespace, secretPtr, false)
if err == nil {
logger.Info("secret created", "name", name, "namespace", props.Namespace)
}
}
return err
} else if managedByKyverno && (!ok || deplHashSec != deplHash) {
_, err = c.client.UpdateResource("", "Secret", props.Namespace, secretPtr, false)
if err == nil {
logger.Info("secret created", "name", name, "namespace", props.Namespace)
logger.Info("secret updated", "name", name, "namespace", props.Namespace)
}
return err
}

View file

@ -22,12 +22,30 @@ func ReadRootCASecret(restConfig *rest.Config, client *client.Client) (result []
return nil, errors.Wrap(err, "failed to get TLS Cert Properties")
}
depl, err := client.GetResource("", "Deployment", certProps.Namespace, config.KyvernoDeploymentName)
deplHash := ""
if err == nil {
deplHash = fmt.Sprintf("%v", depl.GetUID())
}
var deplHashSec string = "default"
var ok, managedByKyverno bool
sname := generateRootCASecretName(certProps)
stlsca, err := client.GetResource("", "Secret", certProps.Namespace, sname)
if err != nil {
return nil, err
}
if label, ok := stlsca.GetLabels()[ManagedByLabel]; ok {
managedByKyverno = label == "kyverno"
}
deplHashSec, ok = stlsca.GetAnnotations()[MasterDeploymentUID]
if managedByKyverno && (!ok || deplHashSec != deplHash) {
return nil, fmt.Errorf("outdated secret")
}
tlsca, err := convertToSecret(stlsca)
if err != nil {
return nil, errors.Wrapf(err, "failed to convert secret %s/%s", certProps.Namespace, sname)
@ -48,11 +66,28 @@ func ReadTLSPair(restConfig *rest.Config, client *client.Client) (*PemPair, erro
return nil, errors.Wrap(err, "failed to get TLS Cert Properties")
}
depl, err := client.GetResource("", "Deployment", certProps.Namespace, config.KyvernoDeploymentName)
deplHash := ""
if err == nil {
deplHash = fmt.Sprintf("%v", depl.GetUID())
}
var deplHashSec string = "default"
var ok, managedByKyverno bool
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)
}
if label, ok := unstrSecret.GetLabels()[ManagedByLabel]; ok {
managedByKyverno = label == "kyverno"
}
deplHashSec, ok = unstrSecret.GetAnnotations()[MasterDeploymentUID]
if managedByKyverno && (!ok || deplHashSec != deplHash) {
return nil, fmt.Errorf("outdated secret")
}
// If secret contains annotation 'self-signed-cert', then it's created using helper scripts to setup self-signed certificates.
// As the root CA used to sign the certificate is required for webhook configuration, check if the corresponding secret is created

View file

@ -248,10 +248,9 @@ func (wrc *Register) cleanupKyvernoResource() bool {
logger := wrc.log.WithName("cleanupKyvernoResource")
deploy, err := wrc.client.GetResource("", "Deployment", deployNamespace, deployName)
if err != nil {
logger.Error(err, "failed to get deployment, cleanup kyverno resources anyway")
return true
logger.Error(err, "failed to get deployment, not cleaning up kyverno resources")
return false
}
if deploy.GetDeletionTimestamp() != nil {
logger.Info("Kyverno is terminating, cleanup Kyverno resources")
return true