Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ For some features, additional programs must be available:
- [helm](https://helm.sh/) for rendering Helm charts
- [kyverno](https://kyverno.io/docs/kyverno-cli/) ^1.13.x when using the Nyl `PostProcessor` resource
- [sops](https://github.com/getsops/sops) when using the SOPS secrets provider
- [vault](https://www.vaultproject.io/) when using the Vault secrets provider (optional - only for local development)

## Local development

Expand Down
138 changes: 138 additions & 0 deletions docs/content/reference/configuration/secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,144 @@ files apply. The `path` field is relative to the location of the `nyl-secrets.ya

---

## Provider: [Vault](https://www.vaultproject.io/)

Allows you to retrieve secrets from a HashiCorp Vault server using the KV secrets engine v2. This provider is designed
to work securely in multi-tenant environments and integrates with both local development and ArgoCD deployments.

### Authentication

The provider supports two authentication methods:

- **JWT Authentication (ArgoCD context)**: When running in ArgoCD, the provider authenticates using the Kubernetes
service account JWT token mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`. This enables secure
multi-tenant deployments where each application's workload identity is used to access only its authorized secrets.

- **Token Authentication (Local development)**: When running locally, the provider uses the token stored in
`~/.vault-token` (obtained via `vault login`).

The provider automatically detects the execution context by checking for ArgoCD environment variables.

### Key Format with Hash Separator

The Vault provider uses a hash (`#`) separator to distinguish between the secret path and field access:

- `"database"` retrieves the entire secret stored at the `database` path (returns a dict)
- `"database#password"` retrieves the `password` field from the `database` secret
- `"database#credentials.username"` retrieves nested fields using dot notation
- `"db.prod#password"` retrieves the `password` field from a secret at path `db.prod`

**Why use hash separator?** This allows you to access secrets with dots in their path names, which was not possible
with pure dot notation. For example, a secret at path `my-app.v2` can be accessed with `"my-app.v2#fieldname"`.

### Configuration Options

- `url` (required): The URL of the Vault server (e.g., `https://vault.example.com:8200`)
- `mount_point` (optional): The mount point of the KV secrets engine. Default: `secret`
- `path` (optional): Path prefix within the KV secrets engine. For example, if `path` is `myapp/`, secrets will be
retrieved from `secret/data/myapp/...`
- `jwt_role` (optional): The Vault role to use for JWT authentication when running in ArgoCD. Required for JWT
authentication.
- `jwt_auth_method` (optional): JWT authentication method to use. Options:
- `"kubernetes"` (default): Use Kubernetes service account token (simple, single-tenant)
- `"nyl"`: Nyl generates ArgoCD application-specific JWT tokens for multi-tenant environments
- `jwt_signing_key` (optional): Signing key for Nyl JWT tokens (required when `jwt_auth_method="nyl"`). Can also be
provided via the `NYL_VAULT_JWT_SIGNING_KEY` environment variable. This should be a shared secret between Nyl
and Vault.
- `namespace` (optional): The Vault namespace to use (Vault Enterprise feature only)

The provider supports token authentication via the `VAULT_TOKEN` environment variable or `~/.vault-token` file
(obtained via `vault login`).

**Note**: The Vault provider is read-only. Setting or unsetting secrets is not supported - manage Vault secrets
through Vault's own interface or CLI tools.

__Example__

=== "TOML"

```toml title="nyl-secrets.toml"
[default]
type = "vault"
url = "https://vault.example.com:8200"
mount_point = "secret"
path = "myapp/"
jwt_role = "nyl-argocd-role"
jwt_auth_method = "kubernetes" # or "nyl" for multi-tenant
```

=== "YAML"

```yaml title="nyl-secrets.yaml"
default:
type: vault
url: https://vault.example.com:8200
mount_point: secret
path: myapp/
jwt_role: nyl-argocd-role
jwt_auth_method: kubernetes # or "nyl" for multi-tenant
```

=== "JSON"

```json title="nyl-secrets.json"
{
"default": {
"type": "vault",
"url": "https://vault.example.com:8200",
"mount_point": "secret",
"path": "myapp/",
"jwt_role": "nyl-argocd-role",
"jwt_auth_method": "kubernetes"
}
}
```

### Usage Examples

```yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
stringData:
# Access entire secret
config: ${{ secrets.get("database") | to_json }}
# Access specific field
password: ${{ secrets.get("database#password") }}
# Access nested field
username: ${{ secrets.get("database#credentials.username") }}
# Access secret with dots in path
api-key: ${{ secrets.get("my-app.v2#api_key") }}
```

### Security Considerations

When using Vault in a multi-tenant ArgoCD environment:

#### For Kubernetes JWT Authentication (simple, single-tenant)
1. Configure Vault to trust the Kubernetes cluster's JWT issuer
2. Create a Vault role for each application or team with appropriate policies
3. Bind the Vault role to the ArgoCD application's service account
4. Ensure the `jwt_role` in the Nyl configuration matches the Vault role
5. Use Vault policies to restrict access to only the necessary secrets

#### For Nyl JWT Authentication (multi-tenant)
1. Configure Vault to trust Nyl as a JWT issuer (using the `iss` claim from generated tokens)
2. Create Vault roles that map to ArgoCD project and application identities
3. Nyl automatically generates JWTs when in ArgoCD context with claims including:
- `iss`: Issuer (e.g., `https://argocd.example.com/#nyl-v1`)
- `aud`: Audience (Vault URL)
- `sub`: Subject (e.g., `project:default:application:my-app`)
- `argocd_project`: The ArgoCD project name
- `argocd_app`: The ArgoCD application name
- `repository`: The Git repository URL
4. Use Vault policies to restrict access based on these claims
5. Set `jwt_auth_method: "nyl"` and provide `jwt_signing_key` in the provider configuration
6. The JWT token is automatically generated by Nyl based on the ArgoCD environment

---

## Provider: [KubernetesSecret](https://kubernetes.io/docs/concepts/configuration/secret/)

Allows you to point to a Kubernetes Secret as a source for secrets. Since Kubernetes secret values must be strings,
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ dependencies = [
"bcrypt>=4.2.0",
"databind>=4.5.2",
"filelock>=3.15.4",
"hvac>=2.3.0",
"jinja2>=3.1.4",
"kubernetes>=30.1.0",
"loguru>=0.7.2",
"nr-stream>=1.1.5",
"pyjwt>=2.8.0",
"pyroscope-io>=0.8.11",
"pyyaml>=6.0.1",
"requests>=2.32.3",
Expand Down
Loading