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

# Create a Secret

> Create and manage encrypted secrets for workloads. Covers secret types, workload injection methods, pull secret configuration, and CLI/Console workflows.

Secrets provide secure, centralized storage for sensitive data like credentials, API keys, certificates, and configuration values. Control Plane encrypts all secrets at rest and in transit, with fine-grained access control through policies ensuring only authorized workloads can access the data they need.

<CardGroup cols={2}>
  <Card title="Encrypted Storage" icon="shield-halved">
    All secrets are encrypted using industry-standard algorithms
  </Card>

  <Card title="Policy-Based Access" icon="key">
    Fine-grained control over which workloads can access secrets
  </Card>
</CardGroup>

<Card title="Multiple Injection Methods" icon="syringe" horizontal>
  Inject secrets as environment variables, mount as files, or use as pull secrets for private container registries
</Card>

***

## How Secrets Work

Secrets can be used in two primary ways: **injected into workloads** at runtime, or as **pull secrets** for accessing private container registries.

### Injecting Secrets into Workloads

<Steps>
  <Step title="Create a Secret">
    Store your sensitive data in Control Plane using the Console, CLI, Terraform, or Pulumi. Choose the appropriate secret type for your use case.
  </Step>

  <Step title="Create an Identity">
    Create a [workload identity](/reference/identity) that will be used to authenticate your workload and request access to secrets.
  </Step>

  <Step title="Grant Access with a Policy">
    Create a [policy](/reference/policy) that grants the `reveal` permission on your secret to the workload identity.
  </Step>

  <Step title="Link Identity to Workload">
    Associate the identity with your workload so it inherits the policy permissions.
  </Step>

  <Step title="Reference the Secret">
    Use the `cpln://secret/SECRET_NAME` URI in your workload's environment variables or volume mounts.
  </Step>
</Steps>

<Note>
  A [workload identity](/reference/identity) **must** be granted the [reveal permission](/reference/secret#permissions) on a secret to have its value injected at runtime.
</Note>

### Using Secrets as Pull Secrets

For pulling container images from private registries (Docker Hub, ECR, GCP Artifact Registry, etc.), you can attach registry credentials directly to your GVC as **pull secrets**. This approach doesn't require identity or policy setup.

<Steps>
  <Step title="Create a Registry Secret">
    Create a [Docker](/guides/create-secret/docker), [ECR](/guides/create-secret/ecr), or [GCP](/guides/create-secret/gcp) secret with your registry credentials.
  </Step>

  <Step title="Add to GVC Pull Secrets">
    Add the secret to your GVC's `pullSecretLinks` so all workloads in that GVC can pull from the private registry.
  </Step>
</Steps>

```yaml theme={null}
kind: gvc
name: my-gvc
spec:
  pullSecretLinks:
    - //secret/my-docker-registry
    - //secret/my-ecr-credentials
```

<Tip>
  Pull secrets are configured at the GVC level and automatically available to all workloads within that GVC. No identity or policy configuration is needed for pull secrets.
</Tip>

***

## Choosing the Right Secret Type

### Cloud Provider Credentials

For authenticating with cloud services and pulling container images:

<CardGroup cols={3}>
  <Card title="AWS" icon="aws" href="/guides/create-secret/aws">
    Access key credentials for AWS services
  </Card>

  <Card title="ECR" icon="aws" href="/guides/create-secret/ecr">
    Pull images from Elastic Container Registry
  </Card>

  <Card title="GCP" icon="google" href="/guides/create-secret/gcp">
    Service account keys for Google Cloud
  </Card>

  <Card title="Azure SDK" icon="microsoft" href="/guides/create-secret/azure-sdk">
    Service principal for Azure services
  </Card>

  <Card title="Azure Connector" icon="microsoft" href="/guides/create-secret/azure-connector">
    Connect to Azure Function Apps
  </Card>

  <Card title="Docker" icon="docker" href="/guides/create-secret/docker">
    Pull from any container registry
  </Card>
</CardGroup>

### Application Secrets

For storing application configuration and credentials:

<CardGroup cols={3}>
  <Card title="Opaque" icon="file-lines" href="/guides/create-secret/opaque">
    API keys, tokens, and general secrets
  </Card>

  <Card title="Dictionary" icon="book" href="/guides/create-secret/dictionary">
    Multiple related key-value pairs
  </Card>

  <Card title="Username & Password" icon="user-lock" href="/guides/create-secret/userpass">
    Database and service credentials
  </Card>
</CardGroup>

### Certificates & Keys

For cryptographic operations and secure communication:

<CardGroup cols={3}>
  <Card title="TLS" icon="file-certificate" href="/guides/create-secret/tls">
    SSL/TLS certificates for HTTPS
  </Card>

  <Card title="Keypair" icon="key" href="/guides/create-secret/keypair">
    SSH keys and signing keys
  </Card>

  <Card title="NATS Account" icon="message" href="/guides/create-secret/nats-account">
    NATS messaging authentication
  </Card>
</CardGroup>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use specific secret types">
    Choose the most specific secret type for your use case. For example, use **AWS** secrets for AWS credentials rather than storing them as **Opaque**. Specific types provide better validation and structured access.
  </Accordion>

  <Accordion title="Follow least-privilege access">
    Grant `reveal` permission only to identities that need it. Create separate policies for different secrets rather than granting broad access.
  </Accordion>

  <Accordion title="Use environment variables for simple values">
    For API keys and tokens, environment variables are the simplest approach. Use volume mounts for certificates or when your application expects files.
  </Accordion>

  <Accordion title="Rotate secrets regularly">
    Establish a rotation schedule for credentials. Update secrets in Control Plane and redeploy workloads to pick up new values.
  </Accordion>

  <Accordion title="Avoid hardcoding in IaC">
    Never commit secret values to version control. Use Terraform variables, Pulumi config secrets, or external secret management tools.
  </Accordion>

  <Accordion title="Use Dictionary for related values">
    Group related configuration values (like database host, port, and name) in a **Dictionary** secret. This makes management easier while still allowing individual key access.
  </Accordion>
</AccordionGroup>

<Warning>
  Use caution when handling sensitive values in IaC scripts. Best practices recommend using variables, encrypted state files, or external secret management rather than hard-coding sensitive values.
</Warning>

***

## Using Secrets in Workloads

Once created, secrets can be injected into workloads as environment variables or mounted as files.

<Tabs>
  <Tab title="Console UI">
    <Note>
      This guide assumes you already have a GVC, workload, and secret. If you haven't created these yet, see [Create a GVC](/guides/create-gvc), [Create a Workload](/guides/create-workload), and the secret type guides above.
    </Note>

    ### Step 1: Create an Identity

    <Steps>
      <Step title="Navigate to Identities">
        Navigate to **Identities** and click **New**, or click **Create** in the top-right corner and select **Identity**.
      </Step>

      <Step title="Select GVC">
        Ensure the correct **GVC** is selected in the GVC dropdown.
      </Step>

      <Step title="Enter name">
        Enter a **Name** (e.g., `my-workload-identity`).
      </Step>

      <Step title="Create the identity">
        Click **Create**.
      </Step>
    </Steps>

    ### Step 2: Link Identity to Workload

    <Steps>
      <Step title="Navigate to your workload">
        Navigate to your workload.
      </Step>

      <Step title="Open Identity settings">
        Click **Identity** in the left pane.
      </Step>

      <Step title="Select identity">
        Select the identity you created (e.g., `my-workload-identity`).
      </Step>

      <Step title="Save changes">
        Click **Save**.
      </Step>
    </Steps>

    ### Step 3: Create a Policy for Secret Access

    <Steps>
      <Step title="Navigate to Policies">
        Navigate to **Policies** and click **New**, or click **Create** in the top-right corner and select **Policy**.
      </Step>

      <Step title="Enter name">
        Enter a **Name** (e.g., `workload-secret-access`).
      </Step>

      <Step title="Configure target">
        Click **Target** in the left pane. Under **Kind**, select **Secret**.
      </Step>

      <Step title="Add secret items">
        Click **Items** in the left pane. Click **Add** and select the secret you want to grant access to.
      </Step>

      <Step title="Add binding">
        Click **Bindings** in the left pane. Click **Add**.
      </Step>

      <Step title="Configure permissions">
        In the **Permissions** tab, select **reveal**. In the **Identities** tab, select the identity linked to your workload. Click **OK**.
      </Step>

      <Step title="Create the policy">
        Click **Create**.
      </Step>
    </Steps>

    ### Step 4: Inject Secret into Workload

    **Option 1: Environment Variables**

    <Steps>
      <Step title="Navigate to your workload">
        Navigate to your workload.
      </Step>

      <Step title="Open Env Vars">
        Click **Containers** in the left pane, then select the **Env Vars** tab.
      </Step>

      <Step title="Add environment variable">
        Click **Add**. Enter the variable **Name** (e.g., `MY_SECRET`).
      </Step>

      <Step title="Select secret">
        In the **Value** dropdown, change **Literal Value** to **CPLN Secret**. In the dropdown next to it, find and select your secret by name.
      </Step>

      <Step title="Update workload">
        Click **Update**.
      </Step>
    </Steps>

    **Option 2: Volume Mount**

    <Steps>
      <Step title="Navigate to your workload">
        Navigate to your workload.
      </Step>

      <Step title="Open Volumes">
        Click **Containers** in the left pane, then select the **Volumes** tab.
      </Step>

      <Step title="Add volume">
        Click **Add**. Ensure **CPLN Secret** is selected for the URI type.
      </Step>

      <Step title="Configure mount">
        Select the secret from the dropdown by name. Enter the **Path** where the secret will be mounted (e.g., `/secrets/my-secret.txt`).
      </Step>

      <Step title="Update workload">
        Click **Update**.
      </Step>
    </Steps>
  </Tab>

  <Tab title="CLI">
    <Note>
      This guide assumes you already have a GVC, workload, and secret. If you haven't created these yet, see [Create a GVC](/guides/create-gvc), [Create a Workload](/guides/create-workload), and the secret type guides above.
    </Note>

    ### Step 1: Create an Identity

    ```bash theme={null}
    cpln identity create \
      --name my-workload-identity \
      --gvc my-gvc \
      --org my-org
    ```

    ### Step 2: Link Identity to Workload

    ```bash theme={null}
    cpln workload update my-workload \
      --set spec.identityLink=my-workload-identity \
      --gvc my-gvc \
      --org my-org
    ```

    ### Step 3: Create a Policy for Secret Access

    Create the policy targeting your secret:

    ```bash theme={null}
    cpln policy create \
      --name workload-secret-access \
      --target-kind secret \
      --resource my-secret \
      --org my-org
    ```

    Add a binding to grant the identity the `reveal` permission:

    ```bash theme={null}
    cpln policy add-binding workload-secret-access \
      --permission reveal \
      --identity my-workload-identity \
      --gvc my-gvc \
      --org my-org
    ```

    ### Step 4: Inject Secret into Workload

    Update your workload to reference the secret as an environment variable:

    ```bash theme={null}
    cpln workload update my-workload \
      --set spec.containers.<container-name>.env.MY_SECRET.value=cpln://secret/my-secret \
      --gvc my-gvc \
      --org my-org
    ```

    Or mount as a volume by exporting your workload, editing it, and applying:

    ```bash theme={null}
    cpln workload get my-workload \
      -o yaml-slim \
      --gvc my-gvc \
      --org my-org > my-workload.yaml
    ```

    Edit `my-workload.yaml` to add a volume to your container:

    ```yaml theme={null}
    spec:
      containers:
        - name: main
          # ... existing config ...
          volumes:
            - uri: "cpln://secret/my-secret"
              path: /secrets/my-secret.txt
    ```

    Apply the updated workload:

    ```bash theme={null}
    cpln apply --file my-workload.yaml --gvc my-gvc --org my-org
    ```
  </Tab>

  <Tab title="Terraform">
    The following example shows a complete Terraform configuration that creates all the resources needed to inject a secret into a workload. Comments highlight each resource and the key configurations for secret access.

    ```hcl theme={null}
    # Create a GVC
    resource "cpln_gvc" "my_gvc" {
      name        = "my-gvc"
      description = "My GVC"
      locations   = ["aws-us-west-2", "gcp-us-east1"]
    }

    # Create a Secret
    resource "cpln_secret" "my_secret" {
      name        = "my-secret"
      description = "Third-party API key"

      opaque {
        payload  = "my-secret-value"
        encoding = "plain"
      }
    }

    # Create an Identity for the workload
    resource "cpln_identity" "workload_identity" {
      gvc         = cpln_gvc.my_gvc.name
      name        = "my-workload-identity"
      description = "Identity for workload secret access"
    }

    # Create the Workload with identity linked
    resource "cpln_workload" "my_workload" {
      gvc  = cpln_gvc.my_gvc.name
      name = "my-workload"
      type = "standard"

      # Link the identity to the workload
      identity_link = cpln_identity.workload_identity.self_link

      container {
        name   = "main"
        image  = "kennethreitz/httpbin"
        cpu    = "50m"
        memory = "128Mi"

        ports {
          number   = 80
          protocol = "http"
        }

        # Inject secret as environment variable
        env = {
          MY_SECRET = cpln_secret.my_secret.secret_link
        }

        # Mount secret as a file
        volume {
          uri  = cpln_secret.my_secret.secret_link
          path = "/secrets/my-secret.txt"
        }
      }

      options {
        capacity_ai     = true
        timeout_seconds = 5

        autoscaling {
          metric    = "disabled"
          target    = 95
          min_scale = 1
          max_scale = 1
        }
      }

      firewall_spec {
        external {
          inbound_allow_cidr = ["0.0.0.0/0"]
        }
      }
    }

    # Create a Policy granting the identity reveal permission on the secret
    resource "cpln_policy" "secret_access" {
      name        = "workload-secret-access"
      description = "Allow workload to reveal secret"
      target_kind = "secret"
      target_links = [cpln_secret.my_secret.self_link]

      binding {
        permissions     = ["reveal"]
        principal_links = [cpln_identity.workload_identity.self_link]
      }
    }
    ```

    <Warning>
      This example uses a hardcoded secret value for testing. In production, use Terraform variables with `sensitive = true` or integrate with a secrets manager.
    </Warning>
  </Tab>

  <Tab title="Pulumi">
    The following examples show complete Pulumi programs that create all the resources needed to inject a secret into a workload. Comments highlight each resource and the key configurations for secret access.

    <Tabs>
      <Tab title="TypeScript">
        ```typescript theme={null}
        import * as cpln from "@pulumiverse/cpln";

        // Create a GVC
        const gvc = new cpln.Gvc("my-gvc", {
          name: "my-gvc",
          description: "My GVC",
          locations: ["aws-us-west-2", "gcp-us-east1"],
        });

        // Create a Secret
        const secret = new cpln.Secret("my-secret", {
          name: "my-secret",
          description: "Third-party API key",
          opaque: {
            payload: "my-secret-value",
            encoding: "plain",
          },
        });

        // Create an Identity for the workload
        const workloadIdentity = new cpln.Identity("my-workload-identity", {
          gvc: gvc.name,
          name: "my-workload-identity",
          description: "Identity for workload secret access",
        });

        // Create the Workload with identity linked
        const workload = new cpln.Workload("my-workload", {
          gvc: gvc.name,
          name: "my-workload",
          type: "standard",
          // Link the identity to the workload
          identityLink: workloadIdentity.selfLink,
          containers: [
            {
              name: "main",
              image: "kennethreitz/httpbin",
              cpu: "50m",
              memory: "128Mi",
              ports: [
                {
                  number: 80,
                  protocol: "http",
                },
              ],
              // Inject secret as environment variable
              env: {
                MY_SECRET: secret.secretLink,
              },
              // Mount secret as a file
              volumes: [
                {
                  uri: secret.secretLink,
                  path: "/secrets/my-secret.txt",
                },
              ],
            },
          ],
          options: {
            capacityAi: true,
            timeoutSeconds: 5,
            autoscaling: {
              metric: "disabled",
              target: 95,
              minScale: 1,
              maxScale: 1,
            },
          },
          firewallSpec: {
            external: {
              inboundAllowCidrs: ["0.0.0.0/0"],
            },
          },
        });

        // Create a Policy granting the identity reveal permission on the secret
        const secretAccessPolicy = new cpln.Policy("workload-secret-access", {
          name: "workload-secret-access",
          description: "Allow workload to reveal secret",
          targetKind: "secret",
          targetLinks: [secret.selfLink],
          bindings: [
            {
              permissions: ["reveal"],
              principalLinks: [workloadIdentity.selfLink],
            },
          ],
        });
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        import pulumiverse_cpln as cpln

        # Create a GVC
        gvc = cpln.Gvc("my-gvc",
            name="my-gvc",
            description="My GVC",
            locations=["aws-us-west-2", "gcp-us-east1"])

        # Create a Secret
        secret = cpln.Secret("my-secret",
            name="my-secret",
            description="Third-party API key",
            opaque={
                "payload": "my-secret-value",
                "encoding": "plain",
            })

        # Create an Identity for the workload
        workload_identity = cpln.Identity("my-workload-identity",
            gvc=gvc.name,
            name="my-workload-identity",
            description="Identity for workload secret access")

        # Create the Workload with identity linked
        workload = cpln.Workload("my-workload",
            gvc=gvc.name,
            name="my-workload",
            type="standard",
            # Link the identity to the workload
            identity_link=workload_identity.self_link,
            containers=[{
                "name": "main",
                "image": "kennethreitz/httpbin",
                "cpu": "50m",
                "memory": "128Mi",
                "ports": [{
                    "number": 80,
                    "protocol": "http",
                }],
                # Inject secret as environment variable
                "env": {
                    "MY_SECRET": secret.secret_link,
                },
                # Mount secret as a file
                "volumes": [{
                    "uri": secret.secret_link,
                    "path": "/secrets/my-secret.txt",
                }],
            }],
            options={
                "capacity_ai": True,
                "timeout_seconds": 5,
                "autoscaling": {
                    "metric": "disabled",
                    "target": 95,
                    "min_scale": 1,
                    "max_scale": 1,
                },
            },
            firewall_spec={
                "external": {
                    "inbound_allow_cidrs": ["0.0.0.0/0"],
                },
            })

        # Create a Policy granting the identity reveal permission on the secret
        secret_access_policy = cpln.Policy("workload-secret-access",
            name="workload-secret-access",
            description="Allow workload to reveal secret",
            target_kind="secret",
            target_links=[secret.self_link],
            bindings=[{
                "permissions": ["reveal"],
                "principal_links": [workload_identity.self_link],
            }])
        ```
      </Tab>

      <Tab title="Go">
        ```go theme={null}
        package main

        import (
            "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
            "github.com/pulumiverse/pulumi-cpln/sdk/go/cpln"
        )

        func main() {
            pulumi.Run(func(ctx *pulumi.Context) error {
                // Create a GVC
                gvc, err := cpln.NewGvc(ctx, "my-gvc", &cpln.GvcArgs{
                    Name:        pulumi.String("my-gvc"),
                    Description: pulumi.String("My GVC"),
                    Locations:   pulumi.StringArray{pulumi.String("aws-us-west-2"), pulumi.String("gcp-us-east1")},
                })
                if err != nil {
                    return err
                }

                // Create a Secret
                secret, err := cpln.NewSecret(ctx, "my-secret", &cpln.SecretArgs{
                    Name:        pulumi.String("my-secret"),
                    Description: pulumi.String("Third-party API key"),
                    Opaque: &cpln.SecretOpaqueArgs{
                        Payload:  pulumi.String("my-secret-value"),
                        Encoding: pulumi.String("plain"),
                    },
                })
                if err != nil {
                    return err
                }

                // Create an Identity for the workload
                workloadIdentity, err := cpln.NewIdentity(ctx, "my-workload-identity", &cpln.IdentityArgs{
                    Gvc:         gvc.Name,
                    Name:        pulumi.String("my-workload-identity"),
                    Description: pulumi.String("Identity for workload secret access"),
                })
                if err != nil {
                    return err
                }

                // Create the Workload with identity linked
                _, err = cpln.NewWorkload(ctx, "my-workload", &cpln.WorkloadArgs{
                    Gvc:  gvc.Name,
                    Name: pulumi.String("my-workload"),
                    Type: pulumi.String("standard"),
                    // Link the identity to the workload
                    IdentityLink: workloadIdentity.SelfLink,
                    Containers: cpln.WorkloadContainerArray{
                        &cpln.WorkloadContainerArgs{
                            Name:   pulumi.String("main"),
                            Image:  pulumi.String("kennethreitz/httpbin"),
                            Cpu:    pulumi.String("50m"),
                            Memory: pulumi.String("128Mi"),
                            Ports: cpln.WorkloadContainerPortArray{
                                &cpln.WorkloadContainerPortArgs{
                                    Number:   pulumi.Int(80),
                                    Protocol: pulumi.String("http"),
                                },
                            },
                            // Inject secret as environment variable
                            Env: pulumi.StringMap{
                                "MY_SECRET": secret.SecretLink,
                            },
                            // Mount secret as a file
                            Volumes: cpln.WorkloadContainerVolumeArray{
                                &cpln.WorkloadContainerVolumeArgs{
                                    Uri:  secret.SecretLink,
                                    Path: pulumi.String("/secrets/my-secret.txt"),
                                },
                            },
                        },
                    },
                    Options: &cpln.WorkloadOptionsArgs{
                        CapacityAi:     pulumi.Bool(true),
                        TimeoutSeconds: pulumi.Int(5),
                        Autoscaling: &cpln.WorkloadOptionsAutoscalingArgs{
                            Metric:   pulumi.String("disabled"),
                            Target:   pulumi.Int(95),
                            MinScale: pulumi.Int(1),
                            MaxScale: pulumi.Int(1),
                        },
                    },
                    FirewallSpec: &cpln.WorkloadFirewallSpecArgs{
                        External: &cpln.WorkloadFirewallSpecExternalArgs{
                            InboundAllowCidrs: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
                        },
                    },
                })
                if err != nil {
                    return err
                }

                // Create a Policy granting the identity reveal permission on the secret
                _, err = cpln.NewPolicy(ctx, "workload-secret-access", &cpln.PolicyArgs{
                    Name:        pulumi.String("workload-secret-access"),
                    Description: pulumi.String("Allow workload to reveal secret"),
                    TargetKind:  pulumi.String("secret"),
                    TargetLinks: pulumi.StringArray{secret.SelfLink},
                    Bindings: cpln.PolicyBindingArray{
                        &cpln.PolicyBindingArgs{
                            Permissions:    pulumi.StringArray{pulumi.String("reveal")},
                            PrincipalLinks: pulumi.StringArray{workloadIdentity.SelfLink},
                        },
                    },
                })
                if err != nil {
                    return err
                }

                return nil
            })
        }
        ```
      </Tab>

      <Tab title="C#">
        ```csharp theme={null}
        using Pulumi;
        using Pulumiverse.Cpln;
        using Pulumiverse.Cpln.Inputs;

        return await Deployment.RunAsync(() =>
        {
            // Create a GVC
            var gvc = new Gvc("my-gvc", new GvcArgs
            {
                Name = "my-gvc",
                Description = "My GVC",
                Locations = { "aws-us-west-2", "gcp-us-east1" },
            });

            // Create a Secret
            var secret = new Secret("my-secret", new SecretArgs
            {
                Name = "my-secret",
                Description = "Third-party API key",
                Opaque = new SecretOpaqueArgs
                {
                    Payload = "my-secret-value",
                    Encoding = "plain",
                },
            });

            // Create an Identity for the workload
            var workloadIdentity = new Identity("my-workload-identity", new IdentityArgs
            {
                Gvc = gvc.Name,
                Name = "my-workload-identity",
                Description = "Identity for workload secret access",
            });

            // Create the Workload with identity linked
            var workload = new Workload("my-workload", new WorkloadArgs
            {
                Gvc = gvc.Name,
                Name = "my-workload",
                Type = "standard",
                // Link the identity to the workload
                IdentityLink = workloadIdentity.SelfLink,
                Containers = new[]
                {
                    new WorkloadContainerArgs
                    {
                        Name = "main",
                        Image = "kennethreitz/httpbin",
                        Cpu = "50m",
                        Memory = "128Mi",
                        Ports = new[]
                        {
                            new WorkloadContainerPortArgs
                            {
                                Number = 80,
                                Protocol = "http",
                            },
                        },
                        // Inject secret as environment variable
                        Env = {
                            { "MY_SECRET", secret.SecretLink },
                        },
                        // Mount secret as a file
                        Volumes = new[]
                        {
                            new WorkloadContainerVolumeArgs
                            {
                                Uri = secret.SecretLink,
                                Path = "/secrets/my-secret.txt",
                            },
                        },
                    },
                },
                Options = new WorkloadOptionsArgs
                {
                    CapacityAi = true,
                    TimeoutSeconds = 5,
                    Autoscaling = new WorkloadOptionsAutoscalingArgs
                    {
                        Metric = "disabled",
                        Target = 95,
                        MinScale = 1,
                        MaxScale = 1,
                    },
                },
                FirewallSpec = new WorkloadFirewallSpecArgs
                {
                    External = new WorkloadFirewallSpecExternalArgs
                    {
                        InboundAllowCidrs = { "0.0.0.0/0" },
                    },
                },
            });

            // Create a Policy granting the identity reveal permission on the secret
            var secretAccessPolicy = new Policy("workload-secret-access", new PolicyArgs
            {
                Name = "workload-secret-access",
                Description = "Allow workload to reveal secret",
                TargetKind = "secret",
                TargetLinks = { secret.SelfLink },
                Bindings = new[]
                {
                    new PolicyBindingArgs
                    {
                        Permissions = { "reveal" },
                        PrincipalLinks = { workloadIdentity.SelfLink },
                    },
                },
            });
        });
        ```
      </Tab>
    </Tabs>

    <Warning>
      This example uses a hardcoded secret value for testing. In production, use Pulumi config secrets (`pulumi config set --secret`) to manage sensitive values securely.
    </Warning>
  </Tab>
</Tabs>

### Secret Reference Formats

When referencing secrets, use the `cpln://secret/` URI format:

| Format                          | Description                                             | Example                               |
| :------------------------------ | :------------------------------------------------------ | :------------------------------------ |
| `cpln://secret/SECRET_NAME`     | Reference entire secret payload                         | `cpln://secret/my-secret`             |
| `cpln://secret/SECRET_NAME.KEY` | Reference specific key in dictionary/structured secrets | `cpln://secret/my-config.DB_PASSWORD` |

<Note>
  The mount behavior varies by secret type:

  * **Opaque**: The payload is mounted as a file at the specified path
  * **Dictionary and other structured secrets**: A directory is created containing files for each key/property
  * **Docker, Azure SDK, and GCP**: The secret is mounted as a file named `___cpln___.secret` in the specified directory
</Note>

For more details, see the [Workload Volumes Reference](/reference/workload/volumes).

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Secret Reference" icon="book" href="/reference/secret">
    Complete API reference for secrets
  </Card>

  <Card title="Identity Reference" icon="fingerprint" href="/reference/identity">
    Learn more about workload identities
  </Card>

  <Card title="Policy Reference" icon="shield" href="/reference/policy">
    Understand policy-based access control
  </Card>

  <Card title="Workload Volumes" icon="hard-drive" href="/reference/workload/volumes">
    Volume mount options and behaviors
  </Card>
</CardGroup>
