Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to pass vault namespace in AWX “HashiCorp Vault Signed SSH” type credential for role_id and secret_id based authentication #7399

Closed
haribhauhud opened this issue Jun 22, 2020 · 5 comments

Comments

@haribhauhud
Copy link

ISSUE TYPE
  • Extend “HashiCorp Vault Signed SSH” credential support for passing namespace
SUMMARY

We have our internal private vault server for credential management, to retrieve the token from the vault we are using app_role authentication.

Below is the equivalent curl command:

curl --request POST -H "X-Vault-Namespace: " --data '{"role_id": "<ROLE_ID>", "secret_id": "<SECRET_ID>"}' http://<VAULT_ADDR>/v1/auth/approle/login

So here in this case passing namespace is mandatory for us else it will return incorrect role_id not found because we are using namespace in Vault.

As we are integrating AWX with Vault, we are using HashiCorp Vault Signed SSH for authentication using APPROLE ROLE_ID and APPROLE SECRET_ID. There are other all the required fields to pass as input to vault queries like role_name, path_to_secert, and public_key. However, there is no way to pass the vault namespace (and no code to set header) and so we are getting the result as "invalid role_id".

We have tried to hardcode the namespace in awx_web and awx_task in hashivault.py file, then it works for us.

import requests
sess = requests.Session()
headers = {'X-Vault-Namespace': 'our_ns'}
resp = sess.post(request_url, **request_kwargs, headers=headers)
resp.raise_for_status()
token = resp.json()['auth']['client_token']

Can someone please suggest to us how to pass the namespace from AWX UI or is there any other way to handle this scenario?

@ryanpetrello
Copy link
Contributor

@codersplanet sounds like an opportunity for a pull request to the Hashivault credential plugin.

@zaskan
Copy link

zaskan commented Oct 15, 2020

@haribhauhud Can you please follow these steps and confirm if it worked for you?

  1. Create you Hashicorp Vault credential in ansible Tower.
  2. Create the machine credential and use the username you created previously for Hasicorp's Vault
  3. Click on the search icon of "username" (also password and private key should work)
  4. Click on metadata
  5. Specify the namespace in "NAME OF THE SECRET BACKEND" (/<NAMESPACE>/<SECRET ENGINE>)
  6. Then the namespace and the secret engine must be omitted from the "PATH TO SECRET".

@jamesmarshall24
Copy link
Contributor

The above instructions work for testing the query, but clicking save results in the following tower.log entry:

[TIMESTAMP] ERROR    django.request Internal Server Error: /api/v2/credentials/N/
Traceback (most recent call last):
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib64/python3.6/contextlib.py", line 52, in inner
    return func(*args, **kwds)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/api/generics.py", line 304, in dispatch
    return super(APIView, self).dispatch(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
    raise exc
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/generics.py", line 255, in put
    return self.update(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/api/generics.py", line 780, in update
    return super(RetrieveUpdateAPIView, self).update(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/mixins.py", line 67, in update
    serializer.is_valid(raise_exception=True)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/serializers.py", line 234, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/api/serializers.py", line 564, in run_validation
    return super(BaseSerializer, self).run_validation(data)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/rest_framework/serializers.py", line 436, in run_validation
    value = self.validate(value)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/api/serializers.py", line 598, in validate
    obj.full_clean(exclude=exclusions)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/db/models/base.py", line 1181, in full_clean
    self.clean_fields(exclude=exclude)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/models/base.py", line 109, in clean_fields
    super(BaseModel, self).clean_fields(exclude)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/db/models/base.py", line 1223, in clean_fields
    setattr(self, f.attname, f.clean(raw_value, self))
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/django/db/models/fields/__init__.py", line 630, in clean
    self.validate(value, model_instance)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/fields.py", line 701, in validate
    if model_instance.has_encrypted_ssh_key_data and not value.get('ssh_key_unlock'):
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/models/credential/__init__.py", line 159, in has_encrypted_ssh_key_data
    ssh_key_data = self.get_input('ssh_key_data')
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/models/credential/__init__.py", line 278, in get_input
    return self._get_dynamic_input(field_name)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/models/credential/__init__.py", line 306, in _get_dynamic_input
    return input_source.get_input_value()
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/models/credential/__init__.py", line 1218, in get_input_value
    return backend(**backend_kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/main/credential_plugins/hashivault.py", line 130, in kv_backend
    response.raise_for_status()
  File "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/requests/models.py", line 941, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://vault/v1/path/to/kv/

@lucab85
Copy link

lucab85 commented Jun 24, 2021

+1 case 02972971

@wenottingham
Copy link
Contributor

This should be in AWX as of #9590. Let us know if it works for you!

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

No branches or pull requests

6 participants