sops
The atago project wrote these specs on its own initiative and runs them in its own CI, to exercise atago against a real program. They are not sops’s official test suite, and the sops project is not affiliated with atago.
Summary #
1 suite · 7 scenarios
Contents #
- sops + age (secrets encryption) — 7 scenarios
- version prints a semantic version offline
- encryption hides values, keeps keys, and records metadata
- encrypt then decrypt recovers the original values
- extract returns a single decrypted value exactly
- decrypting with the wrong key fails
- a tampered ciphertext fails the MAC
- an encrypted-regex scopes which keys are encrypted
sops + age (secrets encryption) #
sops encrypts the values in a structured file while leaving its keys readable, so a secrets file stays reviewable in a pull request while its contents stay secret.
That split is the contract pinned here: after encryption the structure is still legible and every value is hidden; after decryption the values come back; and a single field can be extracted without decrypting the rest.
The negative guarantees carry equal weight. The wrong key must not decrypt. And flipping one byte of the ciphertext must fail the message authentication check rather than yielding subtly wrong plaintext — the integrity property that separates an encrypted file from an obfuscated one. A regex scoping which keys get encrypted is checked too, since a misconfigured scope is how secrets end up committed in the clear.
Source: test/e2e/thirdparty/sops/sops.atago.yaml
Scenario: version prints a semantic version offline #
only when sops --version --disable-version-check succeeds
When #
sops --version --disable-version-check
Then #
- exit code is
0 - stdout matches
/sops [0-9]+\.[0-9]+\.[0-9]+/
Scenario: encryption hides values, keeps keys, and records metadata #
only when command -v sops && command -v age-keygen succeeds
Given #
- Fixture file
secrets.yamlis created.
Inputs #
Fixture secrets.yaml:
database:
password: hunter2
host: db.internal
region: us-west-1
When #
age-keygen -o key.txt
age-keygen -y key.txt
# capture ${recipient} from stdout
sops encrypt --age ${recipient} secrets.yaml
Then #
- after
age-keygen -o key.txt:- exit code is
0
- exit code is
- after
sops encrypt --age ${recipient} secrets.yaml:- exit code is
0 - stdout contains
password:,host:,ENC[AES256_GCM,sops:,mac: - stdout does not contain
hunter2,db.internal
- exit code is
Scenario: encrypt then decrypt recovers the original values #
only when command -v sops && command -v age-keygen succeeds
Given #
- Fixture file
secrets.yamlis created. - Environment variables are set: SOPS_AGE_KEY_FILE.
Inputs #
Fixture secrets.yaml:
database:
password: hunter2
host: db.internal
region: us-west-1
When #
age-keygen -o key.txt
age-keygen -y key.txt
# capture ${recipient} from stdout
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml
sops decrypt secrets.enc.yaml
Then #
- after
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml:- exit code is
0
- exit code is
- after
sops decrypt secrets.enc.yaml:- exit code is
0 - stdout contains
password: hunter2,host: db.internal,region: us-west-1
- exit code is
Scenario: extract returns a single decrypted value exactly #
only when command -v sops && command -v age-keygen succeeds
Given #
- Fixture file
secrets.yamlis created. - Environment variables are set: SOPS_AGE_KEY_FILE.
Inputs #
Fixture secrets.yaml:
database:
password: hunter2
host: db.internal
region: us-west-1
When #
age-keygen -o key.txt
age-keygen -y key.txt
# capture ${recipient} from stdout
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml
sops decrypt --extract '["region"]' secrets.enc.yaml
Then #
- after
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml:- exit code is
0
- exit code is
- after
sops decrypt --extract '["region"]' secrets.enc.yaml:- exit code is
0 - stdout equals an exact value
- exit code is
Scenario: decrypting with the wrong key fails #
only when command -v sops && command -v age-keygen succeeds
Given #
- Fixture file
secrets.yamlis created. - Environment variables are set: SOPS_AGE_KEY_FILE.
Inputs #
Fixture secrets.yaml:
token: changeme
When #
age-keygen -o key.txt
age-keygen -y key.txt
# capture ${recipient} from stdout
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml
age-keygen -o other.txt
sops decrypt secrets.enc.yaml
Then #
- after
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml:- exit code is
0
- exit code is
- after
age-keygen -o other.txt:- exit code is
0
- exit code is
- after
sops decrypt secrets.enc.yaml:- exit code is
128 - stderr contains
Failed to get the data key
- exit code is
Scenario: a tampered ciphertext fails the MAC #
only when command -v sops && command -v age-keygen succeeds
Given #
- Fixture file
secrets.yamlis created. - Environment variables are set: SOPS_AGE_KEY_FILE.
Inputs #
Fixture secrets.yaml:
token: changeme
When #
age-keygen -o key.txt
age-keygen -y key.txt
# capture ${recipient} from stdout
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml
sed '0,/data:/ s/data:\([A-Za-z0-9]\)/data:Z/' secrets.enc.yaml > tampered.yaml
sops decrypt tampered.yaml
Then #
- after
sops encrypt --age ${recipient} --output secrets.enc.yaml secrets.yaml:- exit code is
0
- exit code is
- after
sed '0,/data:/ s/data:\([A-Za-z0-9]\)/data:Z/' secrets.enc.yaml > tampered.yaml:- exit code is
0
- exit code is
- after
sops decrypt tampered.yaml:- exit code is
25 - stderr contains
message authentication failed
- exit code is
Scenario: an encrypted-regex scopes which keys are encrypted #
only when command -v sops && command -v age-keygen succeeds
Given #
- Fixture file
secrets.yamlis created.
Inputs #
Fixture secrets.yaml:
database:
password: hunter2
host: db.internal
region: us-west-1
When #
age-keygen -o key.txt
age-keygen -y key.txt
# capture ${recipient} from stdout
sops encrypt --age ${recipient} --encrypted-regex '^password$' secrets.yaml
Then #
- after
sops encrypt --age ${recipient} --encrypted-regex '^password$' secrets.yaml:- exit code is
0 - stdout contains
host: db.internal,region: us-west-1,password: ENC[AES256_GCM - stdout does not contain
password: hunter2
- exit code is