diff --git a/k8-operator/api/v1alpha1/infisicalsecret_types.go b/k8-operator/api/v1alpha1/infisicalsecret_types.go index a3f09b695..65da2498c 100644 --- a/k8-operator/api/v1alpha1/infisicalsecret_types.go +++ b/k8-operator/api/v1alpha1/infisicalsecret_types.go @@ -149,6 +149,26 @@ type MangedKubeSecretConfig struct { CreationPolicy string `json:"creationPolicy"` } +type CaReference struct { + // The name of the Kubernetes Secret + // +kubebuilder:validation:Required + SecretName string `json:"secretName"` + + // The namespace where the Kubernetes Secret is located + // +kubebuilder:validation:Required + SecretNamespace string `json:"secretNamespace"` + + // +kubebuilder:validation:Required + // The name of the secret property with the CA certificate value + SecretKey string `json:"key"` +} + +type TLSConfig struct { + // Reference to secret containing CA cert + // +kubebuilder:validation:Optional + CaRef CaReference `json:"caRef,omitempty"` +} + // InfisicalSecretSpec defines the desired state of InfisicalSecret type InfisicalSecretSpec struct { // +kubebuilder:validation:Optional @@ -166,6 +186,9 @@ type InfisicalSecretSpec struct { // Infisical host to pull secrets from // +kubebuilder:validation:Optional HostAPI string `json:"hostAPI"` + + // +kubebuilder:validation:Optional + TLS TLSConfig `json:"tls"` } // InfisicalSecretStatus defines the observed state of InfisicalSecret diff --git a/k8-operator/api/v1alpha1/zz_generated.deepcopy.go b/k8-operator/api/v1alpha1/zz_generated.deepcopy.go index 75d46d28b..dd242910c 100644 --- a/k8-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/k8-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -81,6 +81,21 @@ func (in *AzureAuthDetails) DeepCopy() *AzureAuthDetails { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CaReference) DeepCopyInto(out *CaReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CaReference. +func (in *CaReference) DeepCopy() *CaReference { + if in == nil { + return nil + } + out := new(CaReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GCPIdTokenAuthDetails) DeepCopyInto(out *GCPIdTokenAuthDetails) { *out = *in @@ -178,6 +193,7 @@ func (in *InfisicalSecretSpec) DeepCopyInto(out *InfisicalSecretSpec) { out.TokenSecretReference = in.TokenSecretReference out.Authentication = in.Authentication out.ManagedSecretReference = in.ManagedSecretReference + out.TLS = in.TLS } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfisicalSecretSpec. @@ -337,6 +353,22 @@ func (in *ServiceTokenDetails) DeepCopy() *ServiceTokenDetails { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSConfig) DeepCopyInto(out *TLSConfig) { + *out = *in + out.CaRef = in.CaRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig. +func (in *TLSConfig) DeepCopy() *TLSConfig { + if in == nil { + return nil + } + out := new(TLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UniversalAuthDetails) DeepCopyInto(out *UniversalAuthDetails) { *out = *in diff --git a/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml b/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml index dea7829fc..633b48460 100644 --- a/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml +++ b/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml @@ -290,6 +290,28 @@ spec: resyncInterval: default: 60 type: integer + tls: + properties: + caRef: + description: Reference to secret containing CA cert + properties: + key: + description: The name of the secret property with the CA certificate + value + type: string + secretName: + description: The name of the Kubernetes Secret + type: string + secretNamespace: + description: The namespace where the Kubernetes Secret is + located + type: string + required: + - key + - secretName + - secretNamespace + type: object + type: object tokenSecretReference: properties: secretName: diff --git a/k8-operator/controllers/infisicalsecret_controller.go b/k8-operator/controllers/infisicalsecret_controller.go index 43ed00d4f..6064b13aa 100644 --- a/k8-operator/controllers/infisicalsecret_controller.go +++ b/k8-operator/controllers/infisicalsecret_controller.go @@ -107,6 +107,18 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ api.API_HOST_URL = infisicalSecretCR.Spec.HostAPI } + if infisicalSecretCR.Spec.TLS.CaRef.SecretName != "" { + api.API_CA_CERTIFICATE, err = r.GetInfisicalCaCertificateFromKubeSecret(ctx, infisicalSecretCR) + if err != nil { + fmt.Printf("unable to fetch CA certificate [err=%s]. Will requeue after [requeueTime=%v]\n", err, requeueTime) + return ctrl.Result{ + RequeueAfter: requeueTime, + }, nil + } + + fmt.Println("Using custom CA certificate...") + } + err = r.ReconcileInfisicalSecret(ctx, infisicalSecretCR) r.SetReadyToSyncSecretsConditions(ctx, &infisicalSecretCR, err) diff --git a/k8-operator/controllers/infisicalsecret_helper.go b/k8-operator/controllers/infisicalsecret_helper.go index 6d396d165..a66b4d799 100644 --- a/k8-operator/controllers/infisicalsecret_helper.go +++ b/k8-operator/controllers/infisicalsecret_helper.go @@ -177,6 +177,27 @@ func (r *InfisicalSecretReconciler) GetInfisicalUniversalAuthFromKubeSecret(ctx } +func (r *InfisicalSecretReconciler) GetInfisicalCaCertificateFromKubeSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (caCertificate string, err error) { + + caCertificateFromKubeSecret, err := r.GetKubeSecretByNamespacedName(ctx, types.NamespacedName{ + Namespace: infisicalSecret.Spec.TLS.CaRef.SecretNamespace, + Name: infisicalSecret.Spec.TLS.CaRef.SecretName, + }) + + if k8Errors.IsNotFound(err) { + return "", fmt.Errorf("kubernetes secret containing custom CA certificate cannot be found. [err=%s]", err) + } + + if err != nil { + return "", fmt.Errorf("something went wrong when fetching your CA certificate [err=%s]", err) + } + + caCertificateFromSecret := string(caCertificateFromKubeSecret.Data[infisicalSecret.Spec.TLS.CaRef.SecretKey]) + + return caCertificateFromSecret, nil + +} + // Fetches service account credentials from a Kubernetes secret specified in the infisicalSecret object, extracts the access key, public key, and private key from the secret, and returns them as a ServiceAccountCredentials object. // If any keys are missing or an error occurs, returns an empty object or an error object, respectively. func (r *InfisicalSecretReconciler) GetInfisicalServiceAccountCredentialsFromKubeSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (serviceAccountDetails model.ServiceAccountDetails, err error) { @@ -296,8 +317,9 @@ func (r *InfisicalSecretReconciler) GetResourceVariables(infisicalSecret v1alpha ctx, cancel := context.WithCancel(context.Background()) client := infisicalSdk.NewInfisicalClient(ctx, infisicalSdk.Config{ - SiteUrl: api.API_HOST_URL, - UserAgent: api.USER_AGENT_NAME, + SiteUrl: api.API_HOST_URL, + CaCertificate: api.API_CA_CERTIFICATE, + UserAgent: api.USER_AGENT_NAME, }) resourceVariablesMap[string(infisicalSecret.UID)] = ResourceVariables{ diff --git a/k8-operator/packages/api/variables.go b/k8-operator/packages/api/variables.go index 214b7e1d8..1dd255d42 100644 --- a/k8-operator/packages/api/variables.go +++ b/k8-operator/packages/api/variables.go @@ -1,3 +1,4 @@ package api var API_HOST_URL string = "https://app.infisical.com/api" +var API_CA_CERTIFICATE string = ""