Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Access Control

You can control which recipients are allowed or denied from decrypting specific secrets using the allow and deny fields in the [secret] section of the corresponding *.cott.toml metadata file.

Scenarios for managing access control:

  1. I want to allow only prod-server to be able to decrypt prod-secret
  2. I want to allow everyone except prod-server to be able to decrypt dev-secret
  3. I want to ensure that access control rules are enforced for all secrets before I merge a pull request

I want to allow only prod-server to be able to decrypt prod-secret

In this scenario, we restrict access to a production secret so that only the production server can decrypt it.

First, let’s add a new recipient key for the production server in the admin workspace:

cd /tmp/myproject
ssh-keygen -t ed25519 -f .cottage/prod-server.key -N ""
cp .cottage/prod-server.key.pub .cottage/recipients/prod-server

Now, create and encrypt the production secret:

echo "prod-db-password: supersecret" > prod-secret.yml
ctg encrypt prod-secret.yml
encrypt prod-secret.yml
   into prod-secret.yml.cott.age
   edit .gitignore
   edit prod-secret.yml.cott.toml

Edit the generated prod-secret.yml.cott.toml file to add the allow rule:

sed -i '/\[secret\]/a allow = ["prod-server"]' prod-secret.yml.cott.toml
cat prod-secret.yml.cott.toml
[checksum]
encrypted = "blake3:...XXX..."
recipients = "blake3:...XXX..."

[preview]
format = "yaml"
preview = """
prod-db-password: "...XXX..."
"""

[secret]
allow = ["prod-server"]
timestamp = "...XXX..."

Re-encrypt the secret to apply the new access rules:

ctg encrypt prod-secret.yml
encrypt prod-secret.yml
   into prod-secret.yml.cott.age
   edit prod-secret.yml.cott.toml

Now, only someone with the prod-server key can decrypt this secret. Even the admin who created it will be denied access unless they are explicitly added to the allow list.

Verify that access is denied for the default identity (admin):

rm prod-secret.yml
ctg decrypt prod-secret.yml.cott.age
Error: No matching keys found

Verify that access is granted for the prod-server key:

ctg decrypt prod-secret.yml.cott.age -i .cottage/prod-server.key
cat prod-secret.yml
decrypt prod-secret.yml.cott.age
   into prod-secret.yml
prod-db-password: supersecret

I want to allow everyone except prod-server to be able to decrypt dev-secret

In this scenario, we allow all team members and admins to access a development secret, but prevent the production server from being able to decrypt it.

Create and encrypt the development secret:

echo "dev-db-password: devsecret" > dev-secret.yml
ctg encrypt dev-secret.yml
encrypt dev-secret.yml
   into dev-secret.yml.cott.age
   edit dev-secret.yml.cott.toml

Edit the dev-secret.yml.cott.toml file to add the deny rule:

sed -i '/\[secret\]/a deny = ["prod-server"]' dev-secret.yml.cott.toml
cat dev-secret.yml.cott.toml
[checksum]
encrypted = "blake3:...XXX..."
recipients = "blake3:...XXX..."

[preview]
format = "yaml"
preview = """
dev-db-password: "...XXX..."
"""

[secret]
deny = ["prod-server"]
timestamp = "...XXX..."

Re-encrypt to apply the rules:

ctg encrypt dev-secret.yml
encrypt dev-secret.yml
   into dev-secret.yml.cott.age
   edit dev-secret.yml.cott.toml

Verify that the admin can still decrypt the secret (since they are not prod-server and are in the recipients list):

rm dev-secret.yml

ctg decrypt dev-secret.yml.cott.age

cat dev-secret.yml
decrypt dev-secret.yml.cott.age
   into dev-secret.yml
dev-db-password: devsecret

Verify that the prod-server is denied access:

rm dev-secret.yml
COTTAGE_IDENTITY=.cottage/prod-server.key ctg decrypt dev-secret.yml.cott.age
Error: No matching keys found

Tip

You can use glob patterns in allow and deny rules. For example, allow = ["team-*"] would allow any recipient whose name starts with team-.

I want to ensure that access control rules are enforced for all secrets before I merge a pull request

To ensure that access control rules are properly set up for all secrets before merging a pull request, you can run ctg verify in a CI workflow or a git hook.

Example using GitHub Actions:

# .github/workflows/cottage-verify.yml
name: Cottage Verify
on: [push, pull_request]
permissions:
  contents: read
jobs:
  verify-secrets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Verify secrets
        run: docker run --rm -v "${{ github.workspace }}:/app" ghcr.io/sayanarijit/cottage verify

This way, if someone pushes a secret with incorrect access control rules, or without updating the checksum in metadata, the verification will fail and prevent the pull request from being merged until the issues are resolved.