diff --git a/deps/hashicorp/docker-compose.yml b/deps/hashicorp/docker-compose.yml index bd2ce4980..2868a90e9 100644 --- a/deps/hashicorp/docker-compose.yml +++ b/deps/hashicorp/docker-compose.yml @@ -8,106 +8,112 @@ x-container-common: &container-common services: hashicorp: <<: *container-common - image: consensys/quorum-hashicorp-vault-plugin:v1.1.3 + image: library/vault:1.8.2 tty: true cap_add: - IPC_LOCK volumes: - hashicorp-plugin:/vault/plugins - ./config/config.hcl:/vault/config.hcl:ro - - ./scripts/agent-init.sh:/usr/local/bin/kvv2-init.sh - environment: - VAULT_ADDR: http://hashicorp:8200 - VAULT_IS_READY: /vault/token/.ready - ROOT_TOKEN_PATH: /vault/token/.root - entrypoint: - - sh - - -c - - | - ( sleep 2 && vault-init.sh && kvv2-init.sh && cat > $${VAULT_IS_READY} ) & - vault server -config=/vault/config.hcl + entrypoint: vault server -config=/vault/config.hcl ports: - 8200:8200 - hashicorp-agent: - <<: *container-common - image: consensys/quorum-hashicorp-vault-plugin:v1.1.3 - tty: true - depends_on: - - hashicorp - cap_add: - - IPC_LOCK - environment: - ROOT_TOKEN_PATH: /vault/token/.root - VAULT_ADDR: http://vault:8200 - SECRET_FILE_PATH: /vault/token/secret - ROLE_FILE_PATH: /vault/token/role - VAULT_IS_READY: /vault/token/.ready - volumes: - - hashicorp-token:/vault/token - - ./config/agent-config.hcl:/vault/config.hcl:ro - - ./scripts/agent-init.sh:/usr/local/bin/agent-init.sh - entrypoint: - - sh - - -c - - | - - until [ -f ${VAULT_IS_READY} ]; do - echo "[AGENT] waiting for vault to be ready..." - sleep 1 - done - - agent-init.sh - vault agent -config=/vault/config.hcl - hashicorp-tls: <<: *container-common - image: consensys/quorum-hashicorp-vault-plugin:v1.1.3 + image: library/vault:1.8.2 container_name: hashicorp tty: true cap_add: - IPC_LOCK - environment: - VAULT_ADDR: https://hashicorp:8200 - VAULT_IS_READY: /vault/token/.ready - ROOT_TOKEN_PATH: /vault/token/.root - VAULT_CACERT: ${VAULT_CACERT-/vault/tls/ca.crt} - VAULT_CLIENT_CERT: ${VAULT_CLIENT_CERT-/vault/tls/client.crt} - VAULT_CLIENT_KEY: ${VAULT_CLIENT_KEY-/vault/tls/client.key} volumes: - hashicorp-plugin:/vault/plugins - ./tls:/vault/tls:ro - ./config/config-tls.hcl:/vault/config.hcl:ro - ./tls/ca.crt:/etc/ssl/certs/vault.crt - entrypoint: - - sh - - -c - - | - ( sleep 2 && vault-init.sh && kvv2-init.sh && cat > $${VAULT_IS_READY} ) & - vault server -config=/vault/config.hcl + entrypoint: vault server -config=/vault/config.hcl ports: - 8200:8200 + hashicorp-init-tls: + <<: *container-common + build: . + container_name: hashicorp-init + environment: + VAULT_ADDR: ${VAULT_ADDR-https://hashicorp:8200} + VAULT_CACERT: ${VAULT_CACERT-/vault/tls/ca.crt} + VAULT_CLIENT_CERT: ${VAULT_CLIENT_CERT-/vault/tls/client.crt} + VAULT_CLIENT_KEY: ${VAULT_CLIENT_KEY-/vault/tls/client.key} + PLUGIN_PATH: ${PLUGIN_PATH-/vault/plugins} + TOKEN_PATH: ${TOKEN_PATH-/vault/token} + PLUGIN_VERSION: ${PLUGIN_VERSION-v1.0.0} + restart: "no" + depends_on: + - hashicorp-tls + volumes: + - hashicorp-token:/vault/token + - hashicorp-plugin:/vault/plugins + - ./scripts/init-tls.sh:/init.sh + - ./scripts/plugin.sh:/plugin.sh + - ./tls/ca.crt:/vault/tls/ca.crt:ro + - ./tls/client.crt:/vault/tls/client.crt:ro + - ./tls/client.key:/vault/tls/client.key:ro + command: > + sh -c "./plugin.sh && ./init.sh" + + hashicorp-init: + <<: *container-common + build: . + environment: + VAULT_ADDR: ${VAULT_ADDR-http://hashicorp:8200} + PLUGIN_PATH: ${PLUGIN_PATH-/vault/plugins} + TOKEN_PATH: ${TOKEN_PATH-/vault/token} + PLUGIN_VERSION: ${PLUGIN_VERSION-v1.0.0} + restart: "no" + depends_on: + - hashicorp + volumes: + - hashicorp-token:/vault/token + - hashicorp-plugin:/vault/plugins + - ./scripts/init.sh:/init.sh + - ./scripts/plugin.sh:/plugin.sh + command: > + sh -c "./plugin.sh && ./init.sh" + hashicorp-agent-tls: <<: *container-common - image: consensys/quorum-hashicorp-vault-plugin:v1.1.3 - tty: true container_name: hashicorp-agent + environment: + VAULT_ADDR: ${VAULT_ADDR-https://hashicorp:8202} + VAULT_CACERT: ${VAULT_CACERT-/vault/tls/ca.crt} + image: library/vault:1.8.2 + tty: true depends_on: - hashicorp-tls + - hashicorp-init-tls cap_add: - IPC_LOCK - environment: - VAULT_ADDR: ${VAULT_ADDR-https://hashicorp:8202} - VAULT_CACERT: ${VAULT_CACERT-/vault/tls/ca.crt} - VAULT_CLIENT_CERT: ${VAULT_CLIENT_CERT-/vault/tls/client.crt} - VAULT_CLIENT_KEY: ${VAULT_CLIENT_KEY-/vault/tls/client.key} volumes: - hashicorp-token:/vault/token - ./config/agent-config-tls.hcl:/vault/config.hcl:ro - ./tls:/vault/tls:ro entrypoint: vault agent -config=/vault/config.hcl + hashicorp-agent: + <<: *container-common + environment: + VAULT_ADDR: ${VAULT_ADDR-http://hashicorp:8200} + image: library/vault:1.8.2 + tty: true + depends_on: + - hashicorp + - hashicorp-init + cap_add: + - IPC_LOCK + volumes: + - hashicorp-token:/vault/token + - ./config/agent-config.hcl:/vault/config.hcl:ro + entrypoint: vault agent -config=/vault/config.hcl volumes: hashicorp-token: diff --git a/deps/hashicorp/scripts/agent-init.sh b/deps/hashicorp/scripts/agent-init.sh deleted file mode 100755 index f9c519a75..000000000 --- a/deps/hashicorp/scripts/agent-init.sh +++ /dev/null @@ -1,38 +0,0 @@ -VAULT_TOKEN=$(cat "${ROOT_TOKEN_PATH}") - -VAULT_SSL_PARAMS="" -if [ -n "$VAULT_CACERT" ]; then - VAULT_SSL_PARAMS="$VAULT_SSL_PARAMS --cacert $VAULT_CACERT" -fi - -if [ -n "$VAULT_CLIENT_CERT" ]; then - VAULT_SSL_PARAMS="$VAULT_SSL_PARAMS --cert $VAULT_CLIENT_CERT" -fi - -if [ -n "$VAULT_CLIENT_KEY" ]; then - VAULT_SSL_PARAMS="$VAULT_SSL_PARAMS --key $VAULT_CLIENT_KEY" -fi - -curl -s --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST ${VAULT_SSL_PARAMS} \ - --data '{"type": "approle"}' \ - ${VAULT_ADDR}/v1/sys/auth/approle - -curl -s --header "X-Vault-Token: $VAULT_TOKEN" --request PUT ${VAULT_SSL_PARAMS} \ - --data '{ "policy":"path \"'"${PLUGIN_MOUNT_PATH}/*"'\" { capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\"] }" }' \ - ${VAULT_ADDR}/v1/sys/policies/acl/allow_secrets - -curl -s --header "X-Vault-Token: $VAULT_TOKEN" --request POST ${VAULT_SSL_PARAMS} \ - --data '{"policies": ["allow_secrets"]}' \ - ${VAULT_ADDR}/v1/auth/approle/role/key-manager - -curl -s --header "X-Vault-Token: $VAULT_TOKEN" ${VAULT_SSL_PARAMS} \ - ${VAULT_ADDR}/v1/auth/approle/role/key-manager/role-id > role.json -ROLE_ID=$(cat role.json | jq .data.role_id | tr -d '"') -echo $ROLE_ID > ${ROLE_FILE_PATH} -rm role.json - -curl -s --header "X-Vault-Token: $VAULT_TOKEN" --request POST ${VAULT_SSL_PARAMS} \ - ${VAULT_ADDR}/v1/auth/approle/role/key-manager/secret-id > secret.json -SECRET_ID=$(cat secret.json | jq .data.secret_id | tr -d '"') -echo $SECRET_ID > ${SECRET_FILE_PATH} -rm secret.json diff --git a/deps/hashicorp/scripts/init-tls.sh b/deps/hashicorp/scripts/init-tls.sh new file mode 100755 index 000000000..66b59bfc2 --- /dev/null +++ b/deps/hashicorp/scripts/init-tls.sh @@ -0,0 +1,80 @@ +# Store root token in a file so it can be shared with other services through volume +mkdir -p $TOKEN_PATH + +echo "Initializing Vault: ${VAULT_ADDR}" + +# Init Vault +curl --cacert $VAULT_CACERT --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data '{"secret_shares": 1, "secret_threshold": 1}' ${VAULT_ADDR}/v1/sys/init > init.json + +# Retrieve root token and unseal key +VAULT_TOKEN=$(cat init.json | jq .root_token | tr -d '"') +UNSEAL_KEY=$(cat init.json | jq .keys | jq .[0]) +SHA256SUM=$(cat $PLUGIN_PATH/SHA256SUM) +rm init.json + +if [ "$UNSEAL_KEY" = "null" ]; then + echo "cannot retrieve unseal token" + exit 1 +fi + +echo $VAULT_TOKEN > $TOKEN_PATH/.root +echo "ROOT_TOKEN: $VAULT_TOKEN" +echo "SHA256SUM: ${SHA256SUM}" + +# Unseal Vault +curl --cacert $VAULT_CACERT --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data '{"key": '${UNSEAL_KEY}'}' ${VAULT_ADDR}/v1/sys/unseal + +# Enable kv-v2 secret engine +curl --cacert $VAULT_CACERT --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data '{"type": "kv-v2", "config": {"force_no_cache": true} }' \ + ${VAULT_ADDR}/v1/sys/mounts/secret + + +# Register Quorum plugin +curl --cacert $VAULT_CACERT --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data "{\"sha256\": \"${SHA256SUM}\", \"command\": \"quorum\" }" \ + ${VAULT_ADDR}/v1/sys/plugins/catalog/secret/quorum + +# Enable quorum secret engine +curl --cacert $VAULT_CACERT --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data '{"type": "plugin", "plugin_name": "quorum", "config": {"force_no_cache": true, "passthrough_request_headers": ["X-Vault-Namespace"]} }' \ + ${VAULT_ADDR}/v1/sys/mounts/quorum + +# Enable role policies +# Instructions taken from https://learn.hashicorp.com/tutorials/vault/getting-started-apis +curl --cacert $VAULT_CACERT --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data '{"type": "approle"}' \ + ${VAULT_ADDR}/v1/sys/auth/approle + +curl --cacert $VAULT_CACERT --header "X-Vault-Token: $VAULT_TOKEN" \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --request PUT \ + --data '{ "policy":"path \"quorum/*\" { capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\"] }" }' \ + ${VAULT_ADDR}/v1/sys/policies/acl/allow_secrets + +curl --cacert $VAULT_CACERT --header "X-Vault-Token: $VAULT_TOKEN" \ + --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + --data '{"policies": ["allow_secrets"]}' \ + ${VAULT_ADDR}/v1/auth/approle/role/key-manager + +curl --cacert $VAULT_CACERT --header "X-Vault-Token: $VAULT_TOKEN" \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + ${VAULT_ADDR}/v1/auth/approle/role/key-manager/role-id >role.json +ROLE_ID=$(cat role.json | jq .data.role_id | tr -d '"') +echo $ROLE_ID > $TOKEN_PATH/role + +curl --cacert $VAULT_CACERT --header "X-Vault-Token: $VAULT_TOKEN" \ + --request POST \ + --cert $VAULT_CLIENT_CERT --key $VAULT_CLIENT_KEY \ + ${VAULT_ADDR}/v1/auth/approle/role/key-manager/secret-id >secret.json +SECRET_ID=$(cat secret.json | jq .data.secret_id | tr -d '"') +echo $SECRET_ID > $TOKEN_PATH/secret diff --git a/deps/hashicorp/scripts/init.sh b/deps/hashicorp/scripts/init.sh new file mode 100755 index 000000000..d32721942 --- /dev/null +++ b/deps/hashicorp/scripts/init.sh @@ -0,0 +1,62 @@ +# Store root token in a file so it can be shared with other services through volume +mkdir -p $TOKEN_PATH + +echo "Initializing Vault: ${VAULT_ADDR}" + +# Init Vault +curl --request POST --data '{"secret_shares": 1, "secret_threshold": 1}' ${VAULT_ADDR}/v1/sys/init > init.json + +# Retrieve root token and unseal key +VAULT_TOKEN=$(cat init.json | jq .root_token | tr -d '"') +UNSEAL_KEY=$(cat init.json | jq .keys | jq .[0]) +SHA256SUM=$(cat $PLUGIN_PATH/SHA256SUM) +rm init.json + +if [ "$UNSEAL_KEY" = "null" ]; then + echo "cannot retrieve unseal token" + exit 1 +fi + +echo $VAULT_TOKEN > $TOKEN_PATH/.root +echo "ROOT_TOKEN: $VAULT_TOKEN" +echo "SHA256SUM: ${SHA256SUM}" + +# Unseal Vault +curl --request POST --data '{"key": '${UNSEAL_KEY}'}' ${VAULT_ADDR}/v1/sys/unseal + +# Enable kv-v2 secret engine +curl --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --data '{"type": "kv-v2", "config": {"force_no_cache": true} }' \ + ${VAULT_ADDR}/v1/sys/mounts/secret + +# Register Quorum plugin +curl --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --data "{\"sha256\": \"${SHA256SUM}\", \"command\": \"quorum\" }" \ + ${VAULT_ADDR}/v1/sys/plugins/catalog/secret/quorum + +# Enable quorum secret engine +curl --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --data '{"type": "plugin", "plugin_name": "quorum", "config": {"force_no_cache": true, "passthrough_request_headers": ["X-Vault-Namespace"]} }' \ + ${VAULT_ADDR}/v1/sys/mounts/quorum + +# Enable role policies +# Instructions taken from https://learn.hashicorp.com/tutorials/vault/getting-started-apis +curl --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST \ + --data '{"type": "approle"}' \ + ${VAULT_ADDR}/v1/sys/auth/approle + +curl --header "X-Vault-Token: $VAULT_TOKEN" --request PUT \ + --data '{ "policy":"path \"quorum/*\" { capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\"] }" }' \ + ${VAULT_ADDR}/v1/sys/policies/acl/allow_secrets + +curl --header "X-Vault-Token: $VAULT_TOKEN" --request POST \ + --data '{"policies": ["allow_secrets"]}' \ + ${VAULT_ADDR}/v1/auth/approle/role/key-manager + +curl --header "X-Vault-Token: $VAULT_TOKEN" ${VAULT_ADDR}/v1/auth/approle/role/key-manager/role-id >role.json +ROLE_ID=$(cat role.json | jq .data.role_id | tr -d '"') +echo $ROLE_ID > $TOKEN_PATH/role + +curl --header "X-Vault-Token: $VAULT_TOKEN" --request POST ${VAULT_ADDR}/v1/auth/approle/role/key-manager/secret-id >secret.json +SECRET_ID=$(cat secret.json | jq .data.secret_id | tr -d '"') +echo $SECRET_ID > $TOKEN_PATH/secret diff --git a/deps/hashicorp/scripts/kvv2-init.sh b/deps/hashicorp/scripts/kvv2-init.sh deleted file mode 100755 index 662f05925..000000000 --- a/deps/hashicorp/scripts/kvv2-init.sh +++ /dev/null @@ -1,18 +0,0 @@ -VAULT_SSL_PARAMS="" -if [ -n "$VAULT_CACERT" ]; then - VAULT_SSL_PARAMS="$VAULT_SSL_PARAMS --cacert $VAULT_CACERT" -fi - -if [ -n "$VAULT_CLIENT_CERT" ]; then - VAULT_SSL_PARAMS="$VAULT_SSL_PARAMS --cert $VAULT_CLIENT_CERT" -fi - -if [ -n "$VAULT_CLIENT_KEY" ]; then - VAULT_SSL_PARAMS="$VAULT_SSL_PARAMS --key $VAULT_CLIENT_KEY" -fi - -# Enable kv-v2 secret engine -curl --header "X-Vault-Token: ${VAULT_TOKEN}" --request POST ${VAULT_SSL_PARAMS}\ - --data '{"type": "kv-v2", "config": {"force_no_cache": true} }' \ - ${VAULT_ADDR}/v1/sys/mounts/secret - diff --git a/deps/hashicorp/scripts/plugin.sh b/deps/hashicorp/scripts/plugin.sh new file mode 100755 index 000000000..35dcc3937 --- /dev/null +++ b/deps/hashicorp/scripts/plugin.sh @@ -0,0 +1,23 @@ +# Download vault plugin assets + +VERSION="${PLUGIN_VERSION}" +FILE_PATH="${PLUGIN_PATH}" + +FILES="quorum-hashicorp-vault-plugin SHA256SUM" +GITHUB_URL="https://github.com/ConsenSys/quorum-hashicorp-vault-plugin" + +echo "Installing Quorum Hashicorp Vault plugin version '$VERSION'" +for FILE in ${FILES}; do + echo "Downloading $FILE..." + /usr/bin/wget --header='Accept:application/octet-stream' \ + $GITHUB_URL/releases/download/$VERSION/$FILE \ + -O "${FILE_PATH}/${FILE}" + + + echo "File at ${FILE_PATH}/${FILE}..." +done + +echo "Renaming plugin" +mv ${FILE_PATH}/quorum-hashicorp-vault-plugin ${FILE_PATH}/quorum +echo "Changing plugin permissions" +chmod 777 ${FILE_PATH}/quorum