From 5aadc41a4a2867b2110e98b483c666c7af74b54a Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Thu, 13 Jun 2024 07:19:33 +0200 Subject: [PATCH] Feat: Resource Variables --- .../controllers/infisicalsecret_controller.go | 54 ++++++++++++++++--- .../controllers/infisicalsecret_helper.go | 50 +++++++++++++---- 2 files changed, 86 insertions(+), 18 deletions(-) diff --git a/k8-operator/controllers/infisicalsecret_controller.go b/k8-operator/controllers/infisicalsecret_controller.go index 0bbd3b89b..6d23fa049 100644 --- a/k8-operator/controllers/infisicalsecret_controller.go +++ b/k8-operator/controllers/infisicalsecret_controller.go @@ -9,10 +9,10 @@ import ( "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" secretsv1alpha1 "github.com/Infisical/infisical/k8-operator/api/v1alpha1" "github.com/Infisical/infisical/k8-operator/packages/api" - infisical "github.com/infisical/go-sdk" infisicalSdk "github.com/infisical/go-sdk" ) @@ -34,6 +34,40 @@ type InfisicalSecretReconciler struct { // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.13.1/pkg/reconcile +type ResourceVariables struct { + infisicalClient infisicalSdk.InfisicalClientInterface + authDetails AuthenticationDetails +} + +// Maps the infisicalSecretCR.UID to a infisicalSdk.InfisicalClientInterface and AuthenticationDetails. +var resourceVariablesMap = make(map[string]ResourceVariables) + +const finalizerName = "secrets.finalizers.infisical.com" + +func (r *InfisicalSecretReconciler) addFinalizer(ctx context.Context, infisicalSecret *secretsv1alpha1.InfisicalSecret) error { + if !controllerutil.ContainsFinalizer(infisicalSecret, finalizerName) { + controllerutil.AddFinalizer(infisicalSecret, finalizerName) + if err := r.Update(ctx, infisicalSecret); err != nil { + return err + } + } + return nil +} + +func (r *InfisicalSecretReconciler) handleFinalizer(ctx context.Context, infisicalSecret *secretsv1alpha1.InfisicalSecret) error { + if controllerutil.ContainsFinalizer(infisicalSecret, finalizerName) { + // Cleanup deployment variables + delete(resourceVariablesMap, string(infisicalSecret.UID)) + + // Remove the finalizer and update the resource + controllerutil.RemoveFinalizer(infisicalSecret, finalizerName) + if err := r.Update(ctx, infisicalSecret); err != nil { + return err + } + } + return nil +} + func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { var infisicalSecretCR secretsv1alpha1.InfisicalSecret requeueTime := time.Minute // seconds @@ -60,8 +94,18 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ fmt.Printf("\nRe-sync interval set. Interval: %v\n", requeueTime) } + // Add the finalizer if it does not exist + if err := r.addFinalizer(ctx, &infisicalSecretCR); err != nil { + return ctrl.Result{}, err + } + // Check if the resource is already marked for deletion if infisicalSecretCR.GetDeletionTimestamp() != nil { + // Handle the finalizer logic + if err := r.handleFinalizer(ctx, &infisicalSecretCR); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{ Requeue: false, }, nil @@ -82,13 +126,7 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ api.API_HOST_URL = infisicalSecretCR.Spec.HostAPI } - // Initialize the SDK client with the necessary configuration - infisicalClient := infisical.NewInfisicalClient(infisicalSdk.Config{ - SiteUrl: api.API_HOST_URL, - UserAgent: api.USER_AGENT_NAME, - }) - - err = r.ReconcileInfisicalSecret(ctx, infisicalSecretCR, infisicalClient) + err = r.ReconcileInfisicalSecret(ctx, infisicalSecretCR) r.SetReadyToSyncSecretsConditions(ctx, &infisicalSecretCR, err) if err != nil { diff --git a/k8-operator/controllers/infisicalsecret_helper.go b/k8-operator/controllers/infisicalsecret_helper.go index f0d021a97..4653bd419 100644 --- a/k8-operator/controllers/infisicalsecret_helper.go +++ b/k8-operator/controllers/infisicalsecret_helper.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Infisical/infisical/k8-operator/api/v1alpha1" + "github.com/Infisical/infisical/k8-operator/packages/api" "github.com/Infisical/infisical/k8-operator/packages/model" "github.com/Infisical/infisical/k8-operator/packages/util" @@ -19,12 +20,6 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -type AuthenticationDetails struct { - authStrategy AuthStrategyType - machineIdentityScope v1alpha1.MachineIdentityScopeInWorkspace // This will only be set if a machine identity auth method is used (e.g. UniversalAuth or KubernetesAuth, etc.) - isMachineIdentityAuth bool -} - const SERVICE_ACCOUNT_ACCESS_KEY = "serviceAccountAccessKey" const SERVICE_ACCOUNT_PUBLIC_KEY = "serviceAccountPublicKey" const SERVICE_ACCOUNT_PRIVATE_KEY = "serviceAccountPrivateKey" @@ -38,9 +33,6 @@ const OPERATOR_SETTINGS_CONFIGMAP_NAME = "infisical-config" const OPERATOR_SETTINGS_CONFIGMAP_NAMESPACE = "infisical-operator-system" const INFISICAL_DOMAIN = "https://app.infisical.com/api" -// var infisicalClient = infisicalSdk.NewInfisicalClient(infisicalSdk.Config{}) -var authDetails AuthenticationDetails - func (r *InfisicalSecretReconciler) HandleAuthentication(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret, infisicalClient infisicalSdk.InfisicalClientInterface) (AuthenticationDetails, error) { // ? Legacy support, service token auth @@ -287,7 +279,41 @@ func (r *InfisicalSecretReconciler) UpdateInfisicalManagedKubeSecret(ctx context return nil } -func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret, infisicalClient infisicalSdk.InfisicalClientInterface) error { +func (r *InfisicalSecretReconciler) GetResourceVariables(infisicalSecret v1alpha1.InfisicalSecret) ResourceVariables { + + var resourceVariables ResourceVariables + + if _, ok := resourceVariablesMap[string(infisicalSecret.UID)]; !ok { + + client := infisicalSdk.NewInfisicalClient(infisicalSdk.Config{ + SiteUrl: infisicalSecret.Spec.HostAPI, + UserAgent: api.USER_AGENT_NAME, + }) + + resourceVariablesMap[string(infisicalSecret.UID)] = ResourceVariables{ + infisicalClient: client, + authDetails: AuthenticationDetails{}, + } + + resourceVariables = resourceVariablesMap[string(infisicalSecret.UID)] + + } else { + resourceVariables = resourceVariablesMap[string(infisicalSecret.UID)] + } + + return resourceVariables + +} + +func (r *InfisicalSecretReconciler) UpdateResourceVariables(infisicalSecret v1alpha1.InfisicalSecret, resourceVariables ResourceVariables) { + resourceVariablesMap[string(infisicalSecret.UID)] = resourceVariables +} + +func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) error { + + resourceVariables := r.GetResourceVariables(infisicalSecret) + infisicalClient := resourceVariables.infisicalClient + authDetails := resourceVariables.authDetails if authDetails.authStrategy == "" { fmt.Println("ReconcileInfisicalSecret: No authentication strategy found. Attempting to authenticate") @@ -299,6 +325,10 @@ func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context } authDetails = details + r.UpdateResourceVariables(infisicalSecret, ResourceVariables{ + infisicalClient: infisicalClient, + authDetails: authDetails, + }) } // Look for managed secret by name and namespace