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 GCP Secrets Blueprint encrypts each stage's application secrets with that stage's Cloud KMS key and syncs them into Secret Manager of the stage project 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 a Cloud KMS key. A .sops.yaml file maps paths to keys with creation rules. Anyone allowed to use the key in Cloud KMS 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-gcp-blueprint-secrets has one folder per stage (sandbox/, dev/, staging/, prod/) and one flat YAML file per application in each. .sops.yaml maps each folder to its key; only the folder decides which key encrypts a file:
creation_rules:
- path_regex: ^sandbox[/\\][^/\\]+\.yaml$
gcp_kms: projects/acme-core-security/locations/us-west1/keyRings/acme-sops/cryptoKeys/sops-sandbox # TODO: project id incl. suffix, namespace and home region
- path_regex: ^dev[/\\][^/\\]+\.yaml$
gcp_kms: projects/acme-core-security/locations/us-west1/keyRings/acme-sops/cryptoKeys/sops-dev # TODO: project id incl. suffix, namespace and home region
- path_regex: ^staging[/\\][^/\\]+\.yaml$
gcp_kms: projects/acme-core-security/locations/us-west1/keyRings/acme-sops/cryptoKeys/sops-staging # TODO: project id incl. suffix (leads only)
- path_regex: ^prod[/\\][^/\\]+\.yaml$
gcp_kms: projects/acme-core-security/locations/us-west1/keyRings/acme-sops/cryptoKeys/sops-prod # TODO: project id incl. suffix (leads only)
Cloud KMS keys are named without a version: SOPS encrypts with the primary version and Cloud KMS decrypts with whichever version encrypted, so the yearly rotation changes nothing in the repository. No encrypted_regex is set, so every value and every comment is encrypted. A pre-commit hook refuses a commit that touches a plaintext stage file.
The keys. The kms-sops unit of the GCP Enterprise Baseline creates the four keys in the key ring acme-sops of acme-core-security. Key IAM decides who can decrypt which stage: the platform and DevOps leads use every key, every engineer group only sops-sandbox and sops-dev, and the syncer holds Decrypter on all four. Cloud KMS lists the grants. Developers run sops with their own Application Default Credentials, so access is enforced by Cloud KMS, not only by GitHub.
The workflows. Both authenticate through Workload Identity Federation as sa-acme-secrets-syncer, whose federation admits this repository's tokens only from GitHub Environment runs, so every job runs in its stage's Environment and staging and prod wait for that Environment's reviewers.
plan.ymlon a pull request validates each stage (encrypted, decryptable, flat, noPLACEHOLDERvalue) and does a dry run that reports per secretWould create,Would update,UnchangedorKept, without printing a value.sync.ymlon a merge tomainsyncs only the stages whose folder changed (every stage whenscripts/or.sops.yamlchanged), one stage at a time.scripts/push-to-secretmanager.shdecrypts each file and writes every key as the secret<app>--<KEY>in Secret Manager ofacme-plat-<stage>, with user-managed replication in the home region and the labelsapp,keyandsource=sops. An unchanged value creates no new version. A key removed from the YAML stays in Secret Manager, listed asKept, until someone runs the workflow manually withprune.
The syncer may administer every secret of the stage projects except the platform-owned ones whose IDs start with platform--. The jobs use GitHub-hosted runners; RUNNER_LABELS moves them to the Baseline's self-hosted runners once a VPC Service Controls perimeter is enforced. SOPS 3.13.3 and yq v4.47.1 are pinned and their downloads are checked against SHA-256 checksums.
Terms you will see
| Term | Meaning |
|---|---|
.sops.yaml | The configuration that maps file paths to encryption keys. |
| Creation rule | One path regex and the key that encrypts matching files. |
| Data key | The per-file key that encrypts values; itself wrapped by the Cloud KMS key. |
PLACEHOLDER | The value the shipped sample files carry until real values are encrypted in. |
| Prune | The manual sync option that deletes secrets whose key left the YAML. |
Where to read more
- GCP Secrets Blueprint overview and GCP Web App Blueprint overview.
- Cloud KMS for the stage keys and their rotation.
- GitOps for keeping desired state, secrets included, in Git.