Skip to content

Commit

Permalink
Added support for approles (#51)
Browse files Browse the repository at this point in the history
* Added support for approles

* Documented the approle support

* formated the documented vars

* Added link to official approle documentation

* Line too long fixed

* Reformated Code

* Changed method prefix to single underscore

* Changed _fetch_token to _fetch_github_token
  • Loading branch information
dervolker authored and jhaals committed Jul 31, 2017
1 parent c44d7b6 commit a62cdc3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 7 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ By default secrets fetched from Vault will be cached in memory, unless you speci
Note that secrets will be fetched once per fork (defaults to 5). If you turn off
this feature by toggling above variable, all lookups will be done per node instead.

### [`Approle`](https://www.vaultproject.io/docs/auth/approle.html) support

If you want to use the Approle auth backend, you can do this by setting the follwing
environment variables. If those vars are set, it is tried to get an approle token. If
caching is enabled, the token is stored in the cache, so that it can be reused.

export ANSIBLE_HASHICORP_VAULT_ROLE_ID=ba78195c-12c9-557f-f8e2-75705b9b52ec
export ANSIBLE_HASHICORP_VAULT_SECRET_ID=5a4d079b-e6aa-ad54-8b0c-09dd35b740ee

Per default the authentication will be done against ${YOUR_HOST}/v1/auth/approle/login
You can change this to fit your layout by setting the following var to your value:

export ANSIBLE_HASHICORP_VAULT_ROLE_PATH=v1/auth/my/role/path/approle/login

### Usage
ansible-vault works as any other lookup plugin.

Expand Down
45 changes: 38 additions & 7 deletions vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,28 @@ def run(self, terms, inject=None, variables=None, **kwargs):
raise AnsibleError('Vault address not set. Specify with'
' VAULT_ADDR environment variable or vault_addr Ansible variable')

# Support for Approle backend
approle_role_id = os.getenv('ANSIBLE_HASHICORP_VAULT_ROLE_ID')
approle_secret_id = os.getenv('ANSIBLE_HASHICORP_VAULT_SECRET_ID')
approle_role_path = os.getenv('ANSIBLE_HASHICORP_VAULT_ROLE_PATH', 'v1/auth/approle/login')

# first check if an approle token is already cached
vault_token = _vault_cache.get('ANSIBLE_HASHICORP_VAULT_APPROLE_TOKEN', None)

# if approle role-id and secret-id are set, use approle to get a token
# and if caching is activated, the token will be stored in the cache
if not vault_token and approle_role_id and approle_secret_id:
vault_token = self._fetch_approle_token(
cafile, capath, approle_role_id, approle_secret_id, approle_role_path, url, cahostverify)
if vault_token and _use_vault_cache:
_vault_cache['ANSIBLE_HASHICORP_VAULT_APPROLE_TOKEN'] = vault_token

# the environment variable takes precedence over the file-based token.
# intentionally do *not* support setting this via an Ansible variable,
# so as not to encourage bad security practices.
github_token = os.getenv('VAULT_GITHUB_API_TOKEN')
vault_token = os.getenv('VAULT_TOKEN')
if not vault_token:
vault_token = os.getenv('VAULT_TOKEN')
if not vault_token and not github_token:
token_path = os.path.join(os.getenv('HOME'), '.vault-token')
try:
Expand All @@ -126,24 +143,38 @@ def run(self, terms, inject=None, variables=None, **kwargs):
result = _vault_cache[key]
else:
if not vault_token:
token_result = self._fetch_token(cafile, capath, github_token, url, cahostverify)
token_result = self._fetch_github_token(cafile, capath, github_token, url, cahostverify)
vault_token = token_result['auth']['client_token']
result = self._fetch_remotely(cafile, capath, data, key, vault_token, url, cahostverify)
if _use_vault_cache:
_vault_cache[key] = result

return [result['data'][field]] if field is not None else [result['data']]

def _fetch_token(self, cafile, capath, github_token, url, cahostverify):
def _fetch_approle_token(self, cafile, capath, role_id, secret_id, approle_role_path, url, cahostverify):
request_url = urljoin(url, approle_role_path)
req_params = {
'role_id': role_id,
'secret_id': secret_id
}
result = self._fetch_client_token(cafile, capath, request_url, req_params, cahostverify)
token = result['auth']['client_token']
return token

def _fetch_github_token(self, cafile, capath, github_token, url, cahostverify):
request_url = urljoin(url, "v1/auth/github/login")
req_params = {}
req_params['token'] = github_token
result = self._fetch_client_token(cafile, capath, request_url, req_params, cahostverify)
return result

def _fetch_client_token(self, cafile, capath, url, data, cahostverify):
try:
context = None
if cafile or capath:
context = ssl.create_default_context(cafile=cafile, capath=capath)
context.check_hostname = cahostverify
request_url = urljoin(url, "v1/auth/github/login")
req_params = {}
req_params['token'] = github_token
req = urllib2.Request(request_url, json.dumps(req_params))
req = urllib2.Request(url, json.dumps(data))
req.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(req, context=context) if context else urllib2.urlopen(req)
except AttributeError as e:
Expand Down

0 comments on commit a62cdc3

Please sign in to comment.