diff --git a/cmd/manager/cmd.go b/cmd/manager/cmd.go index 06c8f705..82df75e8 100644 --- a/cmd/manager/cmd.go +++ b/cmd/manager/cmd.go @@ -41,21 +41,22 @@ import ( func NewCmd(scheme *runtime.Scheme) *cobra.Command { // CLI flags var ( - metricsBindAddress string - healthProbeBindAddress string - leaderElect bool - tmpDirectory string - kineImage string - controllerReconcileTimeout time.Duration - cacheResyncPeriod time.Duration - datastore string - managerNamespace string - managerServiceAccountName string - managerServiceName string - webhookCABundle []byte - migrateJobImage string - maxConcurrentReconciles int - disableTelemetry bool + metricsBindAddress string + healthProbeBindAddress string + leaderElect bool + tmpDirectory string + kineImage string + controllerReconcileTimeout time.Duration + cacheResyncPeriod time.Duration + datastore string + managerNamespace string + managerServiceAccountName string + managerServiceName string + webhookCABundle []byte + migrateJobImage string + maxConcurrentReconciles int + disableTelemetry bool + certificateExpirationDeadline time.Duration webhookCAPath string ) @@ -76,6 +77,10 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command { return err } + if certificateExpirationDeadline < 24*time.Hour { + return fmt.Errorf("certificate expiration deadline must be at least 24 hours") + } + if webhookCABundle, err = os.ReadFile(webhookCAPath); err != nil { return fmt.Errorf("unable to read webhook CA: %w", err) } @@ -186,7 +191,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command { } } - if err = (&controllers.CertificateLifecycle{Channel: certChannel}).SetupWithManager(mgr); err != nil { + if err = (&controllers.CertificateLifecycle{Channel: certChannel, Deadline: certificateExpirationDeadline}).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "CertificateLifecycle") return err @@ -309,6 +314,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command { cmd.Flags().DurationVar(&controllerReconcileTimeout, "controller-reconcile-timeout", 30*time.Second, "The reconciliation request timeout before the controller withdraw the external resource calls, such as dealing with the Datastore, or the Tenant Control Plane API endpoint.") cmd.Flags().DurationVar(&cacheResyncPeriod, "cache-resync-period", 10*time.Hour, "The controller-runtime.Manager cache resync period.") cmd.Flags().BoolVar(&disableTelemetry, "disable-telemetry", false, "Disable the analytics traces collection.") + cmd.Flags().DurationVar(&certificateExpirationDeadline, "certificate-expiration-deadline", 24*time.Hour, "Define the deadline upon certificate expiration to start the renewal process, cannot be less than a 24 hours.") cobra.OnInitialize(func() { viper.AutomaticEnv() diff --git a/controllers/certificate_lifecycle_controller.go b/controllers/certificate_lifecycle_controller.go index fff2be0a..e9a3a681 100644 --- a/controllers/certificate_lifecycle_controller.go +++ b/controllers/certificate_lifecycle_controller.go @@ -30,8 +30,10 @@ import ( ) type CertificateLifecycle struct { - Channel CertificateChannel - client client.Client + Channel CertificateChannel + Deadline time.Duration + + client client.Client } func (s *CertificateLifecycle) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { @@ -76,7 +78,7 @@ func (s *CertificateLifecycle) Reconcile(ctx context.Context, request reconcile. return reconcile.Result{}, nil } - deadline := time.Now().AddDate(0, 0, 1) + deadline := time.Now().Add(s.Deadline) if deadline.After(crt.NotAfter) { logger.Info("certificate near expiration, must be rotated") diff --git a/docs/content/guides/certs-lifecycle.md b/docs/content/guides/certs-lifecycle.md index bcaf7169..5a72cb24 100644 --- a/docs/content/guides/certs-lifecycle.md +++ b/docs/content/guides/certs-lifecycle.md @@ -94,7 +94,10 @@ k8s-126-576c775b5d-jmvlm 4/4 Running 0 50s The Kamaji operator will run a controller which processes all the Secrets to determine their expiration, both for the `kubeconfig`, as well as for the certificates. The controller, named `CertificateLifecycle`, will extract the certificates from the _Secret_ objects notifying the `TenantControlPlaneReconciler` controller which will start a new certificate rotation. -The rotation will occur the day before their expiration. +By default, the rotation will occur the day before their expiration. + +This rotation deadline can be dynamically configured using the Kamaji CLI flag `--certificate-expiration-deadline` using the Go _Duration_ syntax: +e.g.: set the value `7d` to trigger the renewal a week before the effective expiration date. > Nota Bene: >