Inbound SSO improvements

This commit is contained in:
Jay Lee
2022-11-18 16:06:14 +00:00
parent 9b6ad2fa60
commit 8c33b88e3e
3 changed files with 150 additions and 21 deletions

View File

@@ -11624,6 +11624,8 @@ def ProcessGAMCommand(args):
gapi_directory_customer.doGetCustomerInfo() gapi_directory_customer.doGetCustomerInfo()
elif argument in ['inboundssoprofile', 'inboundssoprofiles']: elif argument in ['inboundssoprofile', 'inboundssoprofiles']:
gapi_cloudidentity_inboundsso.info_profile() gapi_cloudidentity_inboundsso.info_profile()
elif argument in ['inboundssoassignment', 'inboundssoassignments']:
gapi_cloudidentity_inboundsso.info_assignment()
elif argument in ['org', 'ou', 'orgunit']: elif argument in ['org', 'ou', 'orgunit']:
gapi_directory_orgunits.info() gapi_directory_orgunits.info()
elif argument == 'resource': elif argument == 'resource':
@@ -11795,13 +11797,13 @@ def ProcessGAMCommand(args):
elif argument in ['groupmembers', 'groupsmembers']: elif argument in ['groupmembers', 'groupsmembers']:
gapi_directory_groups.print_members() gapi_directory_groups.print_members()
elif argument in ['inboundssoassignment', 'inboundssoassignments']: elif argument in ['inboundssoassignment', 'inboundssoassignments']:
gapi_cloudidentity_inboundsso.print_assignments() gapi_cloudidentity_inboundsso.print_show_assignments()
elif argument in ['cigroupmembers', 'cigroupsmembers']: elif argument in ['cigroupmembers', 'cigroupsmembers']:
gapi_cloudidentity_groups.print_members() gapi_cloudidentity_groups.print_members()
elif argument in ['inboundssoprofile', 'inboundssoprofiles']: elif argument in ['inboundssoprofile', 'inboundssoprofiles']:
gapi_cloudidentity_inboundsso.print_profiles() gapi_cloudidentity_inboundsso.print_show_profiles()
elif argument in ['inboundssocredential', 'inboundssocredentials']: elif argument in ['inboundssocredential', 'inboundssocredentials']:
gapi_cloudidentity_inboundsso.print_credentials() gapi_cloudidentity_inboundsso.print_show_credentials()
elif argument in ['orgs', 'ous']: elif argument in ['orgs', 'ous']:
gapi_directory_orgunits.print_() gapi_directory_orgunits.print_()
elif argument == 'privileges': elif argument == 'privileges':
@@ -11902,6 +11904,12 @@ def ProcessGAMCommand(args):
gapi_licensing.show() gapi_licensing.show()
elif argument in ['project', 'projects']: elif argument in ['project', 'projects']:
doPrintShowProjects(False) doPrintShowProjects(False)
elif argument in ['inboundssoprofile', 'inboundssoprofiles']:
gapi_cloudidentity_inboundsso.print_show_profiles('show')
elif argument in ['inboundssocredential', 'inboundssocredentials']:
gapi_cloudidentity_inboundsso.print_show_credentials('show')
elif argument in ['inboundssoassignment', 'inboundssoassignments']:
gapi_cloudidentity_inboundsso.print_show_assignments('show')
elif argument in ['sakey', 'sakeys']: elif argument in ['sakey', 'sakeys']:
doShowServiceAccountKeys() doShowServiceAccountKeys()
elif argument in ['browsertoken', 'browsertokens']: elif argument in ['browsertoken', 'browsertokens']:

View File

@@ -1,5 +1,6 @@
"""Methods related to Cloud Identity Inbound (Google as SP) SAML SSO""" """Methods related to Cloud Identity Inbound (Google as SP) SAML SSO"""
from datetime import datetime from datetime import datetime
import re
import sys import sys
import dateutil.parser import dateutil.parser
@@ -11,6 +12,7 @@ from gam import controlflow
from gam import display from gam import display
from gam import fileutils from gam import fileutils
from gam import gapi from gam import gapi
from gam import utils
from gam.gapi import errors as gapi_errors from gam.gapi import errors as gapi_errors
from gam.gapi import cloudidentity as gapi_cloudidentity from gam.gapi import cloudidentity as gapi_cloudidentity
from gam.gapi import directory as gapi_directory from gam.gapi import directory as gapi_directory
@@ -91,6 +93,41 @@ def profile_displayname_to_name(displayName, ci=None):
controlflow.system_error_exit(3, err_text) controlflow.system_error_exit(3, err_text)
'''get an assignment based on target'''
def assignment_by_target(target, ci=None):
if not ci:
ci = build()
group_pattern = r'^groups/[^/]+$'
ou_pattern = r'^orgUnits/[^/]+$'
if re.match(group_pattern, target):
target_type = 'targetGroup'
elif re.match(ou_pattern, target):
target_type = 'targetOrgUnit'
elif target.lower().startswith('group:'):
target_type = 'targetGroup'
group_email = target[6:]
target = gapi_cloudidentity_groups.group_email_to_id(
ci,
group_email)
elif target.lower().startswith('orgunit:'):
target_type = 'targetOrgUnit'
ou_name = target[8:]
target = get_orgunit_id(ou_name)
else:
controlflow.system_error_exit(3, 'assignments should be prefixed with group: or orgunit:')
customer = get_sso_customer()
_filter = f'customer=="{customer}"'
assignments = gapi.get_all_pages(ci.inboundSsoAssignments(),
'list',
'inboundSsoAssignments',
filter=_filter,
)
for assignment in assignments:
if target_type in assignment and assignment[target_type] == target:
return assignment
controlflow.system_error_exit(3, f'No SSO profile assigned to group {target}')
'''gam create inboundssoprofile''' '''gam create inboundssoprofile'''
def create_profile(): def create_profile():
ci = build() ci = build()
@@ -104,18 +141,42 @@ def create_profile():
'''gam print inboundssoprofiles''' '''gam print inboundssoprofiles'''
def print_profiles(): def print_show_profiles(action='print'):
customer = get_sso_customer() customer = get_sso_customer()
_filter = f'customer=="{customer}"' _filter = f'customer=="{customer}"'
ci = build() ci = build()
todrive = False
i = 3
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'todrive':
todrive = True
i += 1
else:
controlflow.invalid_argument_exit(myarg, 'gam print inboundssoprofiles')
profiles = gapi.get_all_pages(ci.inboundSamlSsoProfiles(), profiles = gapi.get_all_pages(ci.inboundSamlSsoProfiles(),
'list', 'list',
'inboundSamlSsoProfiles', 'inboundSamlSsoProfiles',
filter=_filter, filter=_filter,
) )
for profile in profiles: if action == 'show':
display.print_json(profile) for profile in profiles:
print() display.print_json(profile)
print()
elif action == 'print':
csv_rows = []
titles = []
for profile in profiles:
row = utils.flatten_json(profile)
for item in row:
if item not in titles:
titles.append(item)
csv_rows.append(row)
display.write_csv_file(csv_rows,
titles,
'Inbound SSO Profiles',
todrive)
'''gam update inboundssoprofile''' '''gam update inboundssoprofile'''
@@ -134,16 +195,20 @@ def update_profile():
'''gam info inboundssoprofile''' '''gam info inboundssoprofile'''
def info_profile(): def info_profile(return_only=False, displayName=None, ci=None):
ci = build() if not ci:
name = profile_displayname_to_name(sys.argv[3], ci) ci = build()
if not displayName:
displayName = sys.argv[3]
name = profile_displayname_to_name(displayName, ci)
result = gapi.call(ci.inboundSamlSsoProfiles(), result = gapi.call(ci.inboundSamlSsoProfiles(),
'get', 'get',
name=name, name=name,
) )
if return_only:
return result
display.print_json(result) display.print_json(result)
'''gam delete inboundssoprofile''' '''gam delete inboundssoprofile'''
def delete_profile(): def delete_profile():
ci = build() ci = build()
@@ -256,16 +321,20 @@ def delete_credentials(ci=None, name=None):
'''gam print inboundssocredentials''' '''gam print inboundssocredentials'''
def print_credentials(): def print_show_credentials(action='print'):
ci = build() ci = build()
todrive = False
i = 3 i = 3
profiles = [] profiles = []
while i > len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '') myarg = sys.argv[i].lower().replace('_', '')
if myarg in ['profile', 'profiles']: if myarg in ['profile', 'profiles']:
profiles = sys.argv[i+1].split(',') profiles = sys.argv[i+1].split(',')
for profile in profiles: for profile in profiles:
profile = profile_displayname_to_name(profile, ci) profile = profile_displayname_to_name(profile, ci)
elif myarg == 'todrive':
todrive = True
i += 1
else: else:
controlflow.invalid_argument_exit(myarg, 'gam print inboundssocredentials') controlflow.invalid_argument_exit(myarg, 'gam print inboundssocredentials')
if not profiles: if not profiles:
@@ -278,15 +347,31 @@ def print_credentials():
filter=_filter, filter=_filter,
) )
profiles = [p['name'] for p in profiles] profiles = [p['name'] for p in profiles]
if action == 'print':
titles = []
csv_rows = []
credentials = []
for profile in profiles: for profile in profiles:
credentials = gapi.get_all_pages(ci.inboundSamlSsoProfiles().idpCredentials(), results = gapi.get_all_pages(ci.inboundSamlSsoProfiles().idpCredentials(),
'list', 'list',
'idpCredentials', 'idpCredentials',
parent=profile) parent=profile)
credentials.extend(results)
if action == 'show':
for c in credentials: for c in credentials:
display.print_json(c) display.print_json(c)
print() print()
elif action == 'print':
for c in credentials:
csv_row = utils.flatten_json(c)
for item in csv_row:
if item not in titles:
titles.append(item)
csv_rows.append(csv_row)
display.write_csv_file(csv_rows,
titles,
'Inbound SSO Credentials',
todrive)
'''parse command for create/update inboundssoassignment''' '''parse command for create/update inboundssoassignment'''
def parse_assignment(body, i, ci): def parse_assignment(body, i, ci):
@@ -347,7 +432,7 @@ def create_assignment():
'''gam update inboundssoassignment''' '''gam update inboundssoassignment'''
def update_assignment(): def update_assignment():
ci = build() ci = build()
name = sys.argv[3] name = assignment_target_to_name(sys.argv[3], ci)
body = {} body = {}
body = parse_assignment(body, 4, ci) body = parse_assignment(body, 4, ci)
updateMask = ','.join(list(body.keys())) updateMask = ','.join(list(body.keys()))
@@ -360,11 +445,32 @@ def update_assignment():
display.print_json(result) display.print_json(result)
'''gam info inboundssoassignment'''
def info_assignment():
ci = build()
assignment = assignment_by_target(sys.argv[3], ci)
profile = assignment.get('samlSsoInfo', {}).get('inboundSamlSsoProfile')
if profile:
assignment['samlSsoInfo']['inboundSamlSsoProfile'] = info_profile(return_only=True,
displayName=f'id:{profile}',
ci=ci)
display.print_json(assignment)
'''gam print inboundssoassignments''' '''gam print inboundssoassignments'''
def print_assignments(): def print_show_assignments(action='print'):
ci = build() ci = build()
customer = get_sso_customer() customer = get_sso_customer()
_filter = f'customer=="{customer}"' _filter = f'customer=="{customer}"'
todrive = False
i = 3
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'todrive':
todrive = True
i += 1
else:
controlflow.invalid_argument_exit(myarg, 'gam print inboundssoassignments')
assignments = gapi.get_all_pages(ci.inboundSsoAssignments(), assignments = gapi.get_all_pages(ci.inboundSsoAssignments(),
'list', 'list',
'inboundSsoAssignments', 'inboundSsoAssignments',
@@ -379,6 +485,20 @@ def print_assignments():
ou_id = ou_id.split('/')[1] ou_id = ou_id.split('/')[1]
ou_id = f'id:{ou_id}' ou_id = f'id:{ou_id}'
assignment['orgUnit'] = gapi_directory_orgunits.orgunit_from_orgunitid(ou_id, cd) assignment['orgUnit'] = gapi_directory_orgunits.orgunit_from_orgunitid(ou_id, cd)
display.print_json(assignment) if action == 'show':
print() for assignment in assignments:
display.print_json(assignment)
print()
elif action == 'print':
titles = []
csv_rows = []
for assignment in assignments:
csv_row = utils.flatten_json(assignment)
for item in csv_row:
if item not in titles:
titles.append(item)
csv_rows.append(csv_row)
display.write_csv_file(csv_rows,
titles,
'Inbound SSO Assignments',
todrive)

View File

@@ -2,6 +2,7 @@ import sys
from time import sleep from time import sleep
import gam import gam
from gam import controlflow
from gam import display from gam import display
from gam import gapi from gam import gapi
from gam.gapi import directory as gapi_directory from gam.gapi import directory as gapi_directory
@@ -18,7 +19,7 @@ def delete():
userKey=user_email, userKey=user_email,
throw_reasons=[gapi_errors.ErrorReason.CONDITION_NOT_MET]) throw_reasons=[gapi_errors.ErrorReason.CONDITION_NOT_MET])
except gam.gapi.errors.GapiConditionNotMetError as err: except gam.gapi.errors.GapiConditionNotMetError as err:
display.print_error( controlflow.system_error_exit(3,
f'{err} The user {user_email} may be (or have recently been) on Google Vault Hold and thus not eligible for deletion. You can check holds with "gam user <email> show vaultholds".' f'{err} The user {user_email} may be (or have recently been) on Google Vault Hold and thus not eligible for deletion. You can check holds with "gam user <email> show vaultholds".'
) )