mirror of
https://github.com/ansible/awx.git
synced 2026-03-03 09:48:51 -03:30
store the public key for HashiVault signing in the plugin metadata
This commit is contained in:
committed by
Jake McDermott
parent
2824616ba6
commit
0768c6ac1d
@@ -1440,8 +1440,11 @@ class CredentialExternalTest(SubDetailAPIView):
|
|||||||
backend_kwargs[field_name] = value
|
backend_kwargs[field_name] = value
|
||||||
backend_kwargs.update(request.data.get('metadata', {}))
|
backend_kwargs.update(request.data.get('metadata', {}))
|
||||||
try:
|
try:
|
||||||
obj.credential_type.plugin.backend(None, **backend_kwargs)
|
obj.credential_type.plugin.backend(**backend_kwargs)
|
||||||
return Response({}, status=status.HTTP_202_ACCEPTED)
|
return Response({}, status=status.HTTP_202_ACCEPTED)
|
||||||
|
except requests.exceptions.HTTPError as exc:
|
||||||
|
message = 'HTTP {}\n{}'.format(exc.response.status_code, exc.response.text)
|
||||||
|
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
return Response({'inputs': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
|
return Response({'inputs': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@@ -1489,8 +1492,11 @@ class CredentialTypeExternalTest(SubDetailAPIView):
|
|||||||
backend_kwargs = request.data.get('inputs', {})
|
backend_kwargs = request.data.get('inputs', {})
|
||||||
backend_kwargs.update(request.data.get('metadata', {}))
|
backend_kwargs.update(request.data.get('metadata', {}))
|
||||||
try:
|
try:
|
||||||
obj.plugin.backend(None, **backend_kwargs)
|
obj.plugin.backend(**backend_kwargs)
|
||||||
return Response({}, status=status.HTTP_202_ACCEPTED)
|
return Response({}, status=status.HTTP_202_ACCEPTED)
|
||||||
|
except requests.exceptions.HTTPError as exc:
|
||||||
|
message = 'HTTP {}\n{}'.format(exc.response.status_code, exc.response.text)
|
||||||
|
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
return Response({'inputs': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
|
return Response({'inputs': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ azure_keyvault_inputs = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def azure_keyvault_backend(raw, **kwargs):
|
def azure_keyvault_backend(**kwargs):
|
||||||
url = kwargs['url']
|
url = kwargs['url']
|
||||||
|
|
||||||
def auth_callback(server, resource, scope):
|
def auth_callback(server, resource, scope):
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ conjur_inputs = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def conjur_backend(raw, **kwargs):
|
def conjur_backend(**kwargs):
|
||||||
url = kwargs['url']
|
url = kwargs['url']
|
||||||
api_key = kwargs['api_key']
|
api_key = kwargs['api_key']
|
||||||
account = quote_plus(kwargs['account'])
|
account = quote_plus(kwargs['account'])
|
||||||
|
|||||||
@@ -53,7 +53,12 @@ hashi_kv_inputs['metadata'].extend([{
|
|||||||
hashi_kv_inputs['required'].extend(['api_version', 'secret_key'])
|
hashi_kv_inputs['required'].extend(['api_version', 'secret_key'])
|
||||||
|
|
||||||
hashi_ssh_inputs = copy.deepcopy(base_inputs)
|
hashi_ssh_inputs = copy.deepcopy(base_inputs)
|
||||||
hashi_ssh_inputs['metadata'].extend([{
|
hashi_ssh_inputs['metadata'] = [{
|
||||||
|
'id': 'public_key',
|
||||||
|
'label': _('Unsigned Public Key'),
|
||||||
|
'type': 'string',
|
||||||
|
'multiline': True,
|
||||||
|
}] + hashi_ssh_inputs['metadata'] + [{
|
||||||
'id': 'role',
|
'id': 'role',
|
||||||
'label': _('Role Name'),
|
'label': _('Role Name'),
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
@@ -63,11 +68,11 @@ hashi_ssh_inputs['metadata'].extend([{
|
|||||||
'label': _('Valid Principals'),
|
'label': _('Valid Principals'),
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'help_text': _('Valid principals (either usernames or hostnames) that the certificate should be signed for.'),
|
'help_text': _('Valid principals (either usernames or hostnames) that the certificate should be signed for.'),
|
||||||
}])
|
}]
|
||||||
hashi_ssh_inputs['required'].extend(['role'])
|
hashi_ssh_inputs['required'].extend(['public_key', 'role'])
|
||||||
|
|
||||||
|
|
||||||
def kv_backend(raw, **kwargs):
|
def kv_backend(**kwargs):
|
||||||
token = kwargs['token']
|
token = kwargs['token']
|
||||||
url = urljoin(kwargs['url'], 'v1')
|
url = urljoin(kwargs['url'], 'v1')
|
||||||
secret_path = kwargs['secret_path']
|
secret_path = kwargs['secret_path']
|
||||||
@@ -109,7 +114,7 @@ def kv_backend(raw, **kwargs):
|
|||||||
return json['data']
|
return json['data']
|
||||||
|
|
||||||
|
|
||||||
def ssh_backend(raw, **kwargs):
|
def ssh_backend(**kwargs):
|
||||||
token = kwargs['token']
|
token = kwargs['token']
|
||||||
url = urljoin(kwargs['url'], 'v1')
|
url = urljoin(kwargs['url'], 'v1')
|
||||||
secret_path = kwargs['secret_path']
|
secret_path = kwargs['secret_path']
|
||||||
@@ -118,7 +123,7 @@ def ssh_backend(raw, **kwargs):
|
|||||||
sess = requests.Session()
|
sess = requests.Session()
|
||||||
sess.headers['Authorization'] = 'Bearer {}'.format(token)
|
sess.headers['Authorization'] = 'Bearer {}'.format(token)
|
||||||
json = {
|
json = {
|
||||||
'public_key': raw
|
'public_key': kwargs['public_key']
|
||||||
}
|
}
|
||||||
if kwargs.get('valid_principals'):
|
if kwargs.get('valid_principals'):
|
||||||
json['valid_principals'] = kwargs['valid_principals']
|
json['valid_principals'] = kwargs['valid_principals']
|
||||||
|
|||||||
@@ -1362,13 +1362,7 @@ class CredentialInputSource(PrimordialModel):
|
|||||||
backend_kwargs[field_name] = value
|
backend_kwargs[field_name] = value
|
||||||
|
|
||||||
backend_kwargs.update(self.metadata)
|
backend_kwargs.update(self.metadata)
|
||||||
raw = self.target_credential.inputs.get(self.input_field_name)
|
return backend(**backend_kwargs)
|
||||||
if self.input_field_name in self.target_credential.credential_type.secret_fields:
|
|
||||||
raw = decrypt_field(self.target_credential, self.input_field_name)
|
|
||||||
return backend(
|
|
||||||
raw,
|
|
||||||
**backend_kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_absolute_url(self, request=None):
|
def get_absolute_url(self, request=None):
|
||||||
view_name = 'api:credential_input_source_detail'
|
view_name = 'api:credential_input_source_detail'
|
||||||
|
|||||||
@@ -124,22 +124,6 @@ setuptools.setup(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Fetching vs. Transforming Credential Data
|
|
||||||
-----------------------------------------
|
|
||||||
While _most_ credential plugins will be used to _fetch_ secrets from external
|
|
||||||
systems, they can also be used to *transform* data from Tower _using_ an
|
|
||||||
external secret management system. An example use case is generating signed
|
|
||||||
public keys:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def my_key_signer(unsigned_value_from_awx, **kwargs):
|
|
||||||
return some_libary.sign(
|
|
||||||
url=kwargs['url'],
|
|
||||||
token=kwargs['token'],
|
|
||||||
public_data=unsigned_value_from_awx
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Programmatic Secret Fetching
|
Programmatic Secret Fetching
|
||||||
----------------------------
|
----------------------------
|
||||||
If you want to programmatically fetch secrets from a supported external secret
|
If you want to programmatically fetch secrets from a supported external secret
|
||||||
@@ -288,7 +272,7 @@ HTTP/1.1 200 OK
|
|||||||
-H "Authorization: Bearer <token>" \
|
-H "Authorization: Bearer <token>" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-X POST \
|
-X POST \
|
||||||
-d '{"user": N, "credential_type": 1, "name": "My SSH", "inputs": {"username": "example", "ssh_key_data": "RSA KEY DATA", "ssh_public_key_data": "UNSIGNED PUBLIC KEY DATA"}}'
|
-d '{"user": N, "credential_type": 1, "name": "My SSH", "inputs": {"username": "example", "ssh_key_data": "RSA KEY DATA"}}'
|
||||||
|
|
||||||
HTTP/1.1 201 Created
|
HTTP/1.1 201 Created
|
||||||
{
|
{
|
||||||
@@ -320,7 +304,7 @@ HTTP/1.1 201 Created
|
|||||||
-H "Authorization: Bearer <token>" \
|
-H "Authorization: Bearer <token>" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-X POST \
|
-X POST \
|
||||||
-d '{"source_credential": 2, "input_field_name": "password", "metadata": {"secret_path": "/ssh/", "role": "example-role"}}'
|
-d '{"source_credential": 2, "input_field_name": "password", "metadata": {"public_key": "UNSIGNED PUBLIC KEY", "secret_path": "/ssh/", "role": "example-role"}}'
|
||||||
HTTP/1.1 201 Created
|
HTTP/1.1 201 Created
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user