# !secret

The `!secret` YAML function resolves a **declared** secret from its configured backend (a `secret: true`
[store](/cli/configuration/stores) such as AWS SSM, AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, or
GCP Secret Manager, or a SOPS-encrypted file) and substitutes its value into an Atmos stack manifest. Resolved
values are automatically registered with the I/O masker, so they are redacted in all output.

## Usage

```yaml
  !secret <NAME> | path <yq-expression> | default <default-value>
```

The secret `<NAME>` must be declared under the component's [`secrets.vars`](/cli/configuration/secrets) before it
can be referenced — this keeps the registry of secrets GitOps-friendly and explicit.

Usage examples:

```yaml
  # Resolve a declared secret
  vars:
    api_key: !secret DATADOG_API_KEY

  # Provide a default when the secret is missing
  vars:
    api_key: !secret DATADOG_API_KEY | default "dev-key"

  # Extract a nested value from a structured (JSON) secret
  vars:
    db_host: !secret DATABASE_CONFIG | path ".host"
    db_password: !secret DATABASE_CONFIG | path ".credentials.password"

  # Combine path and default
  vars:
    db_host: !secret DATABASE_CONFIG | path ".host" | default "localhost"
```

## Declaration

A secret must be declared before use. Declarations live in stack/component config and reference a backend by name:

**File:** `stacks/prod/api.yaml`

```yaml
components:
  terraform:
    api:
      secrets:
        vars:
          DATADOG_API_KEY:
            description: "Datadog API key for monitoring"
            store: app-secrets       # a `secret: true` store (track 1)
            required: true
          GITHUB_APP_KEY:
            sops: dev-sops           # a SOPS provider (track 2)
      vars:
        datadog_api_key: !secret DATADOG_API_KEY
```

The backend (`store:` or `sops:`) carries the provider, region, prefix, and optional auth `identity`, so the
declaration stays terse. See [Secrets configuration](/cli/configuration/secrets) for backend setup.

## Masking and Inspection

`!secret` is automatically masked everywhere its value appears. In **inspection** commands —
[`atmos describe`](/cli/commands/describe/component) and the [`atmos list`](/cli/commands/list/list-values)
family — `!secret` resolves to `<MASKED>` **without contacting the backend** when masking is enabled (the
default). This means you can inspect a stack's shape with **no cloud credentials**:

```shell
# No credentials needed — the secret renders as <MASKED>
atmos describe component api --stack=prod

# Reveal the real value (requires access to the secret backend)
atmos describe component api --stack=prod --mask=false
```

In **value-producing** commands (`terraform plan`/`apply`, [`atmos secret get`](/cli/commands/secret/get)), the
value is always retrieved because it is needed to function; `--mask` only controls whether it is redacted in
display output.

## Access Rule

`!secret` is the **only** accessor for a `secret: true` store. Using [`!store`](/functions/yaml/store) against a
`secret: true` store is an error — this makes declarations mandatory-by-construction for secrets and removes any
ambiguity about whether a value is sensitive.

## See Also

- [`atmos secret` command](/cli/commands/secret/usage)
- [Secrets configuration](/cli/configuration/secrets)
- [`!store` YAML function](/functions/yaml/store)
