From a317b6bedeb37873ab596845b43feeb7d1dfc5bf Mon Sep 17 00:00:00 2001 From: Adam Migus Date: Thu, 8 Apr 2021 02:01:05 -0400 Subject: [PATCH] Add Thycotic DevOps Secrets Vault support --- awx/main/credential_plugins/dsv.py | 71 ++++++++++++++++++++++++++++++ awx/settings/defaults.py | 6 +++ requirements/requirements.in | 1 + requirements/requirements.txt | 3 ++ setup.py | 1 + 5 files changed, 82 insertions(+) create mode 100644 awx/main/credential_plugins/dsv.py diff --git a/awx/main/credential_plugins/dsv.py b/awx/main/credential_plugins/dsv.py new file mode 100644 index 0000000000..7fca6a81f7 --- /dev/null +++ b/awx/main/credential_plugins/dsv.py @@ -0,0 +1,71 @@ +from .plugin import CredentialPlugin + +from django.conf import settings +from django.utils.translation import get_language, to_locale, ugettext_lazy as _ +from thycotic.secrets.vault import SecretsVault + + +dsv_inputs = { + 'fields': [ + { + 'id': 'tenant', + 'label': _('Tenant'), + 'help_text': _('The tenant e.g. "ex" when the URL is https://ex.secretservercloud.com'), + 'type': 'string', + }, + {'id': 'client_id', 'label': _('Client ID'), 'type': 'string'}, + { + 'id': 'client_secret', + 'label': _('Client Secret'), + 'type': 'string', + 'secret': True, + }, + ], + 'metadata': [ + { + 'id': 'path', + 'label': _('Secret Path'), + 'type': 'string', + 'help_text': _('The secret path e.g. /test/secret1'), + }, + { + 'id': 'expr', + 'label': _('Attribute Expression'), + 'type': 'string', + 'help_text': _('A Python expression on the dict representation of the secret e.g. "data.username"'), + }, + ], + 'required': ['tenant', 'client_id', 'client_secret', 'path'], +} + +if settings.DEBUG: + dsv_inputs['fields'].append( + { + 'id': 'url_template', + 'label': _('URL template'), + 'type': 'string', + 'default': 'https://{}.secretsvaultcloud.{}/v1', + } + ) + +if to_locale(get_language()) != 'en_US': + dsv_inputs['fields'].append( + { + 'id': 'tld', + 'label': _('Top-level Domain (TLD)'), + 'help_text': _('The Top-level domain of the tenant e.g. "com" when the URL is https://ex.secretservercloud.com'), + 'type': 'string', + 'default': 'com', + 'choices': ['ca', 'com', 'com.au', 'com.sg', 'eu'], + } + ) + + +dsv_plugin = CredentialPlugin( + 'Thycotic DevOps Secrets Vault', + dsv_inputs, + lambda **kwargs: eval( + kwargs['expr'], + SecretsVault(**{k: v for (k, v) in kwargs.items() if k in [field['id'] for field in dsv_inputs['fields']]}).get_secret(kwargs['path']), + ), +) diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index d1b38a2c1e..046392c3e9 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -701,6 +701,12 @@ SATELLITE6_INSTANCE_ID_VAR = 'foreman_id' INSIGHTS_INSTANCE_ID_VAR = 'insights_id' INSIGHTS_EXCLUDE_EMPTY_GROUPS = False +# --------------------- +# --- Thycotic DSV ---- +# --------------------- +DSV_SHOW_TLD = False # overridden when LOCALE != en_US +DSV_SHOW_URL_TEMPLATE = False + # --------------------- # ----- Custom ----- # --------------------- diff --git a/requirements/requirements.in b/requirements/requirements.in index c990767f63..d1b4d1a406 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -42,6 +42,7 @@ psutil pygerduty pyparsing python3-saml +python-dsv-sdk python-ldap>=3.3.1 # https://github.com/python-ldap/python-ldap/issues/270 pyyaml>=5.4.1 # minimum to fix https://github.com/yaml/pyyaml/issues/478 receptorctl diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 0498e5694e..b82437bce3 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -274,6 +274,8 @@ python-dateutil==2.8.1 # adal # kubernetes # receptorctl +python-dsv-sdk==0.0.1 + # via -r /awx_devel/requirements/requirements.in python-ldap==3.3.1 # via # -r /awx_devel/requirements/requirements.in @@ -316,6 +318,7 @@ requests==2.23.0 # django-oauth-toolkit # kubernetes # msrest + # python-dsv-sdk # requests-oauthlib # slackclient # social-auth-core diff --git a/setup.py b/setup.py index a318cb34e9..8c28f28a43 100755 --- a/setup.py +++ b/setup.py @@ -130,6 +130,7 @@ setup( 'azure_kv = awx.main.credential_plugins.azure_kv:azure_keyvault_plugin', 'aim = awx.main.credential_plugins.aim:aim_plugin', 'centrify_vault_kv = awx.main.credential_plugins.centrify_vault:centrify_plugin', + 'thycotic_dsv = awx.main.credential_plugins.dsv:dsv_plugin', ], }, data_files=proc_data_files(