-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'features/filtered-awx-history' into devel
- Loading branch information
Showing
13 changed files
with
2,351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
from .plugin import CredentialPlugin, CertFiles, raise_for_status | ||
|
||
from urllib.parse import quote, urlencode, urljoin | ||
|
||
from .plugin import translate_function as _ | ||
import requests | ||
|
||
aim_inputs = { | ||
'fields': [ | ||
{ | ||
'id': 'url', | ||
'label': _('CyberArk CCP URL'), | ||
'type': 'string', | ||
'format': 'url', | ||
}, | ||
{ | ||
'id': 'webservice_id', | ||
'label': _('Web Service ID'), | ||
'type': 'string', | ||
'help_text': _('The CCP Web Service ID. Leave blank to default to AIMWebService.'), | ||
}, | ||
{ | ||
'id': 'app_id', | ||
'label': _('Application ID'), | ||
'type': 'string', | ||
'secret': True, | ||
}, | ||
{ | ||
'id': 'client_key', | ||
'label': _('Client Key'), | ||
'type': 'string', | ||
'secret': True, | ||
'multiline': True, | ||
}, | ||
{ | ||
'id': 'client_cert', | ||
'label': _('Client Certificate'), | ||
'type': 'string', | ||
'secret': True, | ||
'multiline': True, | ||
}, | ||
{ | ||
'id': 'verify', | ||
'label': _('Verify SSL Certificates'), | ||
'type': 'boolean', | ||
'default': True, | ||
}, | ||
], | ||
'metadata': [ | ||
{ | ||
'id': 'object_query', | ||
'label': _('Object Query'), | ||
'type': 'string', | ||
'help_text': _('Lookup query for the object. Ex: Safe=TestSafe;Object=testAccountName123'), | ||
}, | ||
{'id': 'object_query_format', 'label': _('Object Query Format'), 'type': 'string', 'default': 'Exact', 'choices': ['Exact', 'Regexp']}, | ||
{ | ||
'id': 'object_property', | ||
'label': _('Object Property'), | ||
'type': 'string', | ||
'help_text': _('The property of the object to return. Available properties: Username, Password and Address.'), | ||
}, | ||
{ | ||
'id': 'reason', | ||
'label': _('Reason'), | ||
'type': 'string', | ||
'help_text': _('Object request reason. This is only needed if it is required by the object\'s policy.'), | ||
}, | ||
], | ||
'required': ['url', 'app_id', 'object_query'], | ||
} | ||
|
||
|
||
def aim_backend(**kwargs): | ||
url = kwargs['url'] | ||
client_cert = kwargs.get('client_cert', None) | ||
client_key = kwargs.get('client_key', None) | ||
verify = kwargs['verify'] | ||
webservice_id = kwargs.get('webservice_id', '') | ||
app_id = kwargs['app_id'] | ||
object_query = kwargs['object_query'] | ||
object_query_format = kwargs['object_query_format'] | ||
object_property = kwargs.get('object_property', '') | ||
reason = kwargs.get('reason', None) | ||
if webservice_id == '': | ||
webservice_id = 'AIMWebService' | ||
|
||
query_params = { | ||
'AppId': app_id, | ||
'Query': object_query, | ||
'QueryFormat': object_query_format, | ||
} | ||
if reason: | ||
query_params['reason'] = reason | ||
|
||
request_qs = '?' + urlencode(query_params, quote_via=quote) | ||
request_url = urljoin(url, '/'.join([webservice_id, 'api', 'Accounts'])) | ||
|
||
with CertFiles(client_cert, client_key) as cert: | ||
res = requests.get( | ||
request_url + request_qs, | ||
timeout=30, | ||
cert=cert, | ||
verify=verify, | ||
allow_redirects=False, | ||
) | ||
raise_for_status(res) | ||
# CCP returns the property name capitalized, username is camel case | ||
# so we need to handle that case | ||
if object_property == '': | ||
object_property = 'Content' | ||
elif object_property.lower() == 'username': | ||
object_property = 'UserName' | ||
elif object_property.lower() == 'password': | ||
object_property = 'Content' | ||
elif object_property.lower() == 'address': | ||
object_property = 'Address' | ||
elif object_property not in res: | ||
raise KeyError('Property {} not found in object, available properties: Username, Password and Address'.format(object_property)) | ||
else: | ||
object_property = object_property.capitalize() | ||
|
||
return res.json()[object_property] | ||
|
||
|
||
aim_plugin = CredentialPlugin('CyberArk Central Credential Provider Lookup', inputs=aim_inputs, backend=aim_backend) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import boto3 | ||
from botocore.exceptions import ClientError | ||
|
||
from .plugin import CredentialPlugin | ||
from .plugin import translate_function as _ | ||
|
||
|
||
secrets_manager_inputs = { | ||
'fields': [ | ||
{ | ||
'id': 'aws_access_key', | ||
'label': _('AWS Access Key'), | ||
'type': 'string', | ||
}, | ||
{ | ||
'id': 'aws_secret_key', | ||
'label': _('AWS Secret Key'), | ||
'type': 'string', | ||
'secret': True, | ||
}, | ||
], | ||
'metadata': [ | ||
{ | ||
'id': 'region_name', | ||
'label': _('AWS Secrets Manager Region'), | ||
'type': 'string', | ||
'help_text': _('Region which the secrets manager is located'), | ||
}, | ||
{ | ||
'id': 'secret_name', | ||
'label': _('AWS Secret Name'), | ||
'type': 'string', | ||
}, | ||
], | ||
'required': ['aws_access_key', 'aws_secret_key', 'region_name', 'secret_name'], | ||
} | ||
|
||
|
||
def aws_secretsmanager_backend(**kwargs): | ||
secret_name = kwargs['secret_name'] | ||
region_name = kwargs['region_name'] | ||
aws_secret_access_key = kwargs['aws_secret_key'] | ||
aws_access_key_id = kwargs['aws_access_key'] | ||
|
||
session = boto3.session.Session() | ||
client = session.client( | ||
service_name='secretsmanager', region_name=region_name, aws_secret_access_key=aws_secret_access_key, aws_access_key_id=aws_access_key_id | ||
) | ||
|
||
try: | ||
get_secret_value_response = client.get_secret_value(SecretId=secret_name) | ||
except ClientError as e: | ||
raise e | ||
# Secrets Manager decrypts the secret value using the associated KMS CMK | ||
# Depending on whether the secret was a string or binary, only one of these fields will be populated | ||
if 'SecretString' in get_secret_value_response: | ||
secret = get_secret_value_response['SecretString'] | ||
|
||
else: | ||
secret = get_secret_value_response['SecretBinary'] | ||
|
||
return secret | ||
|
||
|
||
aws_secretmanager_plugin = CredentialPlugin('AWS Secrets Manager lookup', inputs=secrets_manager_inputs, backend=aws_secretsmanager_backend) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
from azure.keyvault.secrets import SecretClient | ||
from azure.identity import ClientSecretCredential | ||
from msrestazure import azure_cloud | ||
|
||
from .plugin import CredentialPlugin | ||
|
||
from .plugin import translate_function as _ | ||
|
||
|
||
# https://github.com/Azure/msrestazure-for-python/blob/master/msrestazure/azure_cloud.py | ||
clouds = [vars(azure_cloud)[n] for n in dir(azure_cloud) if n.startswith("AZURE_") and n.endswith("_CLOUD")] | ||
default_cloud = vars(azure_cloud)["AZURE_PUBLIC_CLOUD"] | ||
|
||
|
||
azure_keyvault_inputs = { | ||
'fields': [ | ||
{ | ||
'id': 'url', | ||
'label': _('Vault URL (DNS Name)'), | ||
'type': 'string', | ||
'format': 'url', | ||
}, | ||
{'id': 'client', 'label': _('Client ID'), 'type': 'string'}, | ||
{ | ||
'id': 'secret', | ||
'label': _('Client Secret'), | ||
'type': 'string', | ||
'secret': True, | ||
}, | ||
{'id': 'tenant', 'label': _('Tenant ID'), 'type': 'string'}, | ||
{ | ||
'id': 'cloud_name', | ||
'label': _('Cloud Environment'), | ||
'help_text': _('Specify which azure cloud environment to use.'), | ||
'choices': list(set([default_cloud.name] + [c.name for c in clouds])), | ||
'default': default_cloud.name, | ||
}, | ||
], | ||
'metadata': [ | ||
{ | ||
'id': 'secret_field', | ||
'label': _('Secret Name'), | ||
'type': 'string', | ||
'help_text': _('The name of the secret to look up.'), | ||
}, | ||
{ | ||
'id': 'secret_version', | ||
'label': _('Secret Version'), | ||
'type': 'string', | ||
'help_text': _('Used to specify a specific secret version (if left empty, the latest version will be used).'), | ||
}, | ||
], | ||
'required': ['url', 'client', 'secret', 'tenant', 'secret_field'], | ||
} | ||
|
||
|
||
def azure_keyvault_backend(**kwargs): | ||
csc = ClientSecretCredential(tenant_id=kwargs['tenant'], client_id=kwargs['client'], client_secret=kwargs['secret']) | ||
kv = SecretClient(credential=csc, vault_url=kwargs['url']) | ||
return kv.get_secret(name=kwargs['secret_field'], version=kwargs.get('secret_version', '')).value | ||
|
||
|
||
azure_keyvault_plugin = CredentialPlugin('Microsoft Azure Key Vault', inputs=azure_keyvault_inputs, backend=azure_keyvault_backend) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
from .plugin import CredentialPlugin, raise_for_status | ||
from .plugin import translate_function as _ | ||
from urllib.parse import urljoin | ||
import requests | ||
|
||
pas_inputs = { | ||
'fields': [ | ||
{ | ||
'id': 'url', | ||
'label': _('Centrify Tenant URL'), | ||
'type': 'string', | ||
'help_text': _('Centrify Tenant URL'), | ||
'format': 'url', | ||
}, | ||
{ | ||
'id': 'client_id', | ||
'label': _('Centrify API User'), | ||
'type': 'string', | ||
'help_text': _('Centrify API User, having necessary permissions as mentioned in support doc'), | ||
}, | ||
{ | ||
'id': 'client_password', | ||
'label': _('Centrify API Password'), | ||
'type': 'string', | ||
'help_text': _('Password of Centrify API User with necessary permissions'), | ||
'secret': True, | ||
}, | ||
{ | ||
'id': 'oauth_application_id', | ||
'label': _('OAuth2 Application ID'), | ||
'type': 'string', | ||
'help_text': _('Application ID of the configured OAuth2 Client (defaults to \'awx\')'), | ||
'default': 'awx', | ||
}, | ||
{ | ||
'id': 'oauth_scope', | ||
'label': _('OAuth2 Scope'), | ||
'type': 'string', | ||
'help_text': _('Scope of the configured OAuth2 Client (defaults to \'awx\')'), | ||
'default': 'awx', | ||
}, | ||
], | ||
'metadata': [ | ||
{ | ||
'id': 'account-name', | ||
'label': _('Account Name'), | ||
'type': 'string', | ||
'help_text': _('Local system account or Domain account name enrolled in Centrify Vault. eg. (root or DOMAIN/Administrator)'), | ||
}, | ||
{ | ||
'id': 'system-name', | ||
'label': _('System Name'), | ||
'type': 'string', | ||
'help_text': _('Machine Name enrolled with in Centrify Portal'), | ||
}, | ||
], | ||
'required': ['url', 'account-name', 'system-name', 'client_id', 'client_password'], | ||
} | ||
|
||
|
||
# generate bearer token to authenticate with PAS portal, Input : Client ID, Client Secret | ||
def handle_auth(**kwargs): | ||
post_data = {"grant_type": "client_credentials", "scope": kwargs['oauth_scope']} | ||
response = requests.post(kwargs['endpoint'], data=post_data, auth=(kwargs['client_id'], kwargs['client_password']), verify=True, timeout=(5, 30)) | ||
raise_for_status(response) | ||
try: | ||
return response.json()['access_token'] | ||
except KeyError: | ||
raise RuntimeError('OAuth request to tenant was unsuccessful') | ||
|
||
|
||
# fetch the ID of system with RedRock query, Input : System Name, Account Name | ||
def get_ID(**kwargs): | ||
endpoint = urljoin(kwargs['url'], '/Redrock/query') | ||
name = " Name='{0}' and User='{1}'".format(kwargs['system_name'], kwargs['acc_name']) | ||
query = 'Select ID from VaultAccount where {0}'.format(name) | ||
post_headers = {"Authorization": "Bearer " + kwargs['access_token'], "X-CENTRIFY-NATIVE-CLIENT": "true"} | ||
response = requests.post(endpoint, json={'Script': query}, headers=post_headers, verify=True, timeout=(5, 30)) | ||
raise_for_status(response) | ||
try: | ||
result_str = response.json()["Result"]["Results"] | ||
return result_str[0]["Row"]["ID"] | ||
except (IndexError, KeyError): | ||
raise RuntimeError("Error Detected!! Check the Inputs") | ||
|
||
|
||
# CheckOut Password from Centrify Vault, Input : ID | ||
def get_passwd(**kwargs): | ||
endpoint = urljoin(kwargs['url'], '/ServerManage/CheckoutPassword') | ||
post_headers = {"Authorization": "Bearer " + kwargs['access_token'], "X-CENTRIFY-NATIVE-CLIENT": "true"} | ||
response = requests.post(endpoint, json={'ID': kwargs['acc_id']}, headers=post_headers, verify=True, timeout=(5, 30)) | ||
raise_for_status(response) | ||
try: | ||
return response.json()["Result"]["Password"] | ||
except KeyError: | ||
raise RuntimeError("Password Not Found") | ||
|
||
|
||
def centrify_backend(**kwargs): | ||
url = kwargs.get('url') | ||
acc_name = kwargs.get('account-name') | ||
system_name = kwargs.get('system-name') | ||
client_id = kwargs.get('client_id') | ||
client_password = kwargs.get('client_password') | ||
app_id = kwargs.get('oauth_application_id', 'awx') | ||
endpoint = urljoin(url, f'/oauth2/token/{app_id}') | ||
endpoint = {'endpoint': endpoint, 'client_id': client_id, 'client_password': client_password, 'oauth_scope': kwargs.get('oauth_scope', 'awx')} | ||
token = handle_auth(**endpoint) | ||
get_id_args = {'system_name': system_name, 'acc_name': acc_name, 'url': url, 'access_token': token} | ||
acc_id = get_ID(**get_id_args) | ||
get_pwd_args = {'url': url, 'acc_id': acc_id, 'access_token': token} | ||
return get_passwd(**get_pwd_args) | ||
|
||
|
||
centrify_plugin = CredentialPlugin('Centrify Vault Credential Provider Lookup', inputs=pas_inputs, backend=centrify_backend) |
Oops, something went wrong.