> ## Documentation Index
> Fetch the complete documentation index at: https://infisical.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubernetes Operator

> How to use Infisical to inject, push, and manage secrets within Kubernetes clusters

The Infisical Operator is a collection of Kubernetes controllers that streamline how secrets are managed between Infisical and your Kubernetes cluster.
It provides multiple Custom Resource Definitions (CRDs) which enable you to:

* **Sync** secrets from Infisical into Kubernetes.
* **Push** new secrets from Kubernetes to Infisical.
* **Manage** dynamic secrets and automatically create time-bound leases.

When these CRDs are configured, the Infisical Operator will continuously monitor for changes and perform necessary updates to keep your Kubernetes secrets up to date.
It can also automatically reload dependent Deployment resources whenever relevant secrets are updated.

The short video below walks through how the Infisical Operator syncs secrets into your Kubernetes cluster.

[YouTube video player](https://www.youtube.com/embed/Nz15mAwIkYc)

> [!NOTE]
>
> The operator supports two CRD API versions: **v1beta1** and **v1alpha1**. Use **v1beta1** for new installations; **v1alpha1** is legacy and will be deprecated soon.

> [!NOTE]
>
> If you're already using the External Secrets operator, you can view the
> integration documentation for it
> [here](https://external-secrets.io/latest/provider/infisical/).

> [tab] Supported Kubernetes versions
>
> The following [Kubernetes minor releases](https://kubernetes.io/releases/) are currently supported. The latest operator version is tested against each Kubernetes version. It may work with other versions of Kubernetes, but those aren't officially supported.
>
> * 1.33
> * 1.32
> * 1.31
> * 1.30
> * 1.29

> [tab] Supported Kubernetes distributions
>
> The Infisical Kubernetes Operator has been tested successfully in the following hosted Kubernetes environments:
>
> * Amazon Elastic Kubernetes Service (EKS)
> * Google Kubernetes Engine (GKE)
> * Microsoft Azure Kubernetes Service (AKS)
> * Oracle Container Engine for Kubernetes (OKE)
> * Red Hat OpenShift
>
> It may work in other Kubernetes distributions, but those are not officially supported. Please report any issues [here](https://github.com/Infisical/infisical/issues).

## Install

The operator is installed via [Helm](https://infisical.com/docs/self-hosting/helm-charts/secrets-operator.md).

**1. Add the Helm repository**

```bash theme={"dark"}
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
```

**2. Install the chart**

Install the operator cluster-wide or namespace-scoped.

> [accordion] Choosing cluster-wide or namespace-scoped
>
> The installation mode decides whether a resource in one namespace can use credentials from another namespace:
>
> | Mode | Cross-namespace references | Use when |
> | - | - | - |
> | Cluster-wide (default) | Allowed. The cluster is the trust boundary. | You trust everyone who can create operator resources, such as a platform team that manages authentication from one namespace. |
> | Namespace-scoped | Blocked. Kubernetes rejects the operator's requests to other namespaces. | Teams share a cluster and each team owns a namespace. Install one operator per team namespace. |

> [tab] Cluster-wide (default)
>
> The operator will watch and manage CRDs across all namespaces in the cluster. This is the default and quickest way to get started.
>
> ```bash theme={"dark"}
> helm install --generate-name infisical-helm-charts/secrets-operator
> ```

> [tab] Namespace-scoped
>
> Limit the operator's permissions to only specific namespaces instead of cluster-wide access. Useful for multi-tenant clusters or environments requiring strict resource isolation.
>
> Before you install, check these settings:
>
> * Set `scopedRBAC=true` (if you set only `scopedNamespaces`, the operator still gets a ClusterRole and watches every namespace)
> * Set `installCRDs=true` only on the first install (CRDs are cluster-wide resources, so later installs must set `installCRDs=false`)
>
> **Single namespace:**
>
> ```bash theme={"dark"}
> helm install operator-namespaced infisical-helm-charts/secrets-operator \
>   --namespace single-namespace \
>   --set scopedNamespaces=single-namespace \
>   --set scopedRBAC=true
> ```
>
> > [accordion] Using values.yaml file
> >
> > ```yaml values.yaml theme={"dark"}
> >   scopedNamespaces: single-namespace
> >   scopedRBAC: true
> >   installCRDs: true
> > ```
>
> **Multiple namespaces (separate operators):**
>
> ```bash theme={"dark"}
> helm install operator-1 infisical-helm-charts/secrets-operator \
>   --namespace ns1 \
>   --set scopedNamespaces=ns1 \
>   --set scopedRBAC=true \
>   --set installCRDs=true # Only install CRDs once in the cluster (default is true)
>
> helm install operator-namespace2 infisical-helm-charts/secrets-operator \
>   --namespace ns2 \
>   --set scopedNamespaces=ns2 \
>   --set scopedRBAC=true \
>   --set installCRDs=false # Do not install CRDs in subsequent namespace installations
> ```
>
> > [accordion] Using values.yaml file
> >
> > ```yaml values-operator1.yaml theme={"dark"}
> >   scopedNamespaces: ns1
> >   scopedRBAC: true
> >   installCRDs: true
> > ```
> >
> > ```yaml values-operator2.yaml theme={"dark"}
> >   scopedNamespaces: ns2
> >   scopedRBAC: true
> >   installCRDs: false
> > ```
>
> **Multiple namespaces (single operator):**
>
> With one operator for several namespaces, a resource in any of those namespaces can reference a service account, `InfisicalAuth`, or secret in the others. Use separate operators if those namespaces belong to different teams.
>
> ```bash theme={"dark"}
> helm install operator infisical-helm-charts/secrets-operator \
>   --namespace operator-namespace \
>   --set "scopedNamespaces={ns1,ns2,ns3}" \
>   --set scopedRBAC=true
> ```
>
> > [accordion] Using values.yaml file
> >
> > ```yaml values.yaml theme={"dark"}
> >   scopedNamespaces:
> >     - ns1
> >     - ns2
> >     - ns3
> >   scopedRBAC: true
> > ```

**3. Verify the deployment**

Check the pods in the namespace you installed the operator into:

```bash theme={"dark"}
kubectl get pods --namespace <namespace>
```

> [!NOTE]
>
> If you installed cluster-wide without a `--namespace` flag, the operator is deployed into your current namespace (typically `default`), so run `kubectl get pods` without the flag.

### Using your own service account

By default a service account is created for the operator based on the release name.
You can bring your own service account by setting `controllerManager.serviceAccount.create` to `false` and `controllerManager.serviceAccount.name` to the name of your existing service account.

```yaml values.yaml theme={"dark"}
controllerManager:
  serviceAccount:
    create: false
    name: my-service-account
```

> [!NOTE]
>
> The service account must already exist in the namespace you're installing the operator in.

> [!TIP]
>
> Custom service accounts are supported in chart version `0.10.11` and above.

### Syncing resources in parallel

By default, the operator syncs one resource at a time.
To speed up syncing, set `maxConcurrency` at the top level of `values.yaml` to the number of resources the operator should sync at the same time.

```yaml values.yaml theme={"dark"}
maxConcurrency: 5
```

The value must be at least `1`, and a higher value sends more requests to Infisical at the same time.
`maxConcurrency` is supported in chart version `0.11.15` and above.

> [!NOTE]
>
> `maxConcurrency` currently only applies to [InfisicalStaticSecret](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-static-secret-crd.md) resources. The operator still syncs every other resource type one at a time.

## Custom resource definitions

> [tab] v1beta1 (Recommended)
>
> The v1beta1 API separates authentication and connection configuration into their own reusable CRDs, making it easier to manage credentials across multiple secret resources.
>
> | CRD | Description |
> | - | - |
> | [InfisicalConnection](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-connection-crd.md) | Defines how to connect to an Infisical instance (host, TLS). Referenced by other CRDs. |
> | [InfisicalAuth](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-auth-crd.md) | Defines authentication credentials for a machine identity. Referenced by other CRDs. |
> | [InfisicalStaticSecret](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-static-secret-crd.md) | Sync secrets from Infisical to a Kubernetes secret. Replaces `InfisicalSecret`. |

> [tab] v1alpha1
>
> > [!WARNING]
> >
> > The v1alpha1 CRDs are legacy and are planned for deprecation.
>
> | CRD | Status | Description |
> | - | - | - |
> | [InfisicalSecret](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-secret-crd.md) | Deprecated | Sync secrets from Infisical to a Kubernetes secret. Use [InfisicalStaticSecret](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-static-secret-crd.md) (v1beta1) instead. See [migration guide](#migrating-from-v1alpha1-to-v1beta1). |
> | [InfisicalPushSecret](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-push-secret-crd.md) | Active | Push secrets from a Kubernetes secret to Infisical. |
> | [InfisicalDynamicSecret](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-dynamic-secret-crd.md) | Active | Sync dynamic secrets and create leases automatically in Kubernetes. |

## Metrics and Prometheus

The operator exposes Prometheus metrics on `/metrics` for monitoring reconciliation performance, errors, and resource utilization.

### Configuration

Enable the ServiceMonitor during installation. This will create a prometheus `ServiceMonitor` resource in the same namespace as the operator.

```yaml values.yaml theme={"dark"}
telemetry:
  serviceMonitor:
    enabled: true
    # ... other telemetry configuration (optional) ...
```

> [accordion] telemetry.serviceMonitor.enabled
>
> Enable ServiceMonitor for Prometheus Operator. Defaults to `false`.

> [accordion] telemetry.serviceMonitor.selectors
>
> Additional labels for ServiceMonitor. Defaults to `{}`.

> [accordion] telemetry.serviceMonitor.scheme
>
> Scheme to use for the ServiceMonitor. Defaults to `https`.

> [accordion] telemetry.serviceMonitor.port
>
> Port to use for the ServiceMonitor. Defaults to `https`.

> [accordion] telemetry.serviceMonitor.path
>
> Path to use for the ServiceMonitor. Defaults to `/metrics`.

> [accordion] telemetry.serviceMonitor.interval
>
> Scrape interval. Defaults to `30s`.

> [accordion] telemetry.serviceMonitor.scrapeTimeout
>
> Scrape timeout. Defaults to `10s`.

> [accordion] telemetry.serviceMonitor.bearerTokenFile
>
> Bearer token file. Defaults to `/var/run/secrets/kubernetes.io/serviceaccount/token`.

```yaml full-example-values.yaml theme={"dark"}
telemetry:
  serviceMonitor:
    enabled: true

    selectors: {}
    scheme: https
    port: https
    path: /metrics
    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
    interval: 30s
    scrapeTimeout: 10s
```

### Available metrics

The operator exposes standard controller-runtime metrics. For a complete list of available metrics, see the [Kubebuilder metrics reference](https://book.kubebuilder.io/reference/metrics.html).

**Key metrics to monitor:**

* `controller_runtime_reconcile_total` - Reconciliation count
* `controller_runtime_reconcile_errors_total` - Error count
* `controller_runtime_reconcile_time_seconds` - Reconciliation duration

**v1beta1 controllers:** `InfisicalStaticSecret`, `InfisicalAuth`, `InfisicalConnection`

**v1alpha1 controllers:** `InfisicalSecret`, `InfisicalPushSecret`, `InfisicalDynamicSecret`

For metrics about each InfisicalStaticSecret resource, such as its sync status, see [InfisicalStaticSecret metrics](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-static-secret-crd.md#metrics).

### Example Prometheus setup

**1. Install Prometheus Operator**

```bash theme={"dark"}
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace
```

**2. Install Operator with Metrics Enabled**

```bash theme={"dark"}
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'

helm install infisical-secrets-operator infisical-helm-charts/secrets-operator \
  --set telemetry.serviceMonitor.enabled=true
```

**3. Verify ServiceMonitor**

```bash theme={"dark"}
kubectl get servicemonitor
```

Check that the ServiceMonitor appears in your operator's namespace.

**4. Access Prometheus**

```bash theme={"dark"}
kubectl port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090:9090
```

Open [http://localhost:9090/targets](http://localhost:9090/targets) and verify the operator target shows **UP**.

### Example queries

```promql theme={"dark"}
# Total reconciliations
controller_runtime_reconcile_total

# P99 latency
histogram_quantile(0.99, rate(controller_runtime_reconcile_time_seconds_bucket[5m]))

# Memory usage (MB)
process_resident_memory_bytes / 1024 / 1024
```

## General configuration

### Private/self-signed certificate

To connect to Infisical instances behind a private/self-signed certificate, you can configure TLS settings
to point to a CA certificate stored in a Kubernetes secret resource.

> [tab] v1beta1 (Recommended)
>
> In v1beta1, TLS is configured on the [InfisicalConnection](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-connection-crd.md) resource:
>
> ```yaml theme={"dark"}
> apiVersion: secrets.infisical.com/v1beta1
> kind: InfisicalConnection
> metadata:
>   name: my-infisical-connection
> spec:
>   address: https://infisical.mydomain.com
>   tls:
>     caCertificate:
>       name: secret-containing-ca-certificate
>       namespace: default
>       key: ca.crt
> ```
>
> All CRDs that reference this `InfisicalConnection` will automatically use the configured TLS settings.

> [tab] v1alpha1
>
> In v1alpha1, TLS is configured inline on each CRD:
>
> ```yaml theme={"dark"}
> spec:
>   hostAPI: https://app.infisical.com/api
>   tls:
>     caRef:
>       secretName: custom-ca-certificate
>       secretNamespace: default
>       key: ca.crt
> ```

## Templating

Fetching secrets from Infisical as-is via the operator may not be enough. This is where templating functionality may be helpful.
Using Go templates, you can format, combine, and create new key-value pairs from secrets fetched from Infisical before storing them as Kubernetes Secrets or ConfigMaps.

When a template is set, only the keys defined in `template.data` are included in the output.
When no template is set, all fetched secrets are included as-is.

Each secret is available in the template context as `.SECRET_KEY`, which is an object with two accessors:

* `.Value`: the secret value.
* `.SecretPath`: the path of the secret in Infisical.

### Key/value template map

```yaml theme={"dark"}
targets:
  - name: my-app-config
    namespace: default
    kind: Secret
    creationPolicy: Owner
    template:
      engineVersion: v1
      data:
        DSN: "{{ .SECRET.Value }}.namespace:{{ .SECRET2.Value }}"
        ANOTHER_ONE: "{{ .SECRET3.Value }}"
```

### Bulk string template with a loop

```yaml theme={"dark"}
targets:
  - name: all-secrets
    namespace: default
    kind: Secret
    creationPolicy: Owner
    template:
      engineVersion: v1
      data: |
        {{- range $key, $secret := . }}
        {{ $key }}: "{{ $secret.Value }}"
        {{- end }}
```

To help transform your secrets further, the operator provides a set of built-in functions that you can use in your templates.

### Available helper functions

The Infisical Secrets Operator exposes a wide range of helper functions to make it easier to work with secrets in Kubernetes.

> [accordion] encodeBase64
>
> Encodes a string to a base64-encoded string (e.g. `hello world` becomes `aGVsbG8gd29ybGQ=`).
>
> **Signature**
>
> ```go theme={"dark"}
> encodeBase64(plainString string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     ENCODED_SECRET: "{{ .MY_SECRET.Value | encodeBase64 }}"
> ```

> [accordion] decodeBase64ToBytes
>
> Decodes a base64-encoded string back to its original value (e.g. `aGVsbG8gd29ybGQ=` becomes `hello world`).
>
> **Signature**
>
> ```go theme={"dark"}
> decodeBase64ToBytes(encodedString string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     DECODED_SECRET: "{{ .MY_BASE64_SECRET.Value | decodeBase64ToBytes }}"
> ```

> [accordion] pkcs12key
>
> Extracts all private keys from a PKCS#12 archive and returns them as PKCS#8 PEM-encoded blocks (`-----BEGIN PRIVATE KEY-----...`).
> The archive must not be password-protected — use `pkcs12keyPass` for password-protected archives.
>
> **Signature**
>
> ```go theme={"dark"}
> pkcs12key(input string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     tls.key: "{{ .TLS_CERT_PKCS12.Value | pkcs12key }}"
> ```

> [accordion] pkcs12keyPass
>
> Same as `pkcs12key`, but uses the provided password to decrypt the PKCS#12 archive.
>
> **Signature**
>
> ```go theme={"dark"}
> pkcs12keyPass(password string, input string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     tls.key: '{{ pkcs12keyPass "my-password" .TLS_CERT_PKCS12.Value }}'
> ```

> [accordion] pkcs12cert
>
> Extracts all certificates from a PKCS#12 archive and returns them as an ordered PEM chain (`-----BEGIN CERTIFICATE-----...`).
> Sort order: **leaf → intermediate(s) → root**. If disjunct or multiple leaf certs are provided, they are returned as-is.
> The archive must not be password-protected — use `pkcs12certPass` for password-protected archives.
>
> **Signature**
>
> ```go theme={"dark"}
> pkcs12cert(input string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     tls.crt: "{{ .TLS_CERT_PKCS12.Value | pkcs12cert }}"
> ```

> [accordion] pkcs12certPass
>
> Same as `pkcs12cert`, but uses the provided password to decrypt the PKCS#12 archive.
>
> **Signature**
>
> ```go theme={"dark"}
> pkcs12certPass(password string, input string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     tls.crt: '{{ pkcs12certPass "my-password" .TLS_CERT_PKCS12.Value }}'
> ```

> [accordion] pemToPkcs12
>
> Takes a PEM-encoded certificate and private key and creates a base64-encoded PKCS#12 archive.
> The output is not password-protected — use `pemToPkcs12Pass` to set a password.
>
> **Signature**
>
> ```go theme={"dark"}
> pemToPkcs12(cert string, key string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     keystore.p12: '{{ pemToPkcs12 .TLS_CERT.Value .TLS_KEY.Value }}'
> ```

> [accordion] pemToPkcs12Pass
>
> Same as `pemToPkcs12`, but encrypts the PKCS#12 archive with the provided password.
>
> **Signature**
>
> ```go theme={"dark"}
> pemToPkcs12Pass(cert string, key string, password string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     keystore.p12: '{{ pemToPkcs12Pass .TLS_CERT.Value .TLS_KEY.Value "my-password" }}'
> ```

> [accordion] fullPemToPkcs12
>
> Takes a full PEM-encoded certificate chain (leaf + intermediates + root) and a private key, and creates a base64-encoded PKCS#12 archive that includes the entire chain.
> The output is not password-protected — use `fullPemToPkcs12Pass` to set a password.
>
> **Signature**
>
> ```go theme={"dark"}
> fullPemToPkcs12(cert string, key string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     keystore.p12: '{{ fullPemToPkcs12 .TLS_FULL_CHAIN.Value .TLS_KEY.Value }}'
> ```

> [accordion] fullPemToPkcs12Pass
>
> Same as `fullPemToPkcs12`, but encrypts the PKCS#12 archive with the provided password.
>
> **Signature**
>
> ```go theme={"dark"}
> fullPemToPkcs12Pass(cert string, key string, password string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     keystore.p12: '{{ fullPemToPkcs12Pass .TLS_FULL_CHAIN.Value .TLS_KEY.Value "my-password" }}'
> ```

> [accordion] filterPEM
>
> Filters PEM blocks by type from a bundle containing multiple PEM blocks (e.g. extract only `CERTIFICATE` or `PRIVATE KEY` blocks).
> Common PEM types: `CERTIFICATE`, `PRIVATE KEY`, `PUBLIC KEY`, `RSA PRIVATE KEY`.
>
> **Signature**
>
> ```go theme={"dark"}
> filterPEM(pemType string, input string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     ca.crt: '{{ filterPEM "CERTIFICATE" .TLS_BUNDLE.Value }}'
>     tls.key: '{{ filterPEM "PRIVATE KEY" .TLS_BUNDLE.Value }}'
> ```

> [accordion] filterCertChain
>
> Filters PEM certificates by their position in a certificate chain. The chain is automatically ordered before filtering.
> Accepted types: `leaf` (end-entity certificate), `intermediate` (all intermediate CA certificates), `root` (root CA certificate).
> Returns an empty string if the requested type is not present in the chain.
>
> **Signature**
>
> ```go theme={"dark"}
> filterCertChain(certType string, input string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     tls.crt: '{{ filterCertChain "leaf" .TLS_CHAIN.Value }}'
>     ca.crt: '{{ filterCertChain "root" .TLS_CHAIN.Value }}'
>     intermediate.crt: '{{ filterCertChain "intermediate" .TLS_CHAIN.Value }}'
> ```

> [accordion] jwkPublicKeyPem
>
> Takes a JSON-serialized JWK and returns a PEM block of type `PUBLIC KEY` containing the public key.
> Uses [`x509.MarshalPKIXPublicKey`](https://pkg.go.dev/crypto/x509#MarshalPKIXPublicKey) internally.
>
> **Signature**
>
> ```go theme={"dark"}
> jwkPublicKeyPem(jwkJson string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     public.pem: "{{ .MY_JWK.Value | jwkPublicKeyPem }}"
> ```

> [accordion] jwkPrivateKeyPem
>
> Takes a JSON-serialized JWK and returns a PEM block of type `PRIVATE KEY` containing the private key.
> Uses [`x509.MarshalPKCS8PrivateKey`](https://pkg.go.dev/crypto/x509#MarshalPKCS8PrivateKey) internally.
>
> **Signature**
>
> ```go theme={"dark"}
> jwkPrivateKeyPem(jwkJson string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     private.pem: "{{ .MY_JWK.Value | jwkPrivateKeyPem }}"
> ```

> [accordion] toYaml
>
> Marshals a value to a YAML string. Returns an empty string on marshal error.
>
> **Signature**
>
> ```go theme={"dark"}
> toYaml(v any) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     config.yaml: "{{ .APP_CONFIG.Value | fromYaml | toYaml }}"
> ```

> [accordion] fromYaml
>
> Parses a YAML string into a `map[string]any`, useful for extracting individual fields from a YAML-formatted secret (e.g. `(fromYaml .DB_CONFIG.Value).host` returns the `host` field).
>
> **Signature**
>
> ```go theme={"dark"}
> fromYaml(str string) map[string]any
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     DB_HOST: '{{ (fromYaml .DB_CONFIG.Value).host }}'
>     DB_PORT: '{{ (fromYaml .DB_CONFIG.Value).port }}'
> ```

> [accordion] secretFrom
>
> > [!NOTE]
> >
> > This function is only available in `v1beta1` resources (e.g. `InfisicalStaticSecret`).
>
> Resolves a secret from a specific folder path within the Infisical project. Takes a path and a secret name as parameters, and returns the secret's value by default. You can optionally use `.Value` or `.SecretPath` accessors on the result -- if omitted, `.Value` is used.
>
> This is especially useful when multiple secrets share the same key, either from recursive fetches across different paths or from multiple sources. In both cases, the merge strategy only keeps the first occurrence (read more [here](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-static-secret-crd.md#sources)), so `secretFrom` lets you explicitly select the one you need by its full path.
>
> > [!NOTE]
> >
> > If multiple sources contain a secret with the same name and path, the secret from the first source listed in the `sources` array will be used.
>
> **Signature**
>
> ```go theme={"dark"}
> secretFrom(path string, secretName string) string
> ```
>
> **Template usage**
>
> ```yaml theme={"dark"}
> template:
>   data:
>     # .Value is implicit when no accessor is specified
>     DB_PASSWORD: '{{ secretFrom "/databases/postgres" "DB_PASSWORD" }}'
>     # Explicit .Value accessor (same result as above)
>     STRIPE_API_KEY: '{{ (secretFrom "/services/payments" "API_KEY").Value }}'
>     # Using .SecretPath to get the folder path instead of the value
>     DATADOG_API_KEY: '{{ (secretFrom "/services/observability" "API_KEY").Value }}'
>     DATADOG_API_KEY_PATH: '{{ (secretFrom "/services/observability" "API_KEY").SecretPath }}'
> ```

### Sprig functions

The Infisical Secrets Operator integrates with the [Sprig library](https://github.com/Masterminds/sprig) to provide additional helper functions.

> [!NOTE]
>
> We've removed `expandEnv` and `env` from the supported functions for security reasons.

## Migrating from v1alpha1 to v1beta1

> [!NOTE]
>
> This migration guide applies to `InfisicalSecret` only. `InfisicalPushSecret` and `InfisicalDynamicSecret` don't have v1beta1 replacements yet and should continue to be used as-is.

The v1beta1 API introduces a cleaner separation of concerns. Instead of defining authentication and connection details inline in each secret CRD, you now create dedicated `InfisicalConnection` and `InfisicalAuth` resources that can be shared across multiple secret resources.

### Key changes

* **Secret resource:** `InfisicalSecret` -> `InfisicalStaticSecret`

  `InfisicalStaticSecret` replaces the v1alpha1 `InfisicalSecret` CRD. Instead of defining auth and connection settings inline, it references dedicated `InfisicalAuth` and `InfisicalConnection` resources.

* **Authentication:** inline `authentication` -> `InfisicalAuth`

  Authentication config is now defined in a standalone `InfisicalAuth` resource that can be reused across CRDs. Authenticated credentials are cached and shared by all resources referencing the same `InfisicalAuth`.

* **Connection:** inline `hostAPI` / `tls` -> `InfisicalConnection`

  Connection config is now defined in a standalone `InfisicalConnection` resource that can be reused by auth and secret resources.

### Migration steps

**1. Create an InfisicalConnection resource**

Extract the `hostAPI` and `tls` settings from your existing CRD into a new `InfisicalConnection` resource.
See the [InfisicalConnection CRD](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-connection-crd.md) documentation for the full spec.

**2. Create an InfisicalAuth resource**

Extract the `authentication` block from your existing CRD into a new `InfisicalAuth` resource.
See the [InfisicalAuth CRD](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-auth-crd.md) documentation for the full spec.

**3. Replace InfisicalSecret with InfisicalStaticSecret**

Create a new `InfisicalStaticSecret` resource that references your `InfisicalConnection` and `InfisicalAuth` resources.
See the [InfisicalStaticSecret CRD](https://infisical.com/docs/integrations/platforms/kubernetes/infisical-static-secret-crd.md) documentation for the full spec.

If you were using templates, note that `engineVersion` is now a required field and the only accepted value is `v1`. The `includeAllSecrets` option no longer exists. Instead, you can iterate over all secrets using a bulk string template with a range loop. See the [Templating](#templating) section for details and examples.

**4. Delete the old v1alpha1 resource**

Once you have verified that the new v1beta1 resources are working, delete the old `InfisicalSecret` CRD instance.

## Uninstall operator

The managed secret created by the operator won't be deleted when the operator is uninstalled.

Uninstall Infisical Helm repository

```bash theme={"dark"}
  helm uninstall <release name>
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.