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

# Using the InfisicalStaticSecret CRD

> Learn how to sync secrets from Infisical and store them as native Kubernetes secret resources using the v1beta1 InfisicalStaticSecret CRD.

The `InfisicalStaticSecret` CRD syncs secrets from Infisical into your Kubernetes cluster as native Kubernetes Secrets or ConfigMaps.
It replaces the v1alpha1 `InfisicalSecret` CRD with a cleaner design: authentication and connection details are defined as separate reusable resources ([InfisicalAuth](/docs/integrations/platforms/kubernetes/infisical-auth-crd) and [InfisicalConnection](/docs/integrations/platforms/kubernetes/infisical-connection-crd)) instead of inline blocks.

### Prerequisites

Before creating an `InfisicalStaticSecret`, you need:

1. An [InfisicalConnection](/docs/integrations/platforms/kubernetes/infisical-connection-crd) resource configured with your Infisical host and TLS settings.
2. An [InfisicalAuth](/docs/integrations/platforms/kubernetes/infisical-auth-crd) resource configured with your machine identity authentication method.

### Examples

Each example below contains every resource you need to apply: the credential `Secret`, `InfisicalConnection`, `InfisicalAuth`, and `InfisicalStaticSecret`.
Copy the one that matches your environment, replace the placeholder values, and `kubectl apply -f` it.

For more details on each resource, see the [InfisicalConnection](/docs/integrations/platforms/kubernetes/infisical-connection-crd) and [InfisicalAuth](/docs/integrations/platforms/kubernetes/infisical-auth-crd) documentation or access our [samples](https://github.com/Infisical/kubernetes-operator/tree/main/examples/v1beta1/infisicalstaticsecret).

<AccordionGroup>
  <Accordion title="Kubernetes Auth (Recommended)">
    Best for workloads already running in Kubernetes.

    This example uses **short-lived service account tokens**. If you prefer to use a Gateway as the token reviewer instead, see the [Kubernetes Auth guide](/docs/documentation/platform/identities/kubernetes-auth) for alternative setup options.

    ```yaml complete-kubernetes-auth.yaml theme={"dark"}
    # 1. Service account used by the operator for token review
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: infisical-service-account
      namespace: default
    ---
    # 2. Bind the service account to system:auth-delegator so it can
    #    validate tokens via the Kubernetes TokenReview API
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: infisical-service-account-role-binding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: system:auth-delegator
    subjects:
      - kind: ServiceAccount
        name: infisical-service-account
        namespace: default
    ---
    # 3. Kubernetes secret holding the machine identity ID
    apiVersion: v1
    kind: Secret
    metadata:
      name: kubernetes-credentials
      namespace: default
    type: Opaque
    stringData:
      identityId: <your-machine-identity-id>
    ---
    # 4. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 5. Auth using a Kubernetes service account token
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: kubernetes
      kubernetes:
        identityIdRef:
          name: kubernetes-credentials
          namespace: default
          key: identityId
        serviceAccountRef:
          name: infisical-service-account
          namespace: default
    ---
    # 6. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>

  <Accordion title="Universal Auth">
    Platform-agnostic authentication using a client ID and client secret. Works in any environment.

    ```yaml complete-universal-auth.yaml theme={"dark"}
    # 1. Kubernetes secret holding the client credentials
    apiVersion: v1
    kind: Secret
    metadata:
      name: universal-auth-credentials
      namespace: default
    type: Opaque
    stringData:
      clientId: <your-identity-client-id>
      clientSecret: <your-identity-client-secret>
    ---
    # 2. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 3. Auth using Universal Auth credentials
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: universal
      universal:
        clientIdRef:
          name: universal-auth-credentials
          namespace: default
          key: clientId
        clientSecretRef:
          name: universal-auth-credentials
          namespace: default
          key: clientSecret
    ---
    # 4. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>

  <Accordion title="AWS IAM Auth">
    For workloads running in AWS (EC2, Lambda, EKS). The operator uses the instance's IAM role to authenticate.

    ```yaml complete-aws-iam-auth.yaml theme={"dark"}
    # 1. Kubernetes secret holding the machine identity ID
    apiVersion: v1
    kind: Secret
    metadata:
      name: aws-iam-credentials
      namespace: default
    type: Opaque
    stringData:
      identityId: <your-machine-identity-id>
    ---
    # 2. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 3. Auth using AWS IAM
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: aws-iam
      awsIam:
        identityIdRef:
          name: aws-iam-credentials
          namespace: default
          key: identityId
    ---
    # 4. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>

  <Accordion title="Azure Auth">
    For workloads running in Azure. Uses the Azure managed identity attached to the compute resource.

    ```yaml complete-azure-auth.yaml theme={"dark"}
    # 1. Kubernetes secret holding the machine identity ID
    apiVersion: v1
    kind: Secret
    metadata:
      name: azure-credentials
      namespace: default
    type: Opaque
    stringData:
      identityId: <your-machine-identity-id>
    ---
    # 2. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 3. Auth using Azure managed identity
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: azure
      azure:
        identityIdRef:
          name: azure-credentials
          namespace: default
          key: identityId
    ---
    # 4. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>

  <Accordion title="GCP ID Token Auth">
    For workloads running in GCP. Uses the GCP metadata server to obtain an ID token.

    ```yaml complete-gcp-id-token-auth.yaml theme={"dark"}
    # 1. Kubernetes secret holding the machine identity ID
    apiVersion: v1
    kind: Secret
    metadata:
      name: gcp-id-token-credentials
      namespace: default
    type: Opaque
    stringData:
      identityId: <your-machine-identity-id>
    ---
    # 2. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 3. Auth using a GCP ID token
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: gcp-id-token
      gcpIdToken:
        identityIdRef:
          name: gcp-id-token-credentials
          namespace: default
          key: identityId
    ---
    # 4. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>

  <Accordion title="GCP IAM Auth">
    Uses a GCP service account key file for authentication. Works both inside and outside GCP.

    <Note>
      The `serviceAccountKeyFilePath` must point to a file that exists inside the **operator pod**. You will need to create a Kubernetes Secret with your GCP service account key and mount it as a volume in the operator Deployment (or via Helm values). See the [GCP IAM Auth](/docs/documentation/platform/identities/gcp-auth) guide for details.
    </Note>

    ```yaml complete-gcp-iam-auth.yaml theme={"dark"}
    # 1. Kubernetes secret holding the machine identity ID
    apiVersion: v1
    kind: Secret
    metadata:
      name: gcp-iam-credentials
      namespace: default
    type: Opaque
    stringData:
      identityId: <your-machine-identity-id>
    ---
    # 2. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 3. Auth using GCP IAM with a service account key
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: gcp-iam
      gcpIam:
        identityIdRef:
          name: gcp-iam-credentials
          namespace: default
          key: identityId
        serviceAccountKeyFilePath: /path/to/service-account-key.json
    ---
    # 4. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>

  <Accordion title="LDAP Auth">
    Authenticates using LDAP credentials (username and password).

    ```yaml complete-ldap-auth.yaml theme={"dark"}
    # 1. Kubernetes secret holding LDAP credentials and the machine identity ID
    apiVersion: v1
    kind: Secret
    metadata:
      name: ldap-credentials
      namespace: default
    type: Opaque
    stringData:
      identityId: <your-machine-identity-id>
      username: <your-ldap-username>
      password: <your-ldap-password>
    ---
    # 2. Connection to the Infisical instance
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalConnection
    metadata:
      name: my-infisical-connection
      namespace: default
    spec:
      address: https://app.infisical.com
    ---
    # 3. Auth using LDAP
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalAuth
    metadata:
      name: my-infisical-auth
      namespace: default
    spec:
      infisicalConnectionRef:
        name: my-infisical-connection
        namespace: default
      method: ldap
      ldap:
        identityIdRef:
          name: ldap-credentials
          namespace: default
          key: identityId
        usernameRef:
          name: ldap-credentials
          namespace: default
          key: username
        passwordRef:
          name: ldap-credentials
          namespace: default
          key: password
    ---
    # 4. Sync secrets into a native Kubernetes Secret
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      namespace: default
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      syncOptions:
        refreshInterval: 60s
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```
  </Accordion>
</AccordionGroup>

## CRD properties

<Accordion title="infisicalAuthRef">
  A reference to the `InfisicalAuth` resource that defines how to authenticate with Infisical. The connection to the Infisical instance is resolved through the `InfisicalAuth` resource's `infisicalConnectionRef` field.

  | Field       | Required | Description                                    |
  | ----------- | -------- | ---------------------------------------------- |
  | `name`      | Yes      | The name of the `InfisicalAuth` resource.      |
  | `namespace` | Yes      | The namespace of the `InfisicalAuth` resource. |

  See the [InfisicalAuth CRD](/docs/integrations/platforms/kubernetes/infisical-auth-crd) documentation for details.
</Accordion>

<Accordion title="syncOptions">
  Controls the synchronization behavior.

  | Field             | Required | Description                                                                                                               |
  | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
  | `refreshInterval` | Yes      | How often to resync (e.g. `60s`, `5m`, `1h`).                                                                             |
  | `instantUpdates`  | No       | When `true`, the operator receives real-time push updates from Infisical. Please note that this is an Enterprise feature. |
</Accordion>

<Accordion title="sources">
  An array of secret sources to fetch from Infisical. All secrets from all sources are merged and made available to every target.

  When multiple sources produce a secret with the same key, the **first occurrence wins** — sources listed earlier in the array take precedence over later ones. Direct secrets always take precedence over imported secrets, regardless of source order.

  To access a secret that was dropped by the merge (e.g. a duplicate key under a different path or source), use the `secretFrom` template function to select it by its full path.

  | Field             | Required | Description                                                                 |
  | ----------------- | -------- | --------------------------------------------------------------------------- |
  | `projectId`       | No       | The Infisical project ID.                                                   |
  | `projectSlug`     | No       | The Infisical project slug.                                                 |
  | `environmentSlug` | Yes      | The environment slug (e.g. `dev`, `staging`, `prod`).                       |
  | `secretPath`      | Yes      | The path to the secrets. Root is `/`.                                       |
  | `tagSlugs`        | No       | Filter secrets by tag slugs.                                                |
  | `recursive`       | No       | Whether to recursively fetch secrets from sub-folders. Defaults to `false`. |

  <Note>You have to provide either `projectId` or `projectSlug`. If none or both are set, the CRD validation will fail.</Note>

  ```yaml theme={"dark"}
  sources:
    - projectId: <your-project-id>
      environmentSlug: dev
      secretPath: /app
    - projectId: <your-project-id>
      environmentSlug: dev
      secretPath: /shared
      recursive: true
      tagSlugs:
        - backend
  ```
</Accordion>

<Accordion title="targets">
  An array of Kubernetes Secrets or ConfigMaps to create/update with the fetched secrets.

  | Field            | Required | Description                                                                                                                                                                                                                                                                                                   |
  | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `name`           | Yes      | Name of the managed Kubernetes Secret or ConfigMap.                                                                                                                                                                                                                                                           |
  | `namespace`      | Yes      | Namespace of the managed Kubernetes Secret or ConfigMap.                                                                                                                                                                                                                                                      |
  | `kind`           | Yes      | The type of resource to create. Must be `Secret` or `ConfigMap`.                                                                                                                                                                                                                                              |
  | `secretType`     | No       | Override the default `Opaque` secret type. Only applies when `kind: Secret`. When using a typed secret (e.g. `kubernetes.io/tls`, `kubernetes.io/dockerconfigjson`), you must use a `template` to produce the keys that Kubernetes requires for that type, otherwise the API server will reject the resource. |
  | `creationPolicy` | Yes      | `Owner` sets a Kubernetes owner reference so the managed resource is automatically deleted by the garbage collector when the `InfisicalStaticSecret` is removed. `Orphan` leaves the managed resource in place.                                                                                               |
  | `template`       | No       | Optional templating configuration (see [Templating](#templating) below).                                                                                                                                                                                                                                      |
  | `metadata`       | No       | Custom `labels` and `annotations` to set on the managed resource. When set, these values are used as-is and **not** merged with the `InfisicalStaticSecret` CRD metadata.                                                                                                                                     |

  <Warning>
    ConfigMaps are intended for non-sensitive data only. Use `kind: Secret` for sensitive values.
  </Warning>

  ```yaml theme={"dark"}
  targets:
    - name: app-secrets
      namespace: default
      kind: Secret
      creationPolicy: Owner
    - name: app-config
      namespace: default
      kind: ConfigMap
      creationPolicy: Orphan
      metadata:
        labels:
          app: my-app
        annotations:
          description: "Synced from Infisical"
  ```
</Accordion>

## 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](/docs/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>

## Metadata propagation

The operator provides flexible options for managing labels and annotations on managed Kubernetes Secrets and ConfigMaps.

<AccordionGroup>
  <Accordion title="Default behavior">
    By default, the operator merges labels and annotations from the `InfisicalStaticSecret` resource into each managed Secret or ConfigMap that does not define target-level `metadata`.

    Conflict behavior:

    * Existing labels and annotations that were not previously managed by the operator are preserved.
    * Labels and annotations from the `InfisicalStaticSecret` resource take precedence when the same key already exists on the managed resource.
    * Labels and annotations previously propagated by the operator are removed if they are removed from the `InfisicalStaticSecret` resource.
    * Kubernetes system annotations and Infisical operator tracking annotations are preserved.

    ```yaml theme={"dark"}
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      labels:
        label-to-be-passed-to-managed-secret: sample-value
      annotations:
        example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      sources:
        - projectId: <your-project-id>
          environmentSlug: dev
          secretPath: /
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
    ```

    This creates a managed Secret with the inherited metadata:

    ```yaml theme={"dark"}
    apiVersion: v1
    kind: Secret
    metadata:
      name: managed-secret
      namespace: default
      labels:
        label-to-be-passed-to-managed-secret: sample-value
      annotations:
        example.com/annotation-to-be-passed-to-managed-secret: sample-value
        secrets.infisical.com/version: W/"3f1-ZyOSsrCLGSkAhhCkY2USPu2ivRw"
    type: Opaque
    data: ...
    ```
  </Accordion>

  <Accordion title="Custom target metadata">
    When you specify `metadata` on a target, those labels and annotations are used exclusively for that managed resource:

    * Target `metadata.labels` replaces the managed resource's labels.
    * Target `metadata.annotations` replaces user-defined annotations on the managed resource.
    * Kubernetes system annotations and the Infisical version annotation are preserved.
    * Labels and annotations from the `InfisicalStaticSecret` resource are not propagated to that target.
    * This lets you keep CRD-specific metadata separate from managed resource metadata.

    <Tip>
      To prevent any propagation while using target `metadata`, pass empty objects for labels and/or annotations:

      ```yaml theme={"dark"}
      targets:
        - name: managed-secret
          namespace: default
          kind: Secret
          creationPolicy: Owner
          metadata:
            labels: {}
            annotations: {}
      ```
    </Tip>

    ```yaml theme={"dark"}
    apiVersion: secrets.infisical.com/v1beta1
    kind: InfisicalStaticSecret
    metadata:
      name: my-static-secret
      labels:
        managed-by: infisical-operator
      annotations:
        example.com/cr-specific: "metadata"
    spec:
      infisicalAuthRef:
        name: my-infisical-auth
        namespace: default
      sources:
        - projectId: <your-project-id>
          environmentSlug: prod
          secretPath: /
      targets:
        - name: managed-secret-with-custom-metadata
          namespace: default
          kind: Secret
          creationPolicy: Owner
          metadata:
            labels:
              app: my-application
              environment: production
              tier: backend
            annotations:
              secret.example.com/description: "Production database credentials"
              secret.example.com/owner: "platform-team"
    ```

    This creates a managed Secret with only the target metadata:

    ```yaml theme={"dark"}
    apiVersion: v1
    kind: Secret
    metadata:
      name: managed-secret-with-custom-metadata
      namespace: default
      labels:
        app: my-application
        environment: production
        tier: backend
      annotations:
        secret.example.com/description: "Production database credentials"
        secret.example.com/owner: "platform-team"
    type: Opaque
    data: ...
    ```
  </Accordion>
</AccordionGroup>

## Applying the CRD

```bash theme={"dark"}
kubectl apply -f infisical-static-secret.yaml
```

Verify the managed secret was created:

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

## Using the managed resource in your deployment

The managed Kubernetes Secret or ConfigMap works like any other native resource. You can reference it via `envFrom`, `env`, or `volumes`:

<Tabs>
  <Tab title="Secret">
    <AccordionGroup>
      <Accordion title="envFrom">
        ```yaml theme={"dark"}
        envFrom:
          - secretRef:
              name: managed-secret
        ```
      </Accordion>

      <Accordion title="env">
        ```yaml theme={"dark"}
        env:
          - name: SECRET_NAME
            valueFrom:
              secretKeyRef:
                name: managed-secret
                key: SOME_SECRET_KEY
        ```
      </Accordion>

      <Accordion title="volumes">
        ```yaml theme={"dark"}
        volumes:
          - name: secrets-volume
            secret:
              secretName: managed-secret
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="ConfigMap">
    <AccordionGroup>
      <Accordion title="envFrom">
        ```yaml theme={"dark"}
        envFrom:
          - configMapRef:
              name: managed-configmap
        ```
      </Accordion>

      <Accordion title="env">
        ```yaml theme={"dark"}
        env:
          - name: CONFIG_VALUE
            valueFrom:
              configMapKeyRef:
                name: managed-configmap
                key: SOME_CONFIG_KEY
        ```
      </Accordion>

      <Accordion title="volumes">
        ```yaml theme={"dark"}
        volumes:
          - name: config-volume
            configMap:
              name: managed-configmap
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

## Automatic redeployment

Pods that consume a managed Secret or ConfigMap don't reload automatically when the underlying data changes. Without a restart, the workload may continue using stale values, especially when secrets are injected as environment variables.

To trigger a rolling restart when the managed resource updates, add the following annotation to the Deployment, StatefulSet, or DaemonSet that consumes it:

```yaml theme={"dark"}
secrets.infisical.com/auto-reload: "true"
```

<AccordionGroup>
  <Accordion title="Deployment example">
    <Tabs>
      <Tab title="Secret">
        ```yaml theme={"dark"}
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nginx-deployment
          labels:
            app: nginx
          annotations:
            secrets.infisical.com/auto-reload: "true"
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: nginx
          template:
            metadata:
              labels:
                app: nginx
            spec:
              containers:
                - name: nginx
                  image: nginx:1.14.2
                  envFrom:
                    - secretRef:
                        name: managed-secret
                  ports:
                    - containerPort: 80
        ```
      </Tab>

      <Tab title="ConfigMap">
        ```yaml theme={"dark"}
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: app-deployment
          labels:
            app: app
          annotations:
            secrets.infisical.com/auto-reload: "true"
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: app
          template:
            metadata:
              labels:
                app: app
            spec:
              containers:
                - name: app
                  image: mycompany/app:latest
                  envFrom:
                    - configMapRef:
                        name: managed-configmap
                  ports:
                    - containerPort: 80
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="DaemonSet example">
    <Tabs>
      <Tab title="Secret">
        ```yaml theme={"dark"}
        apiVersion: apps/v1
        kind: DaemonSet
        metadata:
          name: log-agent
          labels:
            app: log-agent
          annotations:
            secrets.infisical.com/auto-reload: "true"
        spec:
          selector:
            matchLabels:
              app: log-agent
          template:
            metadata:
              labels:
                app: log-agent
            spec:
              containers:
                - name: log-agent
                  image: mycompany/log-agent:latest
                  envFrom:
                    - secretRef:
                        name: managed-secret
                  volumeMounts:
                    - name: secrets-volume
                      mountPath: /etc/secrets
                      readOnly: true
              volumes:
                - name: secrets-volume
                  secret:
                    secretName: managed-secret
        ```
      </Tab>

      <Tab title="ConfigMap">
        ```yaml theme={"dark"}
        apiVersion: apps/v1
        kind: DaemonSet
        metadata:
          name: log-agent
          labels:
            app: log-agent
          annotations:
            secrets.infisical.com/auto-reload: "true"
        spec:
          selector:
            matchLabels:
              app: log-agent
          template:
            metadata:
              labels:
                app: log-agent
            spec:
              containers:
                - name: log-agent
                  image: mycompany/log-agent:latest
                  envFrom:
                    - configMapRef:
                        name: managed-configmap
                  volumeMounts:
                    - name: config-volume
                      mountPath: /etc/config
                      readOnly: true
              volumes:
                - name: config-volume
                  configMap:
                    name: managed-configmap
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="StatefulSet example">
    <Tabs>
      <Tab title="Secret">
        ```yaml theme={"dark"}
        apiVersion: apps/v1
        kind: StatefulSet
        metadata:
          name: db-worker
          labels:
            app: db-worker
          annotations:
            secrets.infisical.com/auto-reload: "true"
        spec:
          selector:
            matchLabels:
              app: db-worker
          serviceName: "db-worker"
          replicas: 2
          template:
            metadata:
              labels:
                app: db-worker
            spec:
              containers:
                - name: db-worker
                  image: mycompany/db-worker:stable
                  env:
                    - name: DATABASE_PASSWORD
                      valueFrom:
                        secretKeyRef:
                          name: managed-secret
                          key: DB_PASSWORD
                  ports:
                    - containerPort: 5432
        ```
      </Tab>

      <Tab title="ConfigMap">
        ```yaml theme={"dark"}
        apiVersion: apps/v1
        kind: StatefulSet
        metadata:
          name: db-worker
          labels:
            app: db-worker
          annotations:
            secrets.infisical.com/auto-reload: "true"
        spec:
          selector:
            matchLabels:
              app: db-worker
          serviceName: "db-worker"
          replicas: 2
          template:
            metadata:
              labels:
                app: db-worker
            spec:
              containers:
                - name: db-worker
                  image: mycompany/db-worker:stable
                  env:
                    - name: DATABASE_HOST
                      valueFrom:
                        configMapKeyRef:
                          name: managed-configmap
                          key: DATABASE_HOST
                  ports:
                    - containerPort: 5432
        ```
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

<Info>
  When a managed Secret or ConfigMap is updated, the operator checks for any Deployments, DaemonSets, or StatefulSets that consume the updated resource and have the `secrets.infisical.com/auto-reload: "true"` annotation. For each matching workload, the operator triggers a rolling restart so the pods pick up the latest values.
</Info>

## Troubleshooting

You can check the status of your `InfisicalStaticSecret` resource by inspecting its conditions:

```bash theme={"dark"}
kubectl get infisicalstaticsecret my-static-secret -o jsonpath='{.status.conditions}' | jq
```

When reconciliation is successful, the `secrets.infisical.com/LastReconcileStatus` condition will have `Status: "True"`, `Reason: "OK"`, and `Message: "Reconciliation successful"`.

If reconciliation fails, `Status` will be `"False"`, `Reason` will be set to `Error`, and `Message` will contain details about what went wrong.

The `ObservedGeneration` field indicates which generation of the resource spec the operator has last processed. If `ObservedGeneration` is less than `metadata.generation`, the operator has not yet reconciled the latest changes to the resource.
