From 59a36be4bb3d7ccbe78c0df6a7e85a392fb896c4 Mon Sep 17 00:00:00 2001 From: Stewart Adam Date: Sat, 2 Jun 2018 17:19:15 -0700 Subject: [PATCH] Update documentation for new -k syntax, docker container. Spellcheck. --- README.md | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1174c1b..b898043 100755 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ In short, it's the `network-online.target` equivalent for ZFS encrypted filesyst 1. ZFS filesystem encryption keys are placed into a locally encrypted key repository, whose own encryption key is placed in Azure Key Vault. 2. Upon boot, a system service reaches out to a small Flask web application called the ZFS key gateway with a request for the repository encryption keys. -3. The ZFS key gateway web service aquires authorization from a human to release the key repository's encryption key stored in Key Vault via Twilio SMS. If the owner authorizes the request by replying to the SMS, keys are retrieved from Key Vault and sent back. +3. The ZFS key gateway web service acquires authorization from a human to release the key repository's encryption key stored in Key Vault via Twilio SMS. If the owner authorizes the request by replying to the SMS, keys are retrieved from Key Vault and sent back. The system can now decrypt the local repository and mount the encrypted ZFS filesystems, without the filesystem encryption keys ever leaving the device. @@ -16,7 +16,8 @@ The system can now decrypt the local repository and mount the encrypted ZFS file - Notifies owner via SMS for approval of any key requests - Leverages Azure Key Vault for secure storage of the repository encryption key - CLI tool to facilitate management of the secure local repository containing filesystem encryption keys -- Passes keys to ZFS via stdin +- Passes keys to ZFS securely via pexpect (stdin) +- Gateway limits key requests to one per second to avoid brute-forcing of request PIN ## Setup ### Azure AD application registration @@ -42,43 +43,61 @@ We will setup an Azure AD application to credential the gateway service (Flask s cp zkv.py /usr/local/bin/zkv chmod +x /usr/local/bin/zkv ``` -3. Modify `/etc/sysconfig/zfs-keyvault` to point the correct gatway URL setup in step 3 of the server above *(if you don't know this yet, that's fine -- come back to this step after finishing the server installation)* +3. Ensure the dependencies in `client/requirements.txt` are available in system python. Ideally, you would do so via your OS package manager. As a last resort, run `pip -r client/requirements.txt` as root. +4. Modify `/etc/sysconfig/zfs-keyvault` to point the correct gateway URL setup in step 3 of the server above *(if you don't know this yet, skip this and return to this step after finishing the server installation)*. ### Key repository -1. Create a local filesystem key repository: +1. Create a filesystem key repository on your local system: ``` zkv fs init ``` Note the encryption key for subsequent steps as it cannot be retrieved later. -2. Add one or more filesystems +2. Add one or more filesystems: ``` - zkv fs add 'key_from_step_1' pool1/encfsname1 'zfs_enc_key' - zkv fs add 'key_from_step_1' pool1/encfsname2 'zfs_enc_key' - zkv fs add 'key_from_step_1' pool2/other_encfs 'zfs_enc_key' + zkv fs add -k 'key_from_step_1' pool1/encfsname1 'zfs_enc_key' + zkv fs add -k 'key_from_step_1' pool1/encfsname2 'zfs_enc_key' + zkv fs add -k 'key_from_step_1' pool2/other_encfs 'zfs_enc_key' ... ``` -3. Upload the key from step 1 as a secret to Key Vault, taking note of the name you used for use later +3. Upload the key from step 1 as a secret to Key Vault, taking note of the name you used for use later. ### Installation of the server (ZFS Key Gateway) -1. Copy `zkvgateway/zfs-keyvault-gateway.cfg.sample` as `zkvgateway/zfs-keyvault-gateway.cfg` and fill in the values from the Azure AD and key repository setup sections above -2. Create a docker image: +1. Pull the docker image: ``` - docker build . -t zkvgateway - docker run -it --rm -p 8000:80 --name zkvgateway zkvgateway + docker pull stewartadam/zkvgateway ``` -3. Run the image in your favorite environment (e.g. [App Service for Linux with Containers](https://docs.microsoft.com/en-us/azure/app-service/containers/tutorial-custom-docker-image)), taking note of the public URL +2. Run the image in your favorite environment (e.g. [App Service for Linux with Containers](https://docs.microsoft.com/en-us/azure/app-service/containers/tutorial-custom-docker-image)) + * If you skipped configuration of the public URL during the client, do so now. + * Your container needs information about your Azure AD application and Twilio account passed to it. The easiest way is to override config values at runtime with environment variables: + + ``` + ZKV_SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/db.sqlite' + ZKV_AAD_CLIENT_ID = 'guid-here' + ZKV_AAD_CLIENT_SECRET = 'secret-here' + ZKV_AAD_TENANT_ID = 'guid-here' + ZKV_KEY_VAULT_URI = 'https://YOUR_KV_NAME.vault.azure.net' + ZKV_KEY_VAULT_SECRET = 'KV_SECRET_NAME' + ZKV_TWILIO_ACCOUNT_ID = 'id-here' + ZKV_TWILIO_TOKEN = 'token-here' + ZKV_SMS_TO = '+15551234567' + ZKV_SMS_FROM = '+15551234567' + ``` + + Any of the other Flask parameters (e.g. look at `server/zkvgateway/config.py`) can also be overridden by passing the config keys prefixed by `ZKV_`. + + Alternatively, you can map a volume with a config file in it, and then pass a `CONFIG_FILE` environment variable pointing to the location of the configuration file inside the container. The configuration keys written in the config file should match those in `config.py`, i.e. as above *less* the `ZKV_` prefix. ### Twilio Twilio is used to approve key requests over SMS. 1. Create an account at [twilio.com](https://www.twilio.com/) 2. [Add a phone number](https://www.twilio.com/console/phone-numbers/search) to your account -3. [Configure a messaging webhook](https://support.twilio.com/hc/en-us/articles/223135027-Configuring-phone-numbers-to-receive-calls-or-SMS-messages) for your number with endpoint `https://YOUR_GATEWAY_HOSTNAME.TLD/incoming-message`. +3. [Configure a messaging webhook](https://support.twilio.com/hc/en-us/articles/223135027-Configuring-phone-numbers-to-receive-calls-or-SMS-messages) for your number with endpoint `https://YOUR_GATEWAY_HOSTNAME.TLD/incoming-message` ## Todo +I'm not committed to any of these at this time, but ideas for improvement (or PRs): * Implement one-time password mechanism instead of random PIN * Consider additional security protections (e.g. dead-man switch, remote wipe, key rotation) * Generalize pattern for other encryption providers (e.g. LUKS or dm-crypt) ## Known issues -* Docker image stores its credentials in the image itself. Do not push your generated image to a public registry. -* SMS is insecure \ No newline at end of file +* SMS is insecure