Skip to main content

HashiCorp Vault Integration

Flyte integrates with HashiCorp Vault by leveraging the Vault Agent Sidecar Injector. When a task requests a secret, the VaultSecretManagerInjector adds specific annotations to the task pod. These annotations instruct the Vault Agent to retrieve secrets from Vault and mount them as files within the pod.

Configure the Vault Secret Manager

To enable Vault integration, you must configure the VaultSecretManagerConfig within the Flyte configuration. This configuration specifies the Vault role and any additional annotations required by your Vault setup.

{
"webhook": {
"secretManagerTypes": ["vault"],
"vaultSecretManager": {
"role": "flyte-task-role",
"annotations": {
"vault.hashicorp.com/agent-pre-populate-only": "true",
"vault.hashicorp.com/agent-limits-cpu": "100m"
}
}
}
}

The VaultSecretManagerConfig struct in flyteplugins/go/tasks/pluginmachinery/secret/config/config.go supports the following fields:

  • Role: The Vault role that the injector will use for authentication.
  • Annotations: A map of custom annotations to add to the pod, allowing you to customize the Vault Agent behavior (e.g., resource limits or sidecar configuration).
  • KVVersion: (Deprecated) The default KV engine version. Use the GroupVersion field in the secret request instead.

Requesting Secrets in Tasks

Flyte maps secret requests to Vault paths using the Group and Key fields. The Group corresponds to the Vault secret path, and the Key corresponds to the specific key within that secret.

For Vault KV Secrets Engine V2, specify kv2 in the GroupVersion field. This ensures the injector uses the correct template query (.Data.data) to extract the secret value.

# Example of how a secret request is structured in Flyte
secret = Secret(
group="secret/data/my-app",
key="api_key",
group_version="kv2"
)

The VaultSecretManagerInjector transforms this request into the following annotations (using a unique UUID to prevent collisions):

vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "flyte-task-role"
vault.hashicorp.com/agent-inject-secret-<uuid>: "secret/data/my-app"
vault.hashicorp.com/agent-inject-template-<uuid>: '{{- with secret "secret/data/my-app" -}}{{ .Data.data.api_key }}{{- end -}}'
vault.hashicorp.com/agent-inject-file-<uuid>: "secret/data/my-app/api_key"

KV Engine Version 1

For unversioned secrets (KV V1), set the GroupVersion to kv1. This changes the template query to .Data.

secret = Secret(
group="secret/my-legacy-app",
key="password",
group_version="kv1"
)

Accessing Secrets in the Task

Secrets are mounted as files at a predictable path. The VaultSecretManagerInjector automatically sets the FLYTE_SECRETS_DEFAULT_DIR environment variable to /etc/flyte/secrets.

Files are organized by their group and key: /etc/flyte/secrets/<SecretGroup>/<SecretKey>

For a secret with group="foo" and key="bar", the file will be located at: /etc/flyte/secrets/foo/bar

Troubleshooting and Limitations

Unsupported Mount Requirements

The Vault injector only supports FILE or ANY mount requirements. If you attempt to use ENV_VAR, the injection will fail with an error:

// From flyteplugins/go/tasks/pluginmachinery/secret/vault_secret_manager.go
case coreIdl.Secret_ENV_VAR:
return p, false, fmt.Errorf("Env_Var is not a supported mount requirement for Vault Secret Manager")

Vault Agent Requirement

The VaultSecretManagerInjector does not communicate with Vault directly. It only adds annotations. A Vault Agent Sidecar Injector must be installed and configured in your Kubernetes cluster for these annotations to result in mounted secrets.

Multiple Secrets

Flyte supports requesting multiple secrets in a single task. The injector uses uuid.NewUUID() for each secret's annotation keys (e.g., agent-inject-secret-<uuid>) to ensure that multiple secrets from different paths can be mounted simultaneously without overwriting each other's configuration.