├── Dockerfile ├── LICENSE ├── README.md └── assets ├── check ├── common.sh ├── in └── out /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | MAINTAINER William Huba 3 | 4 | ENV VAULT_VERSION 0.6.1 5 | 6 | RUN apk update && apk add --no-cache \ 7 | openssl \ 8 | jq \ 9 | curl \ 10 | bash 11 | 12 | # Download, unzip the given version of vault and set permissions 13 | RUN wget -qO /tmp/vault.zip https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip && \ 14 | unzip -d /bin /tmp/vault.zip && rm /tmp/vault.zip && chmod 755 /bin/vault 15 | 16 | ADD assets/ /opt/resource/ 17 | RUN chmod +x /opt/resource/* 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Docurated 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://images.microbadger.com/badges/image/docurated/concourse-vault-resource.svg)](https://microbadger.com/images/docurated/concourse-vault-resource "Get your own image badge on microbadger.com") 2 | 3 | # Vault Resource 4 | 5 | Reads secrets from [Vault](https://www.vaultproject.io/). Authentication is done (by default) using the [aws-ec2 method](https://www.vaultproject.io/docs/auth/aws-ec2.html), which must be configured before using this resource. 6 | It can also use the [AppRole method](https://www.vaultproject.io/docs/auth/approle.html) to authenticate. 7 | 8 | ## Source Configuration 9 | 10 | * `url`: *Optional.* The location of the Vault server. Defaults to `https://vault.service.consul:8200`. 11 | 12 | * `role`: *Optional.* The role to authenticate as. Defaults to `concourse`. 13 | 14 | * `nonce`: *Optional.* Client nonce whitelisted by Vault for this EC2 auth. Defaults to `vault-concourse-nonce`, which should probably be changed. 15 | 16 | * `paths`: *Optional.* If specified (as a list of glob patterns), only changes 17 | to the specified files will yield new versions from `check`. 18 | 19 | * `expose_token`: *Optional.* If specified, this option will expose the token to make it available to other resources 20 | 21 | * `auth_method`: *Optional.* By default will use the `aws-ec2` method. If `AppRole` is specified, it will read the `role_id` and `secret_id` parameter to authenticate on the approle endpoint. 22 | 23 | * `role_id`: *Optional.* Use a specific role id to authenticate. This parameter is used only with `auth_method: AppRole`. 24 | 25 | * `secret_id`: *Optional.* Use a specific secret id to authenticate. This parameter is used only with `auth_method: AppRole`. 26 | 27 | * `tls_skip_verify`: *Optional.* Skips Vault SSL verification by exporting 28 | `VAUKT_SKIP_VERIFY=1`. 29 | 30 | ### Example 31 | 32 | Resource configuration using aws-ec2 authentication: 33 | 34 | ``` yaml 35 | resources: 36 | - name: vault 37 | type: vault 38 | source: 39 | url: https://secure.legitcompany.com:8200 40 | role: build-server 41 | nonce: cantguessme 42 | ``` 43 | 44 | Resource configuration using AppRole authentication: 45 | 46 | ``` yaml 47 | resources: 48 | - name: vault 49 | type: vault 50 | source: 51 | url: https://secure.legitcompany.com:8200 52 | auth_method: AppRole 53 | role_id: e6889709-5ff8-c670-a083-79f1c5035709 54 | secret_id: e6889709-5ff8-c670-a083-79f1c5035709 55 | ``` 56 | 57 | Fetching secrets: 58 | 59 | ``` yaml 60 | - get: vault 61 | params: 62 | paths: 63 | - secret/build/git 64 | - secret/build/aws/s3 65 | ``` 66 | 67 | ## Behavior 68 | 69 | ### `check`: Check for new versions. 70 | 71 | Essentially a noop, the current date is always returned as `{"date": "$DATE"}` 72 | 73 | ### `in`: Read secrets from Vault 74 | 75 | Reads secrets from Vault and stores them on disk as JSON files. 76 | 77 | The path of the secret will match the path on disk - ie in the example above, `vault/build/git.json` and `vault/build/aws/s3.json` will be created. 78 | 79 | #### Parameters 80 | 81 | * `paths`: *Required.* List of paths to read from the Vault secret mount. 82 | -------------------------------------------------------------------------------- /assets/check: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Always indicate a new version is available by setting the version to the current date 4 | jq -n "[ 5 | {date: \"$(date +%s)\"} 6 | ]" 7 | -------------------------------------------------------------------------------- /assets/common.sh: -------------------------------------------------------------------------------- 1 | login_aws_ec2() { 2 | vault_role="$1" 3 | vault_nonce="$2" 4 | cert=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 | tr -d '\n') 5 | token=$(vault write -format=json auth/aws-ec2/login role=${vault_role} pkcs7=${cert} nonce=${vault_nonce} | jq -r '.auth.client_token') 6 | if [ -z "${token}" ]; then 7 | echo "ERROR: No token retrieved" 8 | return 1 9 | fi 10 | echo -n "${token}" > ~/.vault-token 11 | } 12 | 13 | login_approle() { 14 | vault_role_id="$1" 15 | vault_secret_id="$2" 16 | token=$(vault write -format=json auth/approle/login role_id=${vault_role_id} secret_id=${vault_secret_id} | jq -r '.auth.client_token') 17 | if [ -z "${token}" ]; then 18 | echo "ERROR: No token retrieved" 19 | return 1 20 | fi 21 | echo -n "${token}" > ~/.vault-token 22 | } 23 | 24 | get_secret() { 25 | vault read -format=json ${1} | jq -r '.data' 26 | } 27 | -------------------------------------------------------------------------------- /assets/in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | exec 3>&1 # make stdout available as fd 3 for the result 6 | exec 1>&2 # redirect all output to stderr for logging 7 | 8 | source $(dirname $0)/common.sh 9 | 10 | destination=$1 11 | payload=$(mktemp $TMPDIR/vault-resource-request.XXXXXX) 12 | cat > $payload <&0 13 | 14 | url=$(jq -r '.source.url // "https://vault.service.consul:8200"' < $payload) 15 | skip_verify=$(jq -r '.source.tls_skip_verify // ""' < $payload) 16 | expose_token=$(jq -r '.source.expose_token // ""' < $payload) 17 | paths=($(jq -r '.params.paths // [] | .[]' < $payload)) 18 | auth_method=$(jq -r '.source.auth_method // "aws_ec2"' < $payload) 19 | # Used for AWS EC2 authentication 20 | role=$(jq -r '.source.role // "concourse"' < $payload) 21 | nonce=$(jq -r '.source.nonce // "vault-concourse-nonce"' < $payload) 22 | # Used for AWS EC2 authentication 23 | role_id=$(jq -r '.source.role_id // ""' < $payload) 24 | secret_id=$(jq -r '.source.secret_id // ""' < $payload) 25 | 26 | echo "INFO: Reading secrets from: ${paths[*]}" 27 | 28 | export VAULT_ADDR=${url} 29 | if [ ! -z "${skip_verify}" ]; then 30 | echo "WARN: Disabling TLS verification for Vault" 31 | export VAULT_SKIP_VERIFY=1 32 | fi 33 | 34 | if [ "${auth_method}" = "AppRole" ]; then 35 | login_approle ${role_id} ${secret_id} 36 | else 37 | login_aws_ec2 ${role} ${nonce} 38 | fi 39 | 40 | for path in "${paths[@]}"; do 41 | mkdir -p ${destination}/$(dirname ${path}) 42 | get_secret ${path} > ${destination}/${path}.json 43 | done 44 | 45 | if [ ! -z "${expose_token}" ]; then 46 | cp ~/.vault-token ${destination}/token 47 | fi 48 | 49 | version="{\"date\": \"$(date +%s)\"}" 50 | jq -n "{ 51 | version: ${version} 52 | }" >&3 53 | -------------------------------------------------------------------------------- /assets/out: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "{}" 4 | --------------------------------------------------------------------------------