diff --git a/docs/secrets.md b/docs/secrets.md index e9051364..95a53b07 100644 --- a/docs/secrets.md +++ b/docs/secrets.md @@ -1,5 +1,108 @@ --- -title: Manually load secrets into Docker swarm +title: Managing secret data --- -TODO. +# Managing secret data + +Co-op Cloud uses [Docker Secrets] to handle sensitive data, like database passwords and API keys, securely: + +``` +$ DOCKER_CONTEXT=swarm.example.com docker secret ls +example_mediawiki_db_password_v1 +example_wordpress_db_password_v1 +``` + +`abra` includes several commands to make it easier to manage secrets: + - `abra app secret generate` -- to auto-generate a single secret, or all secrets defined by the application, and store them in the Docker Swarm store, + - `abra app secret insert` -- to insert a single secret value from the Docker Swarm store, + - `abra app secret delete` -- to remove a single secret, or all secrets defined in the application, from the Docker Swarm store. + + + +## Secret versions + +You will notice `v1` in the example secret names above: like Docker Configs, Docker Secrets are [immutable], which means that their values can't be changed after they're set. To accommodate this, Co-op Cloud uses the established convention of "secret versions". Every time you change (rotate) a secret, you will insert it as a new version. + +Because secret versions are managed per-instance by the people deploying their applications, secret versions are stored in the `.env` file for each application: + +``` +$ find -L ~/.abra/servers/ -name '*.env' -print0 | xargs -0 grep -h SECRET +OIDC_CLIENT_SECRET_VERSION=v1 +RPC_SECRET_VERSION=v1 +CLIENT_SECRET_VERSION=v1 +... +``` + +If you try and add a secret version which already exists, Docker will helpfully complain: + +``` +$ abra app example_wordpress secret insert db_password v1 foobar +Error response from daemon: rpc error: code = AlreadyExists desc = secret example_wordpress_db_password_v1 already exists +``` + +By default, new app instances will look for `v1` secrets. + +## Generating secrets automatically + +You can generate secrets in one of two ways: + +1. While running `abra app new `, by passing `--secrets` +2. At any point once an app instance is defined, by running `abra app secret generate ...` (see `abra help secret generate` for full options) + +!!! note "How are secrets generated?" + + Depending on how the application is configured, you will require the `pwqgen` (from `passwdqc`) and `pwgen` binaries by default, although you can specify your own password-generation app when running `abra secret generate` by providing the `` argument. + +## Inserting secrets manually + +For third-party API tokens, like OAuth client secrets, or keys for services like Mailgun, you will be storing values you already have as the appropriately-named Docker secrets. `abra` provides a convenient interface to the underlying `docker secret create` command: + +``` +abra app example_wordpress secret insert db_password v2 "your-secret-here" +``` + +## Rotating a secret + +So, given how [secret versions](#versions) work, here's how you change a secret: + +1. Find out the current version number of the secret, e.g. by running `abra app example_wordpress config`, and choose a new one. Let's assume it's currently `v1`, so by convention the new secret will be `v2`. +2. Generate or insert the new secret: + ``` + abra app example_wordpress secret generate db_password v2 + ``` + or + ``` + abra app example_wordpress secret insert db_password v2 "foobar" + ``` +3. Edit the app configuration to change which secret version the app will use: + ``` + abra app example_wordpress config + ``` +4. Re-reploy the application with the new secret version: + ``` + abra app example_wordpress deploy + ``` + +## Storing secrets in `pass` + +The Co-op Cloud authors use the [UNIX `pass` tool][pass] to share sensitive data, including Co-op Cloud secrets, and `abra secret...` commands include a `--pass` option to automatically manage generated / inserted secrets: + +``` +# Store generated secrets in `pass`: +abra app new wordpress --secrets --pass +abra app example_wordpress secret generate --all --pass +# Store inserted secret in `pass`: +abra app example_wordpress secret insert db_password v2 --pass +# Remove secrets from Docker, and `pass`: +abra app example_wordpress secret rm --all --pass +``` + +This functionality currently relies on our specific `pass` structure; patches to make that configurable are very welcome! + +## What makes secrets secure? + +TODO + +[Docker Secrets]: https://docs.docker.com/engine/swarm/secrets/ +[immutable]: https://en.wikipedia.org/wiki/Immutable_object +[pass]: https://www.passwordstore.org diff --git a/mkdocs.yml b/mkdocs.yml index 317e9e87..b7dee6ec 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -39,7 +39,7 @@ nav: - Tutorials: - Package your first application: package.md - Use git to manage your configuration: git.md - - Manually load secrets into Docker swarm: secrets.md + - Manage secret data: secrets.md - Back-up and restore an application: backup-restore.md - Consider Docker security hardening practices: hardening.md - Scale an application up to handle more traffic: scale.md