> ## 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.

<br />

<div style={{ position: "relative", paddingBottom: "56.25%", height: 0, overflow: "hidden", maxWidth: "100%" }}>
  <iframe src="https://www.youtube.com/embed/Nz15mAwIkYc" title="YouTube video player" style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", border: 0 }} allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowFullScreen />
</div>

<br />

<Info>
  The operator supports two CRD API versions: **v1beta1** and **v1alpha1**. Use **v1beta1** for new installations; **v1alpha1** is legacy and will be deprecated soon.
</Info>

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

<Tabs>
  <Tab title="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 are not officially supported.

    * 1.33
    * 1.32
    * 1.31
    * 1.30
    * 1.29
  </Tab>

  <Tab title="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).
  </Tab>
</Tabs>

## Install

The operator can be installed via [Helm](https://helm.sh). Helm is a package manager for Kubernetes that allows you to define, install, and upgrade Kubernetes applications.

**Install the latest Helm repository**

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

```bash theme={"dark"}
helm repo update
```

The operator can be installed either cluster-wide or restricted to a specific namespace.
If you require stronger isolation and stricter access controls, a namespace-scoped installation may make more sense.

<Tabs>
  <Tab title="Cluster Wide Installation">
    When installing the operator cluster-wide, the operator will watch and manage CRDs across all namespaces in the cluster.
    This is the default installation method and the quickest way to get started with using the operator. Cluster-wide installations are useful for:

    * **Simplified Management**: A single operator instance manages secrets across all namespaces
    * **Centralized Operations**: One deployment to monitor, update, and maintain
    * **Cross-Namespace Flexibility**: Easily manage secrets for applications spanning multiple namespaces
    * **Quick Setup**: Works out of the box with no additional RBAC configuration required

    ```bash theme={"dark"}
    helm install --generate-name infisical-helm-charts/secrets-operator
    ```
  </Tab>

  <Tab title="Namespace Scoped Installation">
    The operator can be configured to watch and manage secrets in a specific namespace instead of having cluster-wide access. This is useful for:

    * **Enhanced Security**: Limit the operator's permissions to only specific namespaces instead of cluster-wide access
    * **Multi-tenant Clusters**: Run separate operator instances for different teams or applications
    * **Resource Isolation**: Ensure operators in different namespaces don't interfere with each other
    * **Development & Testing**: Run development and production operators side by side in isolated namespaces

    <Note>
      For multiple namespace-scoped installations, only the first installation should install CRDs. Subsequent installations should set `installCRDs: false` to avoid conflicts as CRDs are cluster-wide resources.
    </Note>

    ### Single Namespace

    ```bash theme={"dark"}
    # First namespace installation (with CRDs)
    helm install operator-namespaced infisical-helm-charts/secrets-operator \
      --namespace single-namespace \
      --set scopedNamespaces=single-namespace \
      --set scopedRBAC=true
    ```

    <Accordion title="Using values.yaml file">
      ```yaml values-operator1.yaml theme={"dark"}
        scopedNamespaces: single-namespace
        scopedRBAC: true
        installCRDs: true
      ```
    </Accordion>

    ### Multiple Namespaces

    ```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 title="Using values.yaml file">
      ```yaml values-operator1.yaml theme={"dark"}
        scopedNamespaces: ns1
        scopedRBAC: true
        installCRDs: false
      ```

      ```yaml values-operator2.yaml theme={"dark"}
        scopedNamespaces: ns2
        scopedRBAC: true
        installCRDs: false
      ```
    </Accordion>

    ### Multiple namespaces with one operator installation

    ```bash theme={"dark"}
      helm install operator infisical-helm-charts/secrets-operator \
      --namespace operator-namespace \
      --set "scopedNamespaces={ns1,ns2,ns3}" \
      --set scopedRBAC=true
    ```

    <Accordion title="Using values.yaml file">
      ```yaml values.yaml theme={"dark"}
        scopedNamespaces:
          - ns1
          - ns2
          - ns3
        scopedRBAC: true
      ```
    </Accordion>
  </Tab>
</Tabs>

### Using your own service account

By default a service account is created for the operator based on the operator release name.
You can bring your own service account by setting `controllerManager.serviceAccount.create` to `false` and setting `controllerManager.serviceAccount.name` to the name of the service account you want to use in your values.yaml file.

Example values.yaml file:

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

<Note>
  Please note that if you set `controllerManager.serviceAccount.create` to `false`, the service account needs to already exist in the namespace you are installing the operator in.
</Note>

<Tip>
  Custom service accounts are supported in chart version `0.10.11` and above. Please upgrade your helm chart to `0.10.11` or above before attempting to use custom service accounts.
</Tip>

## Custom Resource Definitions

<Tabs>
  <Tab title="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](/integrations/platforms/kubernetes/infisical-connection-crd)      | Defines how to connect to an Infisical instance (host, TLS). Referenced by other CRDs. |
    | [InfisicalAuth](/integrations/platforms/kubernetes/infisical-auth-crd)                  | Defines authentication credentials for a machine identity. Referenced by other CRDs.   |
    | [InfisicalStaticSecret](/integrations/platforms/kubernetes/infisical-static-secret-crd) | Sync secrets from Infisical to a Kubernetes secret. Replaces `InfisicalSecret`.        |
  </Tab>

  <Tab title="v1alpha1">
    <Warning>
      The v1alpha1 CRDs are legacy and are planned for deprecation.
    </Warning>

    | CRD                                                                                       | Status     | Description                                                                                                                                                                                                                    |
    | ----------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | [InfisicalSecret](/integrations/platforms/kubernetes/infisical-secret-crd)                | Deprecated | Sync secrets from Infisical to a Kubernetes secret. Use [InfisicalStaticSecret](/integrations/platforms/kubernetes/infisical-static-secret-crd) (v1beta1) instead. See [migration guide](#migrating-from-v1alpha1-to-v1beta1). |
    | [InfisicalPushSecret](/integrations/platforms/kubernetes/infisical-push-secret-crd)       | Active     | Push secrets from a Kubernetes secret to Infisical.                                                                                                                                                                            |
    | [InfisicalDynamicSecret](/integrations/platforms/kubernetes/infisical-dynamic-secret-crd) | Active     | Sync dynamic secrets and create leases automatically in Kubernetes.                                                                                                                                                            |
  </Tab>
</Tabs>

## 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) ...
```

<AccordionGroup>
  <Accordion title="telemetry.serviceMonitor.enabled" query="telemetry.serviceMonitor.enabled">
    Enable ServiceMonitor for Prometheus Operator. Defaults to `false`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.selectors" query="telemetry.serviceMonitor.selectors">
    Additional labels for ServiceMonitor. Defaults to `{}`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.scheme" query="telemetry.serviceMonitor.scheme">
    Scheme to use for the ServiceMonitor. Defaults to `https`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.port" query="telemetry.serviceMonitor.port">
    Port to use for the ServiceMonitor. Defaults to `https`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.path" query="telemetry.serviceMonitor.path">
    Path to use for the ServiceMonitor. Defaults to `/metrics`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.interval" query="telemetry.serviceMonitor.interval">
    Scrape interval. Defaults to `30s`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.scrapeTimeout" query="telemetry.serviceMonitor.scrapeTimeout">
    Scrape timeout. Defaults to `10s`.
  </Accordion>

  <Accordion title="telemetry.serviceMonitor.bearerTokenFile" query="telemetry.serviceMonitor.bearerTokenFile">
    Bearer token file. Defaults to `/var/run/secrets/kubernetes.io/serviceaccount/token`.
  </Accordion>
</AccordionGroup>

```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`

### Example Prometheus Setup

<Steps>
  <Step title="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
    ```
  </Step>

  <Step title="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
    ```
  </Step>

  <Step title="Verify ServiceMonitor">
    ```bash theme={"dark"}
    kubectl get servicemonitor
    ```

    Check that the ServiceMonitor appears in your operator's namespace.
  </Step>

  <Step title="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**.
  </Step>
</Steps>

### 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.

<Tabs>
  <Tab title="v1beta1 (Recommended)">
    In v1beta1, TLS is configured on the [InfisicalConnection](/integrations/platforms/kubernetes/infisical-connection-crd) 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>

  <Tab title="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
    ```
  </Tab>
</Tabs>

## 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.

<AccordionGroup>
  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="secretFrom">
    <Note>This function is only available in `v1beta1` resources (e.g. `InfisicalStaticSecret`).</Note>

    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](/integrations/platforms/kubernetes/infisical-static-secret-crd#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.
    </Note>

    **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 }}'
    ```
  </Accordion>
</AccordionGroup>

### 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.
</Note>

## Migrating from v1alpha1 to v1beta1

<Info>
  This migration guide applies to `InfisicalSecret` only. `InfisicalPushSecret` and `InfisicalDynamicSecret` do not have v1beta1 replacements yet and should continue to be used as-is.
</Info>

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

<Steps>
  <Step title="Create an InfisicalConnection resource">
    Extract the `hostAPI` and `tls` settings from your existing CRD into a new `InfisicalConnection` resource.
    See the [InfisicalConnection CRD](/integrations/platforms/kubernetes/infisical-connection-crd) documentation for the full spec.
  </Step>

  <Step title="Create an InfisicalAuth resource">
    Extract the `authentication` block from your existing CRD into a new `InfisicalAuth` resource.
    See the [InfisicalAuth CRD](/integrations/platforms/kubernetes/infisical-auth-crd) documentation for the full spec.
  </Step>

  <Step title="Replace InfisicalSecret with InfisicalStaticSecret">
    Create a new `InfisicalStaticSecret` resource that references your `InfisicalConnection` and `InfisicalAuth` resources.
    See the [InfisicalStaticSecret CRD](/integrations/platforms/kubernetes/infisical-static-secret-crd) 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.
  </Step>

  <Step title="Delete the old v1alpha1 resource">
    Once you have verified that the new v1beta1 resources are working, delete the old `InfisicalSecret` CRD instance.
  </Step>
</Steps>

## Uninstall Operator

The managed secret created by the operator will not be deleted when the operator is uninstalled.

Uninstall Infisical Helm repository

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