Browse Source

feat(infisical): add caBundle and caProvider support (#5770)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
wi-adam 3 months ago
parent
commit
24495bd04f

+ 11 - 0
apis/externalsecrets/v1/secretsstore_infisical_types.go

@@ -164,4 +164,15 @@ type InfisicalProvider struct {
 	// +kubebuilder:default="https://app.infisical.com/api"
 	// +optional
 	HostAPI string `json:"hostAPI,omitempty"`
+
+	// CABundle is a PEM-encoded CA certificate bundle used to validate
+	// the Infisical server's TLS certificate. Mutually exclusive with CAProvider.
+	// +optional
+	CABundle []byte `json:"caBundle,omitempty"`
+
+	// CAProvider is a reference to a Secret or ConfigMap that contains a CA certificate.
+	// The certificate is used to validate the Infisical server's TLS certificate.
+	// Mutually exclusive with CABundle.
+	// +optional
+	CAProvider *CAProvider `json:"caProvider,omitempty"`
 }

+ 10 - 0
apis/externalsecrets/v1/zz_generated.deepcopy.go

@@ -2421,6 +2421,16 @@ func (in *InfisicalProvider) DeepCopyInto(out *InfisicalProvider) {
 	*out = *in
 	in.Auth.DeepCopyInto(&out.Auth)
 	out.SecretsScope = in.SecretsScope
+	if in.CABundle != nil {
+		in, out := &in.CABundle, &out.CABundle
+		*out = make([]byte, len(*in))
+		copy(*out, *in)
+	}
+	if in.CAProvider != nil {
+		in, out := &in.CAProvider, &out.CAProvider
+		*out = new(CAProvider)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfisicalProvider.

+ 45 - 0
config/crds/bases/external-secrets.io_clustersecretstores.yaml

@@ -3267,6 +3267,51 @@ spec:
                             - clientSecret
                             type: object
                         type: object
+                      caBundle:
+                        description: |-
+                          CABundle is a PEM-encoded CA certificate bundle used to validate
+                          the Infisical server's TLS certificate. Mutually exclusive with CAProvider.
+                        format: byte
+                        type: string
+                      caProvider:
+                        description: |-
+                          CAProvider is a reference to a Secret or ConfigMap that contains a CA certificate.
+                          The certificate is used to validate the Infisical server's TLS certificate.
+                          Mutually exclusive with CABundle.
+                        properties:
+                          key:
+                            description: The key where the CA certificate can be found
+                              in the Secret or ConfigMap.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[-._a-zA-Z0-9]+$
+                            type: string
+                          name:
+                            description: The name of the object located at the provider
+                              type.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                            type: string
+                          namespace:
+                            description: |-
+                              The namespace the Provider type is in.
+                              Can only be defined when used in a ClusterSecretStore.
+                            maxLength: 63
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                            type: string
+                          type:
+                            description: The type of provider to use such as "Secret",
+                              or "ConfigMap".
+                            enum:
+                            - Secret
+                            - ConfigMap
+                            type: string
+                        required:
+                        - name
+                        - type
+                        type: object
                       hostAPI:
                         default: https://app.infisical.com/api
                         description: HostAPI specifies the base URL of the Infisical

+ 45 - 0
config/crds/bases/external-secrets.io_secretstores.yaml

@@ -3267,6 +3267,51 @@ spec:
                             - clientSecret
                             type: object
                         type: object
+                      caBundle:
+                        description: |-
+                          CABundle is a PEM-encoded CA certificate bundle used to validate
+                          the Infisical server's TLS certificate. Mutually exclusive with CAProvider.
+                        format: byte
+                        type: string
+                      caProvider:
+                        description: |-
+                          CAProvider is a reference to a Secret or ConfigMap that contains a CA certificate.
+                          The certificate is used to validate the Infisical server's TLS certificate.
+                          Mutually exclusive with CABundle.
+                        properties:
+                          key:
+                            description: The key where the CA certificate can be found
+                              in the Secret or ConfigMap.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[-._a-zA-Z0-9]+$
+                            type: string
+                          name:
+                            description: The name of the object located at the provider
+                              type.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                            type: string
+                          namespace:
+                            description: |-
+                              The namespace the Provider type is in.
+                              Can only be defined when used in a ClusterSecretStore.
+                            maxLength: 63
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                            type: string
+                          type:
+                            description: The type of provider to use such as "Secret",
+                              or "ConfigMap".
+                            enum:
+                            - Secret
+                            - ConfigMap
+                            type: string
+                        required:
+                        - name
+                        - type
+                        type: object
                       hostAPI:
                         default: https://app.infisical.com/api
                         description: HostAPI specifies the base URL of the Infisical

+ 84 - 0
deploy/crds/bundle.yaml

@@ -5136,6 +5136,48 @@ spec:
                                 - clientSecret
                               type: object
                           type: object
+                        caBundle:
+                          description: |-
+                            CABundle is a PEM-encoded CA certificate bundle used to validate
+                            the Infisical server's TLS certificate. Mutually exclusive with CAProvider.
+                          format: byte
+                          type: string
+                        caProvider:
+                          description: |-
+                            CAProvider is a reference to a Secret or ConfigMap that contains a CA certificate.
+                            The certificate is used to validate the Infisical server's TLS certificate.
+                            Mutually exclusive with CABundle.
+                          properties:
+                            key:
+                              description: The key where the CA certificate can be found in the Secret or ConfigMap.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[-._a-zA-Z0-9]+$
+                              type: string
+                            name:
+                              description: The name of the object located at the provider type.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                              type: string
+                            namespace:
+                              description: |-
+                                The namespace the Provider type is in.
+                                Can only be defined when used in a ClusterSecretStore.
+                              maxLength: 63
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                              type: string
+                            type:
+                              description: The type of provider to use such as "Secret", or "ConfigMap".
+                              enum:
+                                - Secret
+                                - ConfigMap
+                              type: string
+                          required:
+                            - name
+                            - type
+                          type: object
                         hostAPI:
                           default: https://app.infisical.com/api
                           description: HostAPI specifies the base URL of the Infisical API. If not provided, it defaults to "https://app.infisical.com/api".
@@ -16760,6 +16802,48 @@ spec:
                                 - clientSecret
                               type: object
                           type: object
+                        caBundle:
+                          description: |-
+                            CABundle is a PEM-encoded CA certificate bundle used to validate
+                            the Infisical server's TLS certificate. Mutually exclusive with CAProvider.
+                          format: byte
+                          type: string
+                        caProvider:
+                          description: |-
+                            CAProvider is a reference to a Secret or ConfigMap that contains a CA certificate.
+                            The certificate is used to validate the Infisical server's TLS certificate.
+                            Mutually exclusive with CABundle.
+                          properties:
+                            key:
+                              description: The key where the CA certificate can be found in the Secret or ConfigMap.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[-._a-zA-Z0-9]+$
+                              type: string
+                            name:
+                              description: The name of the object located at the provider type.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                              type: string
+                            namespace:
+                              description: |-
+                                The namespace the Provider type is in.
+                                Can only be defined when used in a ClusterSecretStore.
+                              maxLength: 63
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                              type: string
+                            type:
+                              description: The type of provider to use such as "Secret", or "ConfigMap".
+                              enum:
+                                - Secret
+                                - ConfigMap
+                              type: string
+                          required:
+                            - name
+                            - type
+                          type: object
                         hostAPI:
                           default: https://app.infisical.com/api
                           description: HostAPI specifies the base URL of the Infisical API. If not provided, it defaults to "https://app.infisical.com/api".

+ 30 - 0
docs/api/spec.md

@@ -1951,6 +1951,7 @@ string
 <a href="#external-secrets.io/v1.BitwardenSecretsManagerProvider">BitwardenSecretsManagerProvider</a>, 
 <a href="#external-secrets.io/v1.ConjurProvider">ConjurProvider</a>, 
 <a href="#external-secrets.io/v1.GitlabProvider">GitlabProvider</a>, 
+<a href="#external-secrets.io/v1.InfisicalProvider">InfisicalProvider</a>, 
 <a href="#external-secrets.io/v1.KubernetesServer">KubernetesServer</a>, 
 <a href="#external-secrets.io/v1.SecretServerProvider">SecretServerProvider</a>, 
 <a href="#external-secrets.io/v1.VaultProvider">VaultProvider</a>)
@@ -6652,6 +6653,35 @@ string
 <p>HostAPI specifies the base URL of the Infisical API. If not provided, it defaults to &ldquo;<a href="https://app.infisical.com/api&quot;">https://app.infisical.com/api&rdquo;</a>.</p>
 </td>
 </tr>
+<tr>
+<td>
+<code>caBundle</code></br>
+<em>
+[]byte
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>CABundle is a PEM-encoded CA certificate bundle used to validate
+the Infisical server&rsquo;s TLS certificate. Mutually exclusive with CAProvider.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>caProvider</code></br>
+<em>
+<a href="#external-secrets.io/v1.CAProvider">
+CAProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>CAProvider is a reference to a Secret or ConfigMap that contains a CA certificate.
+The certificate is used to validate the Infisical server&rsquo;s TLS certificate.
+Mutually exclusive with CABundle.</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="external-secrets.io/v1.IntegrationInfo">IntegrationInfo

+ 65 - 0
docs/provider/infisical.md

@@ -84,3 +84,68 @@ To filter secrets by `path` (path prefix) and `name` (regular expression).
 ``` yaml
 {% include 'infisical-filtered-secrets.yaml' %}
 ```
+
+## Custom CA Certificates
+
+If you are using a self-hosted Infisical instance with a self-signed certificate or a certificate signed by a private CA, you can configure the provider to trust it.
+
+### Using caBundle (inline)
+
+You can provide the CA certificate directly as a base64-encoded PEM bundle:
+
+```yaml
+apiVersion: external-secrets.io/v1
+kind: SecretStore
+metadata:
+  name: infisical
+spec:
+  provider:
+    infisical:
+      hostAPI: https://my-infisical.example.com
+      # Base64-encoded PEM certificate
+      caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..."
+      auth:
+        universalAuthCredentials:
+          clientId:
+            key: clientId
+            name: universal-auth-credentials
+          clientSecret:
+            key: clientSecret
+            name: universal-auth-credentials
+      secretsScope:
+        projectSlug: my-project
+        environmentSlug: dev
+```
+
+### Using caProvider (from Secret or ConfigMap)
+
+Alternatively, you can reference a Secret or ConfigMap containing the CA certificate:
+
+```yaml
+apiVersion: external-secrets.io/v1
+kind: SecretStore
+metadata:
+  name: infisical
+spec:
+  provider:
+    infisical:
+      hostAPI: https://my-infisical.example.com
+      caProvider:
+        type: Secret
+        name: infisical-ca
+        key: ca.crt
+      auth:
+        universalAuthCredentials:
+          clientId:
+            key: clientId
+            name: universal-auth-credentials
+          clientSecret:
+            key: clientSecret
+            name: universal-auth-credentials
+      secretsScope:
+        projectSlug: my-project
+        environmentSlug: dev
+```
+
+!!! note
+    For `ClusterSecretStore`, be sure to set `namespace` in `caProvider`.

+ 13 - 0
docs/snippets/infisical-generic-secret-store.yaml

@@ -9,6 +9,19 @@ spec:
       #
       # Override this if you are using a different Infisical instance.
       hostAPI: https://app.infisical.com
+
+      # Optional: PEM-encoded CA bundle for self-hosted instances with private CAs.
+      # caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..."
+
+      # Optional: Reference to Secret or ConfigMap containing CA certificate.
+      # Mutually exclusive with caBundle.
+      # caProvider:
+      #   type: Secret  # or ConfigMap
+      #   name: infisical-ca
+      #   key: ca.crt
+      #   # namespace is required for ClusterSecretStore
+      #   # namespace: external-secrets
+
       auth:
         universalAuthCredentials:
           clientId:

+ 1 - 1
providers/v1/infisical/go.mod

@@ -9,6 +9,7 @@ require (
 	github.com/stretchr/testify v1.11.1
 	github.com/tidwall/gjson v1.18.0
 	k8s.io/api v0.34.1
+	k8s.io/apimachinery v0.34.1
 	sigs.k8s.io/controller-runtime v0.22.3
 )
 
@@ -125,7 +126,6 @@ require (
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	k8s.io/apiextensions-apiserver v0.34.1 // indirect
-	k8s.io/apimachinery v0.34.1 // indirect
 	k8s.io/client-go v0.34.1 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect

+ 32 - 1
providers/v1/infisical/provider.go

@@ -336,10 +336,29 @@ func (p *Provider) NewClient(ctx context.Context, store esv1.GenericStore, kube
 
 	infisicalSpec := storeSpec.Provider.Infisical
 
+	// Fetch CA certificate if configured
+	var caCertificate string
+	if len(infisicalSpec.CABundle) > 0 || infisicalSpec.CAProvider != nil {
+		caCert, err := esutils.FetchCACertFromSource(ctx, esutils.CreateCertOpts{
+			CABundle:   infisicalSpec.CABundle,
+			CAProvider: infisicalSpec.CAProvider,
+			StoreKind:  store.GetObjectKind().GroupVersionKind().Kind,
+			Namespace:  namespace,
+			Client:     kube,
+		})
+		if err != nil {
+			return nil, fmt.Errorf("failed to get CA certificate: %w", err)
+		}
+		if caCert != nil {
+			caCertificate = string(caCert)
+		}
+	}
+
 	ctx, cancelSdkClient := context.WithCancel(ctx)
 
 	sdkClient := infisicalSdk.NewInfisicalClient(ctx, infisicalSdk.Config{
-		SiteUrl: infisicalSpec.HostAPI,
+		SiteUrl:       infisicalSpec.HostAPI,
+		CaCertificate: caCertificate,
 	})
 	secretPath := infisicalSpec.SecretsScope.SecretsPath
 	if secretPath == "" {
@@ -449,6 +468,18 @@ func (p *Provider) ValidateStore(store esv1.GenericStore) (admission.Warnings, e
 		return nil, errors.New("secretsScope.projectSlug and secretsScope.environmentSlug cannot be empty")
 	}
 
+	// Validate CAProvider namespace requirements
+	if infisicalStoreSpec.CAProvider != nil {
+		if store.GetObjectKind().GroupVersionKind().Kind == esv1.ClusterSecretStoreKind &&
+			infisicalStoreSpec.CAProvider.Namespace == nil {
+			return nil, errors.New("caProvider.namespace is required for ClusterSecretStore")
+		}
+		if store.GetObjectKind().GroupVersionKind().Kind == esv1.SecretStoreKind &&
+			infisicalStoreSpec.CAProvider.Namespace != nil {
+			return nil, errors.New("caProvider.namespace must be empty with SecretStore")
+		}
+	}
+
 	if infisicalStoreSpec.Auth.UniversalAuthCredentials != nil {
 		uaCredential := infisicalStoreSpec.Auth.UniversalAuthCredentials
 		// to validate reference authentication

+ 145 - 0
providers/v1/infisical/provider_test.go

@@ -27,6 +27,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
 	esv1meta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -232,6 +233,7 @@ func TestGetSecretMap(t *testing.T) {
 
 func makeSecretStore(projectSlug, environment, secretsPath string, fn ...storeModifier) *esv1.SecretStore {
 	store := &esv1.SecretStore{
+		TypeMeta: metav1.TypeMeta{Kind: esv1.SecretStoreKind},
 		Spec: esv1.SecretStoreSpec{
 			Provider: &esv1.SecretStoreProvider{
 				Infisical: &esv1.InfisicalProvider{
@@ -275,6 +277,78 @@ func withClientSecret(name, key string, namespace *string) storeModifier {
 	}
 }
 
+func withSecretStoreCAProvider(name, key string, namespace *string) storeModifier {
+	return func(store *esv1.SecretStore) *esv1.SecretStore {
+		store.Spec.Provider.Infisical.CAProvider = &esv1.CAProvider{
+			Type:      esv1.CAProviderTypeSecret,
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+
+type clusterStoreModifier func(*esv1.ClusterSecretStore) *esv1.ClusterSecretStore
+
+func makeClusterSecretStore(projectSlug, environment, secretsPath string, fn ...clusterStoreModifier) *esv1.ClusterSecretStore {
+	store := &esv1.ClusterSecretStore{
+		TypeMeta: metav1.TypeMeta{Kind: esv1.ClusterSecretStoreKind},
+		Spec: esv1.SecretStoreSpec{
+			Provider: &esv1.SecretStoreProvider{
+				Infisical: &esv1.InfisicalProvider{
+					Auth: esv1.InfisicalAuth{
+						UniversalAuthCredentials: &esv1.UniversalAuthCredentials{},
+					},
+					SecretsScope: esv1.MachineIdentityScopeInWorkspace{
+						SecretsPath:     secretsPath,
+						EnvironmentSlug: environment,
+						ProjectSlug:     projectSlug,
+					},
+				},
+			},
+		},
+	}
+	for _, f := range fn {
+		store = f(store)
+	}
+	return store
+}
+
+func withCAProvider(name, key string, namespace *string) clusterStoreModifier {
+	return func(store *esv1.ClusterSecretStore) *esv1.ClusterSecretStore {
+		store.Spec.Provider.Infisical.CAProvider = &esv1.CAProvider{
+			Type:      esv1.CAProviderTypeSecret,
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+
+func withClusterClientID(name, key string, namespace *string) clusterStoreModifier {
+	return func(store *esv1.ClusterSecretStore) *esv1.ClusterSecretStore {
+		store.Spec.Provider.Infisical.Auth.UniversalAuthCredentials.ClientID = esv1meta.SecretKeySelector{
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+
+func withClusterClientSecret(name, key string, namespace *string) clusterStoreModifier {
+	return func(store *esv1.ClusterSecretStore) *esv1.ClusterSecretStore {
+		store.Spec.Provider.Infisical.Auth.UniversalAuthCredentials.ClientSecret = esv1meta.SecretKeySelector{
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+
 type ValidateStoreTestCase struct {
 	name        string
 	store       *esv1.SecretStore
@@ -323,3 +397,74 @@ func TestValidateStore(t *testing.T) {
 		})
 	}
 }
+
+func TestValidateStoreCAProvider(t *testing.T) {
+	const randomID = "some-random-id"
+	const authType = "universal-auth"
+	namespace := "my-namespace"
+
+	testCases := []struct {
+		name        string
+		store       esv1.GenericStore
+		assertError func(t *testing.T, err error)
+	}{
+		{
+			name: "ClusterSecretStore with CAProvider missing namespace should fail",
+			store: makeClusterSecretStore(
+				apiScope.ProjectSlug, apiScope.EnvironmentSlug, apiScope.SecretPath,
+				withClusterClientID(authType, randomID, &namespace),
+				withClusterClientSecret(authType, randomID, &namespace),
+				withCAProvider("my-ca-secret", "ca.crt", nil),
+			),
+			assertError: func(t *testing.T, err error) {
+				require.Error(t, err)
+				assert.Contains(t, err.Error(), "caProvider.namespace is required for ClusterSecretStore")
+			},
+		},
+		{
+			name: "ClusterSecretStore with CAProvider with namespace should succeed",
+			store: makeClusterSecretStore(
+				apiScope.ProjectSlug, apiScope.EnvironmentSlug, apiScope.SecretPath,
+				withClusterClientID(authType, randomID, &namespace),
+				withClusterClientSecret(authType, randomID, &namespace),
+				withCAProvider("my-ca-secret", "ca.crt", &namespace),
+			),
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+		},
+		{
+			name: "SecretStore with CAProvider namespace set should fail",
+			store: makeSecretStore(
+				apiScope.ProjectSlug, apiScope.EnvironmentSlug, apiScope.SecretPath,
+				withClientID(authType, randomID, nil),
+				withClientSecret(authType, randomID, nil),
+				withSecretStoreCAProvider("my-ca-secret", "ca.crt", &namespace),
+			),
+			assertError: func(t *testing.T, err error) {
+				require.Error(t, err)
+				assert.Contains(t, err.Error(), "caProvider.namespace must be empty with SecretStore")
+			},
+		},
+		{
+			name: "SecretStore with CAProvider without namespace should succeed",
+			store: makeSecretStore(
+				apiScope.ProjectSlug, apiScope.EnvironmentSlug, apiScope.SecretPath,
+				withClientID(authType, randomID, nil),
+				withClientSecret(authType, randomID, nil),
+				withSecretStoreCAProvider("my-ca-secret", "ca.crt", nil),
+			),
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+		},
+	}
+
+	p := Provider{}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			_, err := p.ValidateStore(tc.store)
+			tc.assertError(t, err)
+		})
+	}
+}

+ 6 - 0
tests/__snapshot__/clustersecretstore-v1.yaml

@@ -492,6 +492,12 @@ spec:
             key: string
             name: string
             namespace: string
+      caBundle: c3RyaW5n
+      caProvider:
+        key: string
+        name: string
+        namespace: string
+        type: "Secret" # "Secret", "ConfigMap"
       hostAPI: "https://app.infisical.com/api"
       secretsScope:
         environmentSlug: string

+ 6 - 0
tests/__snapshot__/secretstore-v1.yaml

@@ -492,6 +492,12 @@ spec:
             key: string
             name: string
             namespace: string
+      caBundle: c3RyaW5n
+      caProvider:
+        key: string
+        name: string
+        namespace: string
+        type: "Secret" # "Secret", "ConfigMap"
       hostAPI: "https://app.infisical.com/api"
       secretsScope:
         environmentSlug: string