-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9542 from ryanpetrello/centrify
Add support for Centrify Vault as a credential plugin replaces #8952 cc @surbhijain1502 @Asharma-bhavna @badrogh Reviewed-by: Ryan Petrello <None> Reviewed-by: Jake McDermott <yo@jakemcdermott.me> Reviewed-by: Chris Meyers <None>
- Loading branch information
Showing
5 changed files
with
214 additions
and
1 deletion.
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,142 @@ | ||
from .plugin import CredentialPlugin, raise_for_status | ||
from django.utils.translation import ugettext_lazy 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 | ||
) |
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,20 @@ | ||
from django.db import migrations | ||
|
||
from awx.main.models import CredentialType | ||
from awx.main.utils.common import set_current_apps | ||
|
||
|
||
def setup_tower_managed_defaults(apps, schema_editor): | ||
set_current_apps(apps) | ||
CredentialType.setup_tower_managed_defaults() | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('main', '0132_instancegroup_is_container_group'), | ||
] | ||
|
||
operations = [ | ||
migrations.RunPython(setup_tower_managed_defaults), | ||
] |
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
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
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