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 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:

GCP/acme-gcp-blueprint-secrets/.sops.yaml (lines 29-37)
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.yml on a pull request validates each stage (encrypted, decryptable, flat, no PLACEHOLDER value) and does a dry run that reports per secret Would create, Would update, Unchanged or Kept, 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-secretmanager.sh decrypts each file and writes every key as the secret <app>--<KEY> in Secret Manager of acme-plat-<stage>, with user-managed replication in the home region and the labels app, key and source=sops. An unchanged value creates no new version. A key removed from the YAML stays in Secret Manager, listed as Kept, until someone runs the workflow manually with prune.

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​

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 Cloud KMS key.
PLACEHOLDERThe value the shipped sample files carry until real values are encrypted in.
PruneThe manual sync option that deletes secrets whose key left the YAML.

Where to read more​