read cert from memory

Certificate data lives in the db. We're using a fifo here so we can avoid writing
it to disk when making the http request.
This commit is contained in:
Jake McDermott 2019-03-21 15:13:54 -04:00
parent 3dee9f0512
commit cb238c1f24
No known key found for this signature in database
GPG Key ID: 9A6F084352C3A0B7

View File

@ -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