func (r *EncryptionKeysReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) {
	log := log.WithValues("secretNamespace", request.Namespace, "secret", request.Name)
	log.Info("Reconciling a Secret")

	clusterName := request.Namespace

	// The cache configuration of SelectorsByObject should prevent this from happening, but add this as a precaution.
	if request.Name != propagator.EncryptionKeySecret {
		log.Info("Got a reconciliation request for an unexpected Secret. This should have been filtered out.")

		return reconcile.Result{}, nil
	}

	secret := &corev1.Secret{}

	err := r.Get(ctx, request.NamespacedName, secret)
	if err != nil {
		if k8serrors.IsNotFound(err) {
			log.V(2).Info("The Secret was not found on the server. Doing nothing.")

			return ctrl.Result{}, nil
		}

		log.Error(err, "Failed to get the Secret from the server. Will retry the reconcile request.")

		return ctrl.Result{}, err
	}

	annotations := secret.GetAnnotations()
	if strings.EqualFold(annotations[DisableRotationAnnotation], "true") {
		log.Info(
			"Encountered an encryption key Secret with key rotation disabled. Will trigger a policy template update.",
			"annotation", DisableRotationAnnotation,
			"value", annotations[DisableRotationAnnotation],
		)

		// In case the key was manually rotated, trigger a template update
		r.triggerTemplateUpdate(ctx, clusterName, secret)

		return reconcile.Result{}, nil
	}

	lastRotatedTS := annotations[propagator.LastRotatedAnnotation]
	log = log.WithValues("annotation", propagator.LastRotatedAnnotation, "value", lastRotatedTS)

	var nextRotation time.Duration

	if lastRotatedTS == "" {
		log.Info("The annotation is not set. Will rotate the key now.")

		nextRotation = 0
	} else {
		nextRotation, err = r.getNextRotationFromNow(secret)
		if err != nil {
			log.Error(err, "The annotation cannot be parsed. Will rotate the key now.")
			nextRotation = 0
		}
	}

	_, err = aes.NewCipher(secret.Data["key"])
	if err != nil {
		log.Error(err, "The encryption key in the Secret is invalid. Will rotate the key now.")

		nextRotation = 0
		// Set this to a null value so the bad key doesn't get stored as the previous key
		secret.Data["key"] = []byte{}
	}

	if nextRotation > 0 {
		// previousKey only needs to be checked if there won't be a rotation since it would get overwritten anyways
		if len(secret.Data["previousKey"]) > 0 {
			// If previousKey is invalid, it'll cause go-template-utils to fail on the managed cluster, so remove it if
			// a user changed this accidentally
			_, err = aes.NewCipher(secret.Data["previousKey"])
			if err != nil {
				log.Info("The previous encryption key in the Secret is invalid. Will remove it.")

				secret.Data["previousKey"] = []byte{}

				err := r.Update(ctx, secret)
				if err != nil {
					log.Error(err, "Failed to update the Secret. Will retry the request.")

					return reconcile.Result{}, err
				}
			}
		}

		log.V(2).Info("The key is not yet ready to be rotated")

		// Requeueing the same object multiple times is safe as the queue will drop any scheduled
		// requeues in favor of this one
		// https://github.com/kubernetes-sigs/controller-runtime/blob/7ba3e559790c5e3543002a0d9670b4cef3ccf743/pkg/internal/controller/controller.go#L323-L324
		return reconcile.Result{RequeueAfter: nextRotation}, nil
	}

	log.V(1).Info("Rotating the encryption key")

	err = r.rotateKey(ctx, secret)
	if err != nil {
		log.Error(err, "Failed to rotate the encryption key. Will retry the request.")

		return reconcile.Result{}, err
	}

	r.triggerTemplateUpdate(ctx, clusterName, secret)

	// The error is ignored since this can't fail since the annotation value was just set to a valid value
	nextRotation, _ = r.getNextRotationFromNow(secret)

	log.Info("Rotated the encryption key successfully", "nextRotation", nextRotation)

	return reconcile.Result{RequeueAfter: nextRotation}, nil
}
// Reconcile watches all "policy-encryption-key" Secrets on the Hub cluster. This periodically rotates the keys
// and resolves invalid modifications made to the Secret.
Reconcile watches all "policy-encryption-key" Secrets on the Hub cluster. This periodically rotates the keys
and resolves invalid modifications made to the Secret.
// Reconcile watches all " policy - encryption - key " Secrets on the Hub cluster . This periodically rotates the keys // and resolves invalid modifications made to the Secret .
func (r *EncryptionKeysReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) {
	log := log.WithValues("secretNamespace", request.Namespace, "secret", request.Name)
	log.Info("Reconciling a Secret")
	clusterName := request.Namespace
	if request.Name != propagator.EncryptionKeySecret {
		log.Info("Got a reconciliation request for an unexpected Secret. This should have been filtered out.")
		return reconcile.Result{}, nil
	}
	secret := &corev1.Secret{}
	err := r.Get(ctx, request.NamespacedName, secret)
	if err != nil {
		if k8serrors.IsNotFound(err) {
			log.V(2).Info("The Secret was not found on the server. Doing nothing.")
			return ctrl.Result{}, nil
		}
		log.Error(err, "Failed to get the Secret from the server. Will retry the reconcile request.")
		return ctrl.Result{}, err
	}
	annotations := secret.GetAnnotations()
	if strings.EqualFold(annotations[DisableRotationAnnotation], "true") {
		log.Info(
			"Encountered an encryption key Secret with key rotation disabled. Will trigger a policy template update.",
			"annotation", DisableRotationAnnotation,
			"value", annotations[DisableRotationAnnotation],
		)
		r.triggerTemplateUpdate(ctx, clusterName, secret)
		return reconcile.Result{}, nil
	}
	lastRotatedTS := annotations[propagator.LastRotatedAnnotation]
	log = log.WithValues("annotation", propagator.LastRotatedAnnotation, "value", lastRotatedTS)
	var nextRotation time.Duration
	if lastRotatedTS == "" {
		log.Info("The annotation is not set. Will rotate the key now.")
		nextRotation = 0
	} else {
		nextRotation, err = r.getNextRotationFromNow(secret)
		if err != nil {
			log.Error(err, "The annotation cannot be parsed. Will rotate the key now.")
			nextRotation = 0
		}
	}
	_, err = aes.NewCipher(secret.Data["key"])
	if err != nil {
		log.Error(err, "The encryption key in the Secret is invalid. Will rotate the key now.")
		nextRotation = 0
		secret.Data["key"] = []byte{}
	}
	if nextRotation > 0 {
		if len(secret.Data["previousKey"]) > 0 {
			_, err = aes.NewCipher(secret.Data["previousKey"])
			if err != nil {
				log.Info("The previous encryption key in the Secret is invalid. Will remove it.")
				secret.Data["previousKey"] = []byte{}
				err := r.Update(ctx, secret)
				if err != nil {
					log.Error(err, "Failed to update the Secret. Will retry the request.")
					return reconcile.Result{}, err
				}
			}
		}
		log.V(2).Info("The key is not yet ready to be rotated")
		return reconcile.Result{RequeueAfter: nextRotation}, nil
	}
	log.V(1).Info("Rotating the encryption key")
	err = r.rotateKey(ctx, secret)
	if err != nil {
		log.Error(err, "Failed to rotate the encryption key. Will retry the request.")
		return reconcile.Result{}, err
	}
	r.triggerTemplateUpdate(ctx, clusterName, secret)
	nextRotation, _ = r.getNextRotationFromNow(secret)
	log.Info("Rotated the encryption key successfully", "nextRotation", nextRotation)
	return reconcile.Result{RequeueAfter: nextRotation}, nil
}
func ( r * EncryptionKeysReconciler ) Reconcile ( ctx context . Context , request ctrl . Request ) ( ctrl . Result , error ) { log := log . WithValues ( " " , request . Namespace , " " , request . Name ) log . Info ( " " ) clusterName := request . Namespace if request . Name != propagator . EncryptionKeySecret { log . Info ( " " ) return reconcile . Result { } , nil } secret := & corev1 . Secret { } err := r . Get ( ctx , request . NamespacedName , secret ) if err != nil { if k8serrors . IsNotFound ( err ) { log . V ( 2 ) . Info ( " " ) return ctrl . Result { } , nil } log . Error ( err , " " ) return ctrl . Result { } , err } annotations := secret . GetAnnotations ( ) if strings . EqualFold ( annotations [ DisableRotationAnnotation ] , " " ) { log . Info ( " " , " " , DisableRotationAnnotation , " " , annotations [ DisableRotationAnnotation ] , ) r . triggerTemplateUpdate ( ctx , clusterName , secret ) return reconcile . Result { } , nil } lastRotatedTS := annotations [ propagator . LastRotatedAnnotation ] log = log . WithValues ( " " , propagator . LastRotatedAnnotation , " " , lastRotatedTS ) var nextRotation time . Duration if lastRotatedTS == " " { log . Info ( " " ) nextRotation = 0 } else { nextRotation , err = r . getNextRotationFromNow ( secret ) if err != nil { log . Error ( err , " " ) nextRotation = 0 } } _ , err = aes . NewCipher ( secret . Data [ " " ] ) if err != nil { log . Error ( err , " " ) nextRotation = 0 secret . Data [ " " ] = [ ] byte { } } if nextRotation > 0 { if len ( secret . Data [ " " ] ) > 0 { _ , err = aes . NewCipher ( secret . Data [ " " ] ) if err != nil { log . Info ( " " ) secret . Data [ " " ] = [ ] byte { } err := r . Update ( ctx , secret ) if err != nil { log . Error ( err , " " ) return reconcile . Result { } , err } } } log . V ( 2 ) . Info ( " " ) return reconcile . Result { RequeueAfter : nextRotation } , nil } log . V ( 1 ) . Info ( " " ) err = r . rotateKey ( ctx , secret ) if err != nil { log . Error ( err , " " ) return reconcile . Result { } , err } r . triggerTemplateUpdate ( ctx , clusterName , secret ) nextRotation , _ = r . getNextRotationFromNow ( secret ) log . Info ( " " , " " , nextRotation ) return reconcile . Result { RequeueAfter : nextRotation } , nil }
Reconcile watches all "policy-encryption-key" Secrets on the Hub cluster.
Reconcile watches all " policy - encryption - key " Secrets on the Hub cluster .
// The cache configuration of SelectorsByObject should prevent this from happening, but add this as a precaution. // In case the key was manually rotated, trigger a template update // Set this to a null value so the bad key doesn't get stored as the previous key // previousKey only needs to be checked if there won't be a rotation since it would get overwritten anyways // If previousKey is invalid, it'll cause go-template-utils to fail on the managed cluster, so remove it if // a user changed this accidentally // Requeueing the same object multiple times is safe as the queue will drop any scheduled // requeues in favor of this one // https://github.com/kubernetes-sigs/controller-runtime/blob/7ba3e559790c5e3543002a0d9670b4cef3ccf743/pkg/internal/controller/controller.go#L323-L324 // The error is ignored since this can't fail since the annotation value was just set to a valid value