This will setup a single node Consul cluster. Development mode is not used in order to allow data persistence. We'll be interacting with the Consul server from within the container for simplicity.
Create Consul configuration and persistent data directories
$ mkdir p consul/config consul/data
Create Consul configuration file
$ cat > consul/config/server.json
{
"acl_datacenter": "dc1",
"acl_master_token": "root",
"acl_default_policy": "deny",
"acl_down_policy": "extend-cache",
"acl_agent_token": "root"
}
^C
Create network
$ docker network create hashicorp
Create Consul Server
$ docker run -d --name consul-server --network hashicorp -v $PWD/consul-config/:/consul/config/ consul
Start a Vault server in development mode
$ docker run -d --name vault-server --network hashicorp --cap-add=IPC_LOCK -e VAULT_ADDR='http://0.0.0.0:8200' vault `
Get the Unseal Key and Root token
$ export ROOT_TOKEN=$(docker logs vault-server 2>/dev/null | grep "Root Token" | awk -F' ' '{ print $3 }')
Authenticate to Vault
$ docker exec vault-server vault login $ROOT_TOKEN
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token 1eae75c6-c5f8-af1a-3928-914f67a1ebf5
token_accessor b3f1ebc4-2bc2-a907-f3f7-26328b425dbc
token_duration ∞
token_renewable false
token_policies [root]
Enable Consul secret engine
$ docker exec vault-server vault secrets enable consul
Success! Enabled the consul secrets engine at: consul/
Create a Consul management token for Vault to use to provision user tokens
$ docker exec consul-server curl -s -XPUT --data '{ "Name": "vault", "Type": "management" }' "http://127.0.0.1:8500/v1/acl/create?token=${ROOT_TOKEN}"
{
"ID": "861c8ea4-480a-300b-7d80-787293c2ec41"
}
Configure Consul secret engine in Vault
$ docker exec vault-server vault write consul/config/access address=consul-server:8500 token=861c8ea4-480a-300b-7d80-787293c2ec41
Success! Data written to: consul/config/access
Create a Vault privileged role that maps to a Consul ACL
$ docker exec vault-server vault write consul/roles/sysadmin policy=$(echo -n 'key "" { policy = "write" }' | base64 -)
Success! Data written to: consul/roles/sysadmin
Create a Vault limited access role that maps to a Consul ACL
$ docker exec vault-server vault write consul/roles/devs policy=$(echo -n 'key "" { policy = "read" }' | base64 -)
Success! Data written to: consul/roles/devs
Check that Vault can create tokens
$ docker exec vault-server vault read consul/creds/devs
Key Value
--- -----
lease_id consul/creds/devs/e7b3cb14-3aeb-5baa-904d-59d4d1ad3d8a
lease_duration 768h
lease_renewable true
token c5ca5ed8-0df3-b8f0-11e8-12d3e2882c7d
$ docker exec vault-server vault read consul/creds/sysadmin
Key Value
--- -----
lease_id consul/creds/sysadmin/8e11ffc0-21d3-5c29-4540-4107911a773a
lease_duration 768h
lease_renewable true
token afc37f61-c11d-ccc6-6454-73e73f0d150e
Check ACL tokens in Consul
$ docker exec consul-server curl -s "http://127.0.0.1:8500/v1/acl/list?token=${ROOT_TOKEN}"
[
{
"ID": "afc37f61-c11d-ccc6-6454-73e73f0d150e",
"Name": "Vault sysadmin root 1525783733252560521",
"Type": "client",
"Rules": "key \"\" { policy = \"write\" }",
"CreateIndex": 118,
"ModifyIndex": 118
},
{
"ID": "anonymous",
"Name": "Anonymous Token",
"Type": "client",
"Rules": "",
"CreateIndex": 4,
"ModifyIndex": 4
},
{
"ID": "c5ca5ed8-0df3-b8f0-11e8-12d3e2882c7d",
"Name": "Vault devs root 1525783695312786225",
"Type": "client",
"Rules": "key \"\" { policy = \"read\" }",
"CreateIndex": 116,
"ModifyIndex": 116
},
{
"ID": "861c8ea4-480a-300b-7d80-787293c2ec41",
"Name": "vault",
"Type": "management",
"Rules": "",
"CreateIndex": 86,
"ModifyIndex": 86
},
{
"ID": "root",
"Name": "Master Token",
"Type": "management",
"Rules": "",
"CreateIndex": 5,
"ModifyIndex": 5
}
]
Use devs token from Vault and try to create a key value entry in Consul
Using the HTTP API
$ docker exec consul-server curl -s -XPUT --data 'http://www.google.ca' http://127.0.0.1:8500/v1/kv/proxies/webproxy01?token=c5ca5ed8-0df3-b8f0-11e8-12d3e2882c7d
Permission denied
Using the Consul command
$ docker exec consul-server consul kv put -token=c5ca5ed8-0df3-b8f0-11e8-12d3e2882c7d proxies/webproxy01 http://www.google.ca
Error! Failed writing data: Unexpected response code: 403 (Permission denied)
Use sysadmin token from Vault and try to create a key value entry in Consul
Using the HTTP API
$ docker exec consul-server curl -s -XPUT --data 'http://www.google.ca' http://127.0.0.1:8500/v1/kv/proxies/webproxy01?token=afc37f61-c11d-ccc6-6454-73e73f0d150e
true
Using the Consul command
$ docker exec consul-server consul kv put -token=afc37f61-c11d-ccc6-6454-73e73f0d150e proxies/webproxy01 http://www.google.ca
Success! Data written to: proxies/webproxy01
Use devs token to read key value
Using the HTTP API
$ docker exec consul-server curl -s http://127.0.0.1:8500/v1/kv/proxies/webproxy01?token=c5ca5ed8-0df3-b8f0-11e8-12d3e2882c7d
[
{
"LockIndex": 0,
"Key": "proxies/webproxy01",
"Flags": 0,
"Value": "aHR0cDovL3d3dy5nb29nbGUuY2E=",
"CreateIndex": 166,
"ModifyIndex": 378
}
]
Using the Consul command
$ docker exec consul-server consul kv get -token=c5ca5ed8-0df3-b8f0-11e8-12d3e2882c7d proxies/webproxy01
http://www.google.ca
Additional concepts
- Recursive key retrieval
- Check-and-Set
- Watches
Create some users to seed our server with
$ mkdir ldap
$ cat > ldap/users.ldif
dn: ou=users,dc=example,dc=org
changeType: add
objectClass: organizationalUnit
description: Organization users
ou: users
dn: ou=roles,dc=example,dc=org
changeType: add
objectClass: organizationalUnit
description: Organization roles
ou: roles
dn: cn=sysadmins,ou=roles,dc=example,dc=org
changeType: add
objectClass: organizationalRole
description: System Admin role
dn: cn=developers,ou=roles,dc=example,dc=org
changeType: add
objectClass: organizationalRole
description: Developer role
dn: uid=dfayden,ou=users,dc=example,dc=org
changeType: add
objectClass: inetOrgPerson
description: Self-proclaimed "greatest thief in the Multiverse."
sn: Fayden
givenName: Dack
cn: Dack Fayden
uid: dfayden
mail: [email protected]
memberOf: cn=sysadmins,ou=roles,dc=example,dc=org
dn: uid=etirel,ou=users,dc=example,dc=org
changeType: add
objectClass: inetOrgPerson
description: Left her embattled homeland in search of a new place to call home.
sn: Tirel
givenName: Elspeth
cn: Elspeth Tirel
uid: etirel
mail: [email protected]
memberOf: cn=sysadmins,ou=roles,dc=example,dc=org
dn: uid=gjura,ou=users,dc=example,dc=org
changeType: add
objectClass: inetOrgPerson
description: Fiercely loyal, unyielding, just and charismatic.
sn: Jura
givenName: Gideon
cn: Gideon Jura
uid: gjura
mail: [email protected]
memberOf: cn=developers,ou=users,dc=example,dc=org
dn: uid=jbeleren,ou=users,dc=example,dc=org
changeType: add
objectClass: inetOrgPerson
description: Brilliant, curious, and always in control.
sn: Beleren
givenName: Jace
cn: Jace Beleren
uid: jbeleren
mail: [email protected]
memberOf: cn=developers,ou=users,dc=example,dc=org
^C
Start an OpenLDAP server
$ docker run -d --name ldap-server --network hashicorp -v $PWD/ldap:/container/service/slapd/assets/config/bootstrap/ldif/custom osixia/openldap:1.2.0 --copy-service
Perform an LDAP query to verify its working
$ docker exec ldap-server ldapsearch -x -H ldap://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
Enable LDAP auth in Vault
$ docker exec vault-server vault auth enable ldap
Success! Enabled ldap auth method at: ldap/
Configure LDAP auth in Vault
$ docker exec vault-server vault write auth/ldap/config \
$ docker exec vault-server vault write auth/ldap/config \
url="ldap://ldap-server"
userdn="ou=users,dc=example,dc=org"
userattr="uid"
groupdn="ou=roles,dc=example,dc=org"
groupfilter="(objectClass=organizationalRole)"
groupattr="cn"
upndomain="example.org"
binddn="cn=admin,dc=example,dc=org"
bindpass="admin"
Success! Data written to: auth/ldap/config
Create Vault policies
$ mkdir vault
$ cat > vault/consul-devs.json
path "consul/creds/devs" {
capabilities = ["read"]
}
^C
$ cat > vault/consul-sysadmins.json
path "consul/creds/sysadmins" {
capabilities = ["read"]
}
^C
$ docker cp vault/consul-devs.json /tmp/
$ docker cp vault/consul-sysadmins.json /tmp/
$ docker exec vault-server vault policy write consul-devs /tmp/consul-devs.json
Success! Uploaded policy: consul-devs
$ docker exec vault-server vault policy write consul-sysadmins /tmp/consul-devs.json
Success! Uploaded policy: consul-sysadmins
Link LDAP groups to Vault policies
$ docker exec vault-server vault write auth/ldap/groups/developers policies=consul-devs
Success! Data written to: auth/ldap/groups/developers
$ docker exec vault-server vault write auth/ldap/groups/sysadmins policies=consul-sysadmins
Success! Data written to: auth/ldap/groups/sysadmins
Additional reading