Skip to main content

SOPS

SOPS (Secrets OPerationS) is an open-source tool that encrypts the values of a YAML file while leaving its keys readable, so secrets can live in Git and be reviewed like code. The Azure Secrets Blueprint encrypts each stage's application secrets with that stage's Key Vault key and syncs them into the stage's application vault on merge.

What it does​

SOPS generates a data key per file, encrypts every value with it, and wraps the data key with one or more master keys held in a key service, here an Azure Key Vault key. A .sops.yaml file maps paths to keys with creation rules. Anyone allowed to use the key in Key Vault can decrypt; anyone else sees only ciphertext. Because the keys of the YAML stay in clear text, a pull request shows which secrets changed without revealing a value.

How BuiltForProd uses it​

The repository. acme-azure-blueprint-secrets has one folder per stage (sandbox/, dev/, staging/, prod/) and one file per application in each. .sops.yaml maps each folder to its key; only the folder decides which key encrypts a file:

Azure/acme-azure-blueprint-secrets/.sops.yaml (lines 29-37)
creation_rules:
- path_regex: ^sandbox[/\\][^/\\]+\.yaml$
azure_keyvault: https://kv-acme-eus2-sec-sops.vault.azure.net/keys/sops-sandbox/REPLACE_WITH_KEY_VERSION # TODO: paste the kid of sops-sandbox
- path_regex: ^dev[/\\][^/\\]+\.yaml$
azure_keyvault: https://kv-acme-eus2-sec-sops.vault.azure.net/keys/sops-dev/REPLACE_WITH_KEY_VERSION # TODO: paste the kid of sops-dev
- path_regex: ^staging[/\\][^/\\]+\.yaml$
azure_keyvault: https://kv-acme-eus2-sec-sops.vault.azure.net/keys/sops-staging/REPLACE_WITH_KEY_VERSION # TODO: paste the kid of sops-staging (leads only)
- path_regex: ^prod[/\\][^/\\]+\.yaml$
azure_keyvault: https://kv-acme-eus2-sec-sops.vault.azure.net/keys/sops-prod/REPLACE_WITH_KEY_VERSION # TODO: paste the kid of sops-prod (leads only)

Each URL includes the key version, so after a yearly rotation the URL changes and sops updatekeys re-wraps the files. No encrypted_regex is set: every value and every comment is encrypted.

The keys. The sops-keys unit of the Azure Enterprise Baseline creates the four RSA 4096 keys in kv-acme-eus2-sec-sops (acme-core-security), rotated every 365 days. Key-scoped Key Vault Crypto User grants decide who can decrypt which stage:

GroupKeys
ACME_PlatformLeads, ACME_DevOpsLeadsall four, prod included
Platform and DevOps engineers, App, ETL and AI leads and developerssops-sandbox and sops-dev only
id-acme-secrets-syncer (the workflows)all four

The vault keeps its public endpoint, so developers run sops from their workstations with their az login session; Entra RBAC still applies to every call. Key Vault covers the vault's other controls.

The workflows. Both run as id-acme-secrets-syncer, which trusts only environment:<stage> subjects through GitHub OIDC, so every job runs in its stage's GitHub Environment and staging and prod wait for that Environment's reviewers.

  • plan.yml on a pull request validates each stage and does a dry run that reports, per secret, whether it would be created, updated or left unchanged, without printing a value.
  • sync.yml on a merge to main syncs only the stages whose folder changed (every stage when scripts/ or .sops.yaml changed), one stage at a time. scripts/push-to-keyvault.sh decrypts each file and writes every key as the secret <app>--<KEY> (underscores become dashes) into the stage's application vault kv-acme-eus2-<stage>-app, tagged app, key and source=sops. An unchanged value creates no new version. A key removed from the YAML is kept in the vault until someone runs the workflow manually with prune.

The application vaults are private, so the sync job runs on the self-hosted runners of the Azure Enterprise Baseline. The syncer holds Key Vault Secrets Officer on each application vault, granted by the Web App Blueprint from the principal ID the contract vault publishes. Inside the cluster, the External Secrets Operator turns the vault's secrets into Kubernetes Secrets.

SOPS 3.13.3 and yq v4.47.1 are pinned in both workflows and their downloads are checked against SHA-256 checksums before use.

Terms you will see​

TermMeaning
.sops.yamlThe configuration that maps file paths to encryption keys.
Creation ruleOne path regex and the key that encrypts matching files.
Data keyThe per-file key that encrypts values; itself wrapped by the Key Vault key.
updatekeysThe SOPS command that re-wraps files for a new key version.
PruneThe manual sync option that deletes vault secrets whose key left the YAML.

Where to read more​