Skip to content

Instantly share code, notes, and snippets.

@mdasilva
Created May 8, 2018 20:06
Show Gist options
  • Save mdasilva/c3dd6785ffae5e2dcfd701394a7ad238 to your computer and use it in GitHub Desktop.
Save mdasilva/c3dd6785ffae5e2dcfd701394a7ad238 to your computer and use it in GitHub Desktop.

Setup Consul with ACL

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 

Setup Vault

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

Testing the setup so far

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

Vault LDAP Auth

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: dfayden@example.org
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: etirel@example.org
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: gjura@example.org
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: jbeleren@example.org
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 \
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment