diff --git a/awx/main/credential_plugins/conjur.py b/awx/main/credential_plugins/conjur.py index 645ff16afa..048170843f 100644 --- a/awx/main/credential_plugins/conjur.py +++ b/awx/main/credential_plugins/conjur.py @@ -1,7 +1,10 @@ from .plugin import CredentialPlugin import base64 -import io +import os +import stat +import tempfile +import threading from urllib.parse import urljoin, quote_plus from django.utils.translation import ugettext_lazy as _ @@ -47,6 +50,24 @@ conjur_inputs = { } +def create_temporary_fifo(data): + """Open fifo named pipe in a new thread using a temporary file path. The + thread blocks until data is read from the pipe. + + Returns the path to the fifo. + + :param data(bytes): Data to write to the pipe. + """ + path = os.path.join(tempfile.mkdtemp(), next(tempfile._get_candidate_names())) + os.mkfifo(path, stat.S_IRUSR | stat.S_IWUSR) + + threading.Thread( + target=lambda p, d: open(p, 'wb').write(d), + args=(path, data) + ).start() + return path + + def conjur_backend(**kwargs): url = kwargs['url'] api_key = kwargs['api_key'] @@ -54,19 +75,29 @@ def conjur_backend(**kwargs): username = quote_plus(kwargs['username']) secret_path = quote_plus(kwargs['secret_path']) version = kwargs.get('secret_version') - cert = io.StringIO() - cert.write(kwargs.get('cacert', '')) + cacert = kwargs.get('cacert', None) + + auth_kwargs = { + 'headers': {'Content-Type': 'text/plain'}, + 'data': api_key + } + if cacert: + auth_kwargs['verify'] = create_temporary_fifo(cacert.encode()) # https://www.conjur.org/api.html#authentication-authenticate-post resp = requests.post( urljoin(url, '/'.join(['authn', account, username, 'authenticate'])), - headers={'Content-Type': 'text/plain'}, - data=api_key, - verify=cert + **auth_kwargs ) resp.raise_for_status() token = base64.b64encode(resp.content).decode('utf-8') + lookup_kwargs = { + 'headers': {'Authorization': 'Token token="{}"'.format(token)}, + } + if cacert: + lookup_kwargs['verify'] = create_temporary_fifo(cacert.encode()) + # https://www.conjur.org/api.html#secrets-retrieve-a-secret-get path = urljoin(url, '/'.join([ 'secrets', @@ -76,11 +107,8 @@ def conjur_backend(**kwargs): ])) if version: path = '?'.join([path, version]) - resp = requests.get( - path, - headers={'Authorization': 'Token token="{}"'.format(token)}, - verify=cert - ) + + resp = requests.get(path, **lookup_kwargs) resp.raise_for_status() return resp.text