Merge pull request #4285 from olia-dev/issue-4274

related #4274 - added option to verify server certificate with a specific CA

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
This commit is contained in:
softwarefactory-project-zuul[bot]
2019-07-11 16:50:26 +00:00
committed by GitHub
4 changed files with 63 additions and 66 deletions

View File

@@ -1,14 +1,14 @@
from .plugin import CredentialPlugin from .plugin import CredentialPlugin
import os
import stat
import tempfile
import threading
from urllib.parse import quote, urlencode, urljoin from urllib.parse import quote, urlencode, urljoin
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import requests import requests
# AWX
from awx.main.utils import (
create_temporary_fifo,
)
aim_inputs = { aim_inputs = {
'fields': [{ 'fields': [{
@@ -60,24 +60,6 @@ aim_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 aim_backend(**kwargs): def aim_backend(**kwargs):
url = kwargs['url'] url = kwargs['url']
client_cert = kwargs.get('client_cert', None) client_cert = kwargs.get('client_cert', None)

View File

@@ -1,15 +1,16 @@
from .plugin import CredentialPlugin from .plugin import CredentialPlugin
import base64 import base64
import os
import stat
import tempfile
import threading
from urllib.parse import urljoin, quote_plus from urllib.parse import urljoin, quote_plus
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import requests import requests
# AWX
from awx.main.utils import (
create_temporary_fifo,
)
conjur_inputs = { conjur_inputs = {
'fields': [{ 'fields': [{
@@ -51,24 +52,6 @@ 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): def conjur_backend(**kwargs):
url = kwargs['url'] url = kwargs['url']
api_key = kwargs['api_key'] api_key = kwargs['api_key']

View File

@@ -8,6 +8,10 @@ from .plugin import CredentialPlugin
import requests import requests
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
# AWX
from awx.main.utils import (
create_temporary_fifo,
)
base_inputs = { base_inputs = {
'fields': [{ 'fields': [{
@@ -22,6 +26,12 @@ base_inputs = {
'type': 'string', 'type': 'string',
'secret': True, 'secret': True,
'help_text': _('The access token used to authenticate to the Vault server'), 'help_text': _('The access token used to authenticate to the Vault server'),
}, {
'id': 'cacert',
'label': _('CA Certificate'),
'type': 'string',
'multiline': True,
'help_text': _('The CA certificate used to verify the SSL certificate of the Vault server')
}], }],
'metadata': [{ 'metadata': [{
'id': 'secret_path', 'id': 'secret_path',
@@ -78,31 +88,34 @@ def kv_backend(**kwargs):
url = urljoin(kwargs['url'], 'v1') url = urljoin(kwargs['url'], 'v1')
secret_path = kwargs['secret_path'] secret_path = kwargs['secret_path']
secret_key = kwargs.get('secret_key', None) secret_key = kwargs.get('secret_key', None)
cacert = kwargs.get('cacert', None)
api_version = kwargs['api_version'] api_version = kwargs['api_version']
request_kwargs = {'timeout': 30}
if cacert:
request_kwargs['verify'] = create_temporary_fifo(cacert.encode())
sess = requests.Session() sess = requests.Session()
sess.headers['Authorization'] = 'Bearer {}'.format(token) sess.headers['Authorization'] = 'Bearer {}'.format(token)
if api_version == 'v2': if api_version == 'v2':
params = {}
if kwargs.get('secret_version'): if kwargs.get('secret_version'):
params['version'] = kwargs['secret_version'] request_kwargs['params'] = {'version': kwargs['secret_version']}
try: try:
mount_point, *path = pathlib.Path(secret_path.lstrip(os.sep)).parts mount_point, *path = pathlib.Path(secret_path.lstrip(os.sep)).parts
'/'.join(path) '/'.join(path)
except Exception: except Exception:
mount_point, path = secret_path, [] mount_point, path = secret_path, []
# https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version # https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version
response = sess.get( request_url = '/'.join([url, mount_point, 'data'] + path).rstrip('/')
'/'.join([url, mount_point, 'data'] + path).rstrip('/'), response = sess.get(request_url, **request_kwargs)
params=params,
timeout=30
)
response.raise_for_status() response.raise_for_status()
json = response.json()['data'] json = response.json()['data']
else: else:
# https://www.vaultproject.io/api/secret/kv/kv-v1.html#read-secret request_url = '/'.join([url, secret_path]).rstrip('/')
response = sess.get('/'.join([url, secret_path]).rstrip('/'), timeout=30) response = sess.get(request_url, **request_kwargs)
response.raise_for_status() response.raise_for_status()
json = response.json() json = response.json()
@@ -121,20 +134,22 @@ def ssh_backend(**kwargs):
url = urljoin(kwargs['url'], 'v1') url = urljoin(kwargs['url'], 'v1')
secret_path = kwargs['secret_path'] secret_path = kwargs['secret_path']
role = kwargs['role'] role = kwargs['role']
cacert = kwargs.get('cacert', None)
request_kwargs = {'timeout': 30}
if cacert:
request_kwargs['verify'] = create_temporary_fifo(cacert.encode())
request_kwargs['json'] = {'public_key': kwargs['public_key']}
if kwargs.get('valid_principals'):
request_kwargs['json']['valid_principals'] = kwargs['valid_principals']
sess = requests.Session() sess = requests.Session()
sess.headers['Authorization'] = 'Bearer {}'.format(token) sess.headers['Authorization'] = 'Bearer {}'.format(token)
json = {
'public_key': kwargs['public_key']
}
if kwargs.get('valid_principals'):
json['valid_principals'] = kwargs['valid_principals']
# https://www.vaultproject.io/api/secret/ssh/index.html#sign-ssh-key # https://www.vaultproject.io/api/secret/ssh/index.html#sign-ssh-key
resp = sess.post( request_url = '/'.join([url, secret_path, 'sign', role]).rstrip('/')
'/'.join([url, secret_path, 'sign', role]).rstrip('/'), resp = sess.post(request_url, **request_kwargs)
json=json,
timeout=30
)
resp.raise_for_status() resp.raise_for_status()
return resp.json()['data']['signed_key'] return resp.json()['data']['signed_key']

View File

@@ -44,7 +44,7 @@ __all__ = ['get_object_or_400', 'camelcase_to_underscore', 'underscore_to_camelc
'wrap_args_with_proot', 'build_proot_temp_dir', 'check_proot_installed', 'model_to_dict', 'wrap_args_with_proot', 'build_proot_temp_dir', 'check_proot_installed', 'model_to_dict',
'model_instance_diff', 'parse_yaml_or_json', 'RequireDebugTrueOrTest', 'model_instance_diff', 'parse_yaml_or_json', 'RequireDebugTrueOrTest',
'has_model_field_prefetched', 'set_environ', 'IllegalArgumentError', 'get_custom_venv_choices', 'get_external_account', 'has_model_field_prefetched', 'set_environ', 'IllegalArgumentError', 'get_custom_venv_choices', 'get_external_account',
'task_manager_bulk_reschedule', 'schedule_task_manager', 'classproperty'] 'task_manager_bulk_reschedule', 'schedule_task_manager', 'classproperty', 'create_temporary_fifo']
def get_object_or_400(klass, *args, **kwargs): def get_object_or_400(klass, *args, **kwargs):
@@ -1015,3 +1015,20 @@ class classproperty:
def __get__(self, instance, ownerclass): def __get__(self, instance, ownerclass):
return self.fget(ownerclass) return self.fget(ownerclass)
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