Using Vault Approle to access secrets for Drone
This quick doc tries to help further understanding on connecting Vault and Drone for secrets. This doesn’t implement best practices for security, as it depends on your organization, and the Drone docs already describe limiting scope by repository and git event. I had some trouble getting started with the Vault extension, and I hope this helps anyone else in the future that also is implementing Drone and Vault.
My Setup:
- Vault 1.1
- Drone 1.1.0
- GitHub Enterprise
For my scenario, I already have a secret share specifically for drone builds. My Vault is using the KV version 2 which uses secret/data/shared/drone
instead of secret/shared/drone
. The vault cli client and API differ in how it accesses the secret mount.
$ vault kv get secret/data/shared/drone/secret_username
No value found at secret/data/data/shared/drone/secret_username
Versus
$ vault kv get secret/shared/drone/secret_username
====== Metadata ======
Key Value
--- -----
created_time 2019-04-17T19:02:16.871296361Z
deletion_time n/a
destroyed false
version 1
==== Data ====
Key Value
--- -----
value r00t_user
Create Vault HCL policy
# drone-shared.hcl
# Login with AppRole
path "auth/approle/login" {
capabilities = ["create", "read"]
}
# Read shared data kv2
path "secret/data/shared/*" {
capabilities = ["read", "list"]
}
# Read shared data
path "secret/shared/*" {
capabilities = ["read", "list"]
}
$ vault policy write drone-shared ./drone-shared.hcl
$ vault write auth/approle/role/drone-shared token_ttl=48h period=8h policies=drone-shared
$ vault write auth/approle/role/drone-shared --policy=drone-shared
Key Value
--- -----
bind_secret_id true
bound_cidr_list <nil>
local_secret_ids false
period 8h
policies [drone-shared]
secret_id_bound_cidrs <nil>
secret_id_num_uses 0
secret_id_ttl 0s
token_bound_cidrs <nil>
token_max_ttl 0s
token_num_uses 0
token_ttl 48h
Read and export ROLE_ID, SECRET_ID, and login
$ vault read auth/approle/role/drone-shared/role-id
Key Value
--- -----
role_id 0x0ba0c2-b2ea-5e0c-1eb0-1bd25b50dd0b
$ vault write -f auth/approle/role/drone-shared/secret-id
Key Value
--- -----
secret_id beef1-08b5-4e49-a922-89c7ffd47075
...
$ vault write -f auth/approle/login role_id=$ROLE_ID secret_id=$SECRET_ID
Key Value
--- -----
token be071b75-0000-ffff-eeee-fffeeeee0000
token_accessor e23ebb2b-37dc-3fac-8137-9a08fdaaa7c4
token_duration 8h
token_renewable true
token_policies ["default" "drone-shared"]
identity_policies []
policies ["default" "drone-shared"]
token_meta_role_name drone-shared
Generate RPC secrets for communication between server, agent, and for secrets plugin.
# for drone rpc
$ openssl rand -hex 16
b1631ec6ccf4670e681a16476be8f014
# for vault
$ openssl rand -hex 16
734e405271785460ccdf97f0ebad7073
Basic setup using docker-compose
version: '2'
services:
drone-server:
image: drone/drone:1.1.0
ports:
- 1.2.3.4.5:80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /srv/drone_v1/data:/data
restart: always
environment:
- DRONE_OPEN=true
- DRONE_USER_CREATE=username:ecray,admin:true
- DRONE_ORGS=example
- DRONE_AGENTS_ENABLED=true
- DRONE_SERVER_PROTO=https
- DRONE_SERVER_HOST=drone.example.com
- DRONE_GITHUB_PRIVATE_MODE=true
- DRONE_GITHUB_SERVER=https://github.example.com
- DRONE_GITHUB_CLIENT_ID=000bbb3333
- DRONE_GITHUB_CLIENT_SECRET=aaadddeee
- DRONE_LOGS_DEBUG=true
- DRONE_RPC_SECRET=b1631ec6ccf4670e681a16476be8f014
- DRONE_SECRET_ENDPOINT=http://drone-vault:3000
drone-vault:
image: drone/vault:latest
restart: always
ports:
- 3000:3000
environment:
- SECRET_KEY=734e405271785460ccdf97f0ebad7073
- VAULT_ADDR=https://my.vault-endpoint.com:8200
- VAULT_TOKEN_RENEWAL=8h
- VAULT_TOKEN_TTL=48h
- VAULT_TOKEN=be071b75-0000-ffff-eeee-fffeeeee0000
- DRONE_RPC_SERVER=http://drone-server:80
- DRONE_RPC_SECRET=b1631ec6ccf4670e681a16476be8f014
- DEBUG=true
drone-agent:
image: drone/agent:1.1.0
command: agent
restart: always
depends_on: [ drone-server, drone-vault ]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_SERVER=http://drone-server:80
- DRONE_RPC_SECRET=b1631ec6ccf4670e681a16476be8f014
- DRONE_SECRET_SECRET=734e405271785460ccdf97f0ebad7073
- DRONE_SECRET_ENDPOINT=http://drone-vault:3000
- DRONE_LOGS_TRACE=true
Check logs
$ docker-compose logs | grep drone-vault
Attaching to dronev1_drone-agent_1, dronev1_drone-server_1, dronev1_drone-vault_1
drone-vault_1 | time="2019-04-29T19:59:47Z" level=info msg="server listening on address :3000"
drone-vault_1 | time="2019-04-29T19:59:47Z" level=info msg="vault: token renewal enabled: 8h0m0s interval"
Test plugin connection works
$ docker run -it -e DRONE_SECRET_SECRET=ba234f000000000 \
-e DRONE_SECRET_ENDPOINT=http://drone-vault:3000 \
--network dronev1_default \
drone/cli:latest -- plugins secret get secret/data/shared/drone/secret_username value --repo ecray/i-hate-pants
r00t_user
Troubleshooting
If you are getting secret not found
, you should verify that you have Vault auditing enabled and check the logs to see why its failing to find the secret in Vault. I was also getting post: no protocol schema supported for ""
. Which let me to believe that the drone-vault plugin needed to have the VAULT_ADDR declare http or https in it.
HTH