mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-03 12:21:35 +00:00
@@ -4282,19 +4282,19 @@ gam show policies
|
|||||||
<SSOProfileItem> ::= <SSOProfileDisplayName>|<SSOProfileName>
|
<SSOProfileItem> ::= <SSOProfileDisplayName>|<SSOProfileName>
|
||||||
<SSOProfileItemList> ::= "<SSOProfileItem>(,<SSOProfileItem>)*"
|
<SSOProfileItemList> ::= "<SSOProfileItem>(,<SSOProfileItem>)*"
|
||||||
|
|
||||||
gam create inboundssoprofile [name <SSOProfileDisplayName>]
|
gam create inboundssoprofile [saml|oidc] [name <SSOProfileDisplayName>]
|
||||||
[entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
[entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
||||||
[returnnameonly]
|
[returnnameonly]
|
||||||
gam update inboundssoprofile <SSOProfileItem>
|
gam update inboundssoprofile [saml|oidc] <SSOProfileItem>
|
||||||
[entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
[entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
||||||
[returnnameonly]
|
[returnnameonly]
|
||||||
gam delete inboundssoprofile <SSOProfileItem>
|
gam delete inboundssoprofile [saml|oidc] <SSOProfileItem>
|
||||||
|
|
||||||
gam info inboundssoprofile <SSOProfileItem>
|
gam info inboundssoprofile [all|saml|oidc] <SSOProfileItem>
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam show inboundssoprofiles
|
gam show inboundssoprofiles [all|saml|oidc]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam print inboundssoprofiles [todrive <ToDriveAttribute>*]
|
gam print inboundssoprofiles [all|saml|oidc] [todrive <ToDriveAttribute>*]
|
||||||
[[formatjson [quotechar <Character>]]
|
[[formatjson [quotechar <Character>]]
|
||||||
|
|
||||||
<SSOCredentialsName> ::= [id:]inboundSamlSsoProfiles/<String>/idpCredentials/<String>
|
<SSOCredentialsName> ::= [id:]inboundSamlSsoProfiles/<String>/idpCredentials/<String>
|
||||||
@@ -4318,10 +4318,14 @@ gam print inboundssocredentials [profile|profiles <SSOProfileItemList>]
|
|||||||
orgunits/<String> |
|
orgunits/<String> |
|
||||||
orgunit:<OrgUnitPath>
|
orgunit:<OrgUnitPath>
|
||||||
|
|
||||||
gam create inboundssoassignment (group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)
|
gam create inboundssoassignment
|
||||||
(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)(mode domain_wide_saml_if_enabled) [neverredirect]
|
(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)
|
||||||
gam update inboundssoassignment [(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)]
|
(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)|(mode oidc_sso profile <SSOProfileName>}|(mode domain_wide_saml_if_enabled)
|
||||||
[(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)(mode domain_wide_saml_if_enabled)] [neverredirect]
|
[neverredirect]
|
||||||
|
gam update inboundssoassignment <SSOAssignmentName>
|
||||||
|
[(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)]
|
||||||
|
(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)|(mode oidc_sso profile <SSOProfileName>}|(mode domain_wide_saml_if_enabled)
|
||||||
|
[neverredirect]
|
||||||
gam delete inboundssoassignment <SSOAssignmentSelector>
|
gam delete inboundssoassignment <SSOAssignmentSelector>
|
||||||
|
|
||||||
gam info inboundssoassignment <SSOAssignmentSelector>
|
gam info inboundssoassignment <SSOAssignmentSelector>
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
7.10.05
|
||||||
|
|
||||||
|
Added support for Inbound SSO OIDC profiles.
|
||||||
|
|
||||||
|
Currently, if you enter `gam select <SectionName>` and nothing else on the command line,
|
||||||
|
GAM performs no action. Now, it will be treated as if you entered:
|
||||||
|
`gam select <SectionName> save`
|
||||||
|
|
||||||
7.18.04
|
7.18.04
|
||||||
|
|
||||||
Added commands to display/manage Alert Center Pub/Sub notifications.
|
Added commands to display/manage Alert Center Pub/Sub notifications.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
||||||
__version__ = '7.18.04'
|
__version__ = '7.18.05'
|
||||||
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
#pylint: disable=wrong-import-position
|
#pylint: disable=wrong-import-position
|
||||||
@@ -3952,6 +3952,12 @@ def SetGlobalVariables():
|
|||||||
if checkArgumentPresent(Cmd.SELECT_CMD):
|
if checkArgumentPresent(Cmd.SELECT_CMD):
|
||||||
sectionName = _selectSection()
|
sectionName = _selectSection()
|
||||||
GM.Globals[GM.SECTION] = sectionName # Save section for inner gams
|
GM.Globals[GM.SECTION] = sectionName # Save section for inner gams
|
||||||
|
# If command line is simply: gam select <SectionName>
|
||||||
|
# assume save
|
||||||
|
if not Cmd.ArgumentsRemaining():
|
||||||
|
GM.Globals[GM.PARSER].set(configparser.DEFAULTSECT, GC.SECTION, sectionName)
|
||||||
|
_writeGamCfgFile(GM.Globals[GM.PARSER], GM.Globals[GM.GAM_CFG_FILE], Act.SAVE)
|
||||||
|
else:
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
if checkArgumentPresent('save'):
|
if checkArgumentPresent('save'):
|
||||||
GM.Globals[GM.PARSER].set(configparser.DEFAULTSECT, GC.SECTION, sectionName)
|
GM.Globals[GM.PARSER].set(configparser.DEFAULTSECT, GC.SECTION, sectionName)
|
||||||
@@ -11482,13 +11488,14 @@ def _createOauth2serviceJSON(httpObj, projectInfo, svcAcctInfo, create_key=True)
|
|||||||
iam = getAPIService(API.IAM, httpObj)
|
iam = getAPIService(API.IAM, httpObj)
|
||||||
try:
|
try:
|
||||||
service_account = callGAPI(iam.projects().serviceAccounts(), 'create',
|
service_account = callGAPI(iam.projects().serviceAccounts(), 'create',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED, GAPI.ALREADY_EXISTS],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.NOT_FOUND,
|
||||||
|
GAPI.PERMISSION_DENIED, GAPI.ALREADY_EXISTS],
|
||||||
name=f'projects/{projectInfo["projectId"]}',
|
name=f'projects/{projectInfo["projectId"]}',
|
||||||
body={'accountId': svcAcctInfo['name'],
|
body={'accountId': svcAcctInfo['name'],
|
||||||
'serviceAccount': {'displayName': svcAcctInfo['displayName'],
|
'serviceAccount': {'displayName': svcAcctInfo['displayName'],
|
||||||
'description': svcAcctInfo['description']}})
|
'description': svcAcctInfo['description']}})
|
||||||
entityActionPerformed([Ent.PROJECT, projectInfo['projectId'], Ent.SVCACCT, service_account['name'].rsplit('/', 1)[-1]])
|
entityActionPerformed([Ent.PROJECT, projectInfo['projectId'], Ent.SVCACCT, service_account['name'].rsplit('/', 1)[-1]])
|
||||||
except (GAPI.notFound, GAPI.permissionDenied) as e:
|
except (GAPI.failedPrecondition, GAPI.notFound, GAPI.permissionDenied) as e:
|
||||||
entityActionFailedWarning([Ent.PROJECT, projectInfo['projectId']], str(e))
|
entityActionFailedWarning([Ent.PROJECT, projectInfo['projectId']], str(e))
|
||||||
return False
|
return False
|
||||||
except GAPI.alreadyExists as e:
|
except GAPI.alreadyExists as e:
|
||||||
@@ -46393,9 +46400,30 @@ def checkCIUserIsInvitable(users):
|
|||||||
return
|
return
|
||||||
csvPF.writeCSVfile('Invitable Users')
|
csvPF.writeCSVfile('Invitable Users')
|
||||||
|
|
||||||
|
INBOUNDSSO_INPUT_MODE_CHOICE_MAP = {
|
||||||
|
'saml': 'saml',
|
||||||
|
'samlsso': 'saml',
|
||||||
|
'oidc': 'oidc',
|
||||||
|
'oidcsso': 'oidc',
|
||||||
|
}
|
||||||
|
|
||||||
|
INBOUNDSSO_OUTPUT_MODE_CHOICE_MAP = {
|
||||||
|
'all': 'all',
|
||||||
|
'saml': 'saml',
|
||||||
|
'samlsso': 'saml',
|
||||||
|
'oidc': 'oidc',
|
||||||
|
'oidcsso': 'oidc',
|
||||||
|
}
|
||||||
|
|
||||||
|
INBOUNDSSO_ALL_SAML = {'all', 'saml'}
|
||||||
|
INBOUNDSSO_ALL_OIDC = {'all', 'oidc'}
|
||||||
|
|
||||||
INBOUNDSSO_MODE_CHOICE_MAP = {
|
INBOUNDSSO_MODE_CHOICE_MAP = {
|
||||||
'ssooff': 'SSO_OFF',
|
'ssooff': 'SSO_OFF',
|
||||||
|
'saml': 'SAML_SSO',
|
||||||
'samlsso': 'SAML_SSO',
|
'samlsso': 'SAML_SSO',
|
||||||
|
'oidc': 'OIDC_SSO',
|
||||||
|
'oidcsso': 'OIDC_SSO',
|
||||||
'domainwidesamlifenabled': 'DOMAIN_WIDE_SAML_IF_ENABLED'
|
'domainwidesamlifenabled': 'DOMAIN_WIDE_SAML_IF_ENABLED'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46405,29 +46433,49 @@ def getCIOrgunitID(cd, orgunit):
|
|||||||
ou_id = ou_id[3:]
|
ou_id = ou_id[3:]
|
||||||
return f'orgUnits/{ou_id}'
|
return f'orgUnits/{ou_id}'
|
||||||
|
|
||||||
def _getInboundSSOProfiles(ci):
|
def _getInboundSSOProfiles(ci, mode):
|
||||||
customer = normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID])
|
customer = normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID])
|
||||||
|
profiles = []
|
||||||
|
if mode in INBOUNDSSO_ALL_SAML:
|
||||||
try:
|
try:
|
||||||
return callGAPIpages(ci.inboundSamlSsoProfiles(), 'list', 'inboundSamlSsoProfiles',
|
profiles.extend(callGAPIpages(ci.inboundSamlSsoProfiles(), 'list', 'inboundSamlSsoProfiles',
|
||||||
throwReasons=GAPI.CISSO_LIST_THROW_REASONS,
|
throwReasons=GAPI.CISSO_LIST_THROW_REASONS,
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
bailOnInternalError=True,
|
bailOnInternalError=True,
|
||||||
filter=f'customer=="{customer}"')
|
filter=f'customer=="{customer}"'))
|
||||||
except (GAPI.notFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
except (GAPI.notFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
||||||
GAPI.forbidden, GAPI.badRequest, GAPI.invalid,
|
GAPI.forbidden, GAPI.badRequest, GAPI.invalid,
|
||||||
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedWarning([Ent.INBOUND_SSO_PROFILE, customer], str(e))
|
entityActionFailedWarning([Ent.INBOUND_SSO_PROFILE, customer], str(e))
|
||||||
return []
|
if mode in INBOUNDSSO_ALL_OIDC:
|
||||||
|
try:
|
||||||
|
profiles.extend(callGAPIpages(ci.inboundOidcSsoProfiles(), 'list', 'inboundOidcSsoProfiles',
|
||||||
|
throwReasons=GAPI.CISSO_LIST_THROW_REASONS,
|
||||||
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
|
bailOnInternalError=True,
|
||||||
|
filter=f'customer=="{customer}"'))
|
||||||
|
except (GAPI.notFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
||||||
|
GAPI.forbidden, GAPI.badRequest, GAPI.invalid,
|
||||||
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
|
entityActionFailedWarning([Ent.INBOUND_SSO_PROFILE, customer], str(e))
|
||||||
|
return profiles
|
||||||
|
|
||||||
def _convertInboundSSOProfileDisplaynameToName(ci=None, displayName=''):
|
def _convertInboundSSOProfileDisplaynameToName(ci, mode, displayName='',
|
||||||
|
entityType=Ent.INBOUND_SSO_PROFILE):
|
||||||
if displayName.lower().startswith('id:') or displayName.lower().startswith('uid:'):
|
if displayName.lower().startswith('id:') or displayName.lower().startswith('uid:'):
|
||||||
displayName = displayName.split(':', 1)[1]
|
displayName = displayName.split(':', 1)[1]
|
||||||
|
if mode == 'all':
|
||||||
|
if not (displayName.startswith('inboundSamlSsoProfiles/') and
|
||||||
|
displayName.startswith('inboundOidcSsoProfiles/')):
|
||||||
|
displayName = f'inboundSamlSsoProfiles/{displayName}'
|
||||||
|
elif mode == 'saml':
|
||||||
if not displayName.startswith('inboundSamlSsoProfiles/'):
|
if not displayName.startswith('inboundSamlSsoProfiles/'):
|
||||||
displayName = f'inboundSamlSsoProfiles/{displayName}'
|
displayName = f'inboundSamlSsoProfiles/{displayName}'
|
||||||
|
else:
|
||||||
|
if not displayName.startswith('inboundOidcSsoProfiles/'):
|
||||||
|
displayName = f'inboundOidcSsoProfiles/{displayName}'
|
||||||
return displayName
|
return displayName
|
||||||
if not ci:
|
profiles = _getInboundSSOProfiles(ci, mode)
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
||||||
profiles = _getInboundSSOProfiles(ci)
|
|
||||||
matches = []
|
matches = []
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
if displayName.lower() == profile.get('displayName', '').lower():
|
if displayName.lower() == profile.get('displayName', '').lower():
|
||||||
@@ -46435,14 +46483,17 @@ def _convertInboundSSOProfileDisplaynameToName(ci=None, displayName=''):
|
|||||||
if len(matches) == 1:
|
if len(matches) == 1:
|
||||||
return matches[0]['name']
|
return matches[0]['name']
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
usageErrorExit(Msg.NO_SSO_PROFILE_MATCHES.format(displayName))
|
errMsg = Msg.NO_SSO_PROFILE_MATCHES.format(displayName)
|
||||||
|
else:
|
||||||
errMsg = Msg.MULTIPLE_SSO_PROFILES_MATCH.format(displayName)
|
errMsg = Msg.MULTIPLE_SSO_PROFILES_MATCH.format(displayName)
|
||||||
for m in matches:
|
for m in matches:
|
||||||
errMsg += f' {m["name"]} {m["displayName"]}\n'
|
errMsg += f' {m["name"]} {m["displayName"]}\n'
|
||||||
usageErrorExit(errMsg)
|
entityActionFailedWarning([entityType, None], errMsg)
|
||||||
|
return None
|
||||||
|
|
||||||
def _getInboundSSOProfileArguments(body):
|
def _getInboundSSOProfileArguments(body, mode):
|
||||||
returnNameOnly = False
|
returnNameOnly = False
|
||||||
|
if mode == 'saml':
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if myarg == 'name':
|
if myarg == 'name':
|
||||||
@@ -46459,6 +46510,23 @@ def _getInboundSSOProfileArguments(body):
|
|||||||
returnNameOnly = True
|
returnNameOnly = True
|
||||||
else:
|
else:
|
||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
|
else:
|
||||||
|
while Cmd.ArgumentsRemaining():
|
||||||
|
myarg = getArgument()
|
||||||
|
if myarg == 'name':
|
||||||
|
body['displayName'] = getString(Cmd.OB_STRING)
|
||||||
|
elif myarg == 'issueruri':
|
||||||
|
body.setdefault('idpConfig', {})['issuerUri'] = getString(Cmd.OB_STRING)
|
||||||
|
elif myarg == 'changepasswordurl':
|
||||||
|
body.setdefault('idpConfig', {})['changePasswordUri'] = getString(Cmd.OB_STRING)
|
||||||
|
elif myarg == 'clientid':
|
||||||
|
body.setdefault('rpConfig', {})['clientId'] = getString(Cmd.OB_STRING)
|
||||||
|
elif myarg == 'clientsecret':
|
||||||
|
body.setdefault('rpConfig', {})['clientSecret'] = getString(Cmd.OB_STRING)
|
||||||
|
elif myarg == 'returnnameonly':
|
||||||
|
returnNameOnly = True
|
||||||
|
else:
|
||||||
|
unknownArgumentExit()
|
||||||
return (returnNameOnly, body)
|
return (returnNameOnly, body)
|
||||||
|
|
||||||
def _showInboundSSOProfile(profile, FJQC, i=0, count=0):
|
def _showInboundSSOProfile(profile, FJQC, i=0, count=0):
|
||||||
@@ -46489,18 +46557,24 @@ def _processInboundSSOProfileResult(result, returnNameOnly, kvlist, function):
|
|||||||
else:
|
else:
|
||||||
writeStdout('inProgress\n')
|
writeStdout('inProgress\n')
|
||||||
|
|
||||||
# gam create inboundssoprofile [name <SSOProfileName>]
|
def _getInboundSSOModeService(ci):
|
||||||
|
mode = getChoice(INBOUNDSSO_INPUT_MODE_CHOICE_MAP, defaultChoice='saml', mapChoice=True)
|
||||||
|
service = ci.inboundSamlSsoProfiles() if mode == 'saml' else ci.inboundOidcSsoProfiles()
|
||||||
|
return (mode, service)
|
||||||
|
|
||||||
|
# gam create inboundssoprofile [saml|oidc] [name <SSOProfileName>]
|
||||||
# [entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
# [entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
||||||
# [returnnameonly]
|
# [returnnameonly]
|
||||||
def doCreateInboundSSOProfile():
|
def doCreateInboundSSOProfile():
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
|
mode, service = _getInboundSSOModeService(ci)
|
||||||
body = {'customer': normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID]),
|
body = {'customer': normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID]),
|
||||||
'displayName': 'SSO Profile'
|
'displayName': 'SSO Profile'
|
||||||
}
|
}
|
||||||
returnNameOnly, body = _getInboundSSOProfileArguments(body)
|
returnNameOnly, body = _getInboundSSOProfileArguments(body, mode)
|
||||||
kvlist = [Ent.INBOUND_SSO_PROFILE, body['displayName']]
|
kvlist = [Ent.INBOUND_SSO_PROFILE, body['displayName']]
|
||||||
try:
|
try:
|
||||||
result = callGAPI(ci.inboundSamlSsoProfiles(), 'create',
|
result = callGAPI(service, 'create',
|
||||||
throwReasons=GAPI.CISSO_CREATE_THROW_REASONS,
|
throwReasons=GAPI.CISSO_CREATE_THROW_REASONS,
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
bailOnInternalError=True,
|
bailOnInternalError=True,
|
||||||
@@ -46511,16 +46585,19 @@ def doCreateInboundSSOProfile():
|
|||||||
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedWarning(kvlist, str(e))
|
entityActionFailedWarning(kvlist, str(e))
|
||||||
|
|
||||||
# gam update inboundssoprofile <SSOProfileItem>
|
# gam update inboundssoprofile [saml|oidc] <SSOProfileItem>
|
||||||
# [entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
# [entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
||||||
# [returnnameonly]
|
# [returnnameonly]
|
||||||
def doUpdateInboundSSOProfile():
|
def doUpdateInboundSSOProfile():
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
name = _convertInboundSSOProfileDisplaynameToName(ci, getString(Cmd.OB_STRING))
|
mode, service = _getInboundSSOModeService(ci)
|
||||||
returnNameOnly, body = _getInboundSSOProfileArguments({})
|
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, getString(Cmd.OB_STRING))
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
|
returnNameOnly, body = _getInboundSSOProfileArguments({}, mode)
|
||||||
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
||||||
try:
|
try:
|
||||||
result = callGAPI(ci.inboundSamlSsoProfiles(), 'patch',
|
result = callGAPI(service, 'patch',
|
||||||
throwReasons=GAPI.CISSO_UPDATE_THROW_REASONS,
|
throwReasons=GAPI.CISSO_UPDATE_THROW_REASONS,
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
bailOnInternalError=True,
|
bailOnInternalError=True,
|
||||||
@@ -46533,14 +46610,17 @@ def doUpdateInboundSSOProfile():
|
|||||||
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedWarning(kvlist, str(e))
|
entityActionFailedWarning(kvlist, str(e))
|
||||||
|
|
||||||
# gam delete inboundssoprofile <SSOProfileItem>
|
# gam delete inboundssoprofile [saml|oidc] <SSOProfileItem>
|
||||||
def doDeleteInboundSSOProfile():
|
def doDeleteInboundSSOProfile():
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
name = _convertInboundSSOProfileDisplaynameToName(ci, getString(Cmd.OB_STRING))
|
mode, service = _getInboundSSOModeService(ci)
|
||||||
|
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, getString(Cmd.OB_STRING))
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
checkForExtraneousArguments()
|
checkForExtraneousArguments()
|
||||||
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
||||||
try:
|
try:
|
||||||
result = callGAPI(ci.inboundSamlSsoProfiles(), 'delete',
|
result = callGAPI(service, 'delete',
|
||||||
throwReasons=GAPI.CISSO_UPDATE_THROW_REASONS,
|
throwReasons=GAPI.CISSO_UPDATE_THROW_REASONS,
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
bailOnInternalError=True,
|
bailOnInternalError=True,
|
||||||
@@ -46553,8 +46633,10 @@ def doDeleteInboundSSOProfile():
|
|||||||
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedWarning(kvlist, str(e))
|
entityActionFailedWarning(kvlist, str(e))
|
||||||
|
|
||||||
def _getInboundSSOProfile(ci, name):
|
def _getInboundSSOProfileByName(ci, mode, name):
|
||||||
|
notFound = False
|
||||||
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
||||||
|
if mode in INBOUNDSSO_ALL_SAML:
|
||||||
try:
|
try:
|
||||||
return callGAPI(ci.inboundSamlSsoProfiles(), 'get',
|
return callGAPI(ci.inboundSamlSsoProfiles(), 'get',
|
||||||
throwReasons=GAPI.CISSO_GET_THROW_REASONS,
|
throwReasons=GAPI.CISSO_GET_THROW_REASONS,
|
||||||
@@ -46562,24 +46644,43 @@ def _getInboundSSOProfile(ci, name):
|
|||||||
bailOnInternalError=True,
|
bailOnInternalError=True,
|
||||||
name=name)
|
name=name)
|
||||||
except GAPI.notFound:
|
except GAPI.notFound:
|
||||||
entityActionFailedWarning(kvlist, Msg.DOES_NOT_EXIST)
|
notFound = True
|
||||||
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
||||||
GAPI.badRequest, GAPI.invalid, GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
GAPI.badRequest, GAPI.invalid, GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedWarning(kvlist, str(e))
|
entityActionFailedWarning(kvlist, str(e))
|
||||||
|
if mode in INBOUNDSSO_ALL_OIDC:
|
||||||
|
try:
|
||||||
|
return callGAPI(ci.inboundOidcSsoProfiles(), 'get',
|
||||||
|
throwReasons=GAPI.CISSO_GET_THROW_REASONS,
|
||||||
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
|
bailOnInternalError=True,
|
||||||
|
name=name)
|
||||||
|
except GAPI.notFound:
|
||||||
|
notFound = True
|
||||||
|
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
||||||
|
GAPI.badRequest, GAPI.invalid, GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
|
entityActionFailedWarning(kvlist, str(e))
|
||||||
|
if notFound:
|
||||||
|
entityActionFailedWarning(kvlist, Msg.DOES_NOT_EXIST)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# gam info inboundssoprofile <SSOProfileItem> [formatjson]
|
# gam info inboundssoprofile [all|saml|oidc] <SSOProfileItem> [formatjson]
|
||||||
def doInfoInboundSSOProfile():
|
def doInfoInboundSSOProfile():
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
name = _convertInboundSSOProfileDisplaynameToName(ci, getString(Cmd.OB_STRING))
|
mode = getChoice(INBOUNDSSO_OUTPUT_MODE_CHOICE_MAP, defaultChoice='all', mapChoice=True)
|
||||||
|
name = getString(Cmd.OB_STRING)
|
||||||
FJQC = FormatJSONQuoteChar(formatJSONOnly=True)
|
FJQC = FormatJSONQuoteChar(formatJSONOnly=True)
|
||||||
profile = _getInboundSSOProfile(ci, name)
|
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, name)
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
|
mode = 'saml' if name.startswith('inboundSamlSsoProfiles/') else 'oidc'
|
||||||
|
profile = _getInboundSSOProfileByName(ci, mode, name)
|
||||||
if profile:
|
if profile:
|
||||||
_showInboundSSOProfile(profile, FJQC)
|
_showInboundSSOProfile(profile, FJQC)
|
||||||
|
|
||||||
# gam show inboundssoprofile
|
# gam show inboundssoprofile [all|saml|oidc]
|
||||||
# [formatjson]
|
# [formatjson]
|
||||||
# gam print inboundssoprofile [todrive <ToDriveAttribute>*]
|
# gam print inboundssoprofile [all|saml|oidc] [todrive <ToDriveAttribute>*]
|
||||||
# [[formatjson [quotechar <Character>]]
|
# [[formatjson [quotechar <Character>]]
|
||||||
def doPrintShowInboundSSOProfiles():
|
def doPrintShowInboundSSOProfiles():
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
@@ -46587,6 +46688,7 @@ def doPrintShowInboundSSOProfiles():
|
|||||||
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
|
||||||
FJQC = FormatJSONQuoteChar(csvPF)
|
FJQC = FormatJSONQuoteChar(csvPF)
|
||||||
cfilter = f'customer=="{customer}"'
|
cfilter = f'customer=="{customer}"'
|
||||||
|
mode = getChoice(INBOUNDSSO_OUTPUT_MODE_CHOICE_MAP, defaultChoice='all', mapChoice=True)
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
@@ -46595,7 +46697,7 @@ def doPrintShowInboundSSOProfiles():
|
|||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
if csvPF:
|
if csvPF:
|
||||||
printGettingAllAccountEntities(Ent.INBOUND_SSO_PROFILE, cfilter)
|
printGettingAllAccountEntities(Ent.INBOUND_SSO_PROFILE, cfilter)
|
||||||
profiles = _getInboundSSOProfiles(ci)
|
profiles = _getInboundSSOProfiles(ci, mode)
|
||||||
if not csvPF:
|
if not csvPF:
|
||||||
count = len(profiles)
|
count = len(profiles)
|
||||||
if not FJQC.formatJSON:
|
if not FJQC.formatJSON:
|
||||||
@@ -46665,6 +46767,7 @@ def _processInboundSSOCredentialsResult(result, kvlist, function):
|
|||||||
# (pemfile <FileName>)|(generatekey [keysize 1024|2048|4096]) [replaceolddest]
|
# (pemfile <FileName>)|(generatekey [keysize 1024|2048|4096]) [replaceolddest]
|
||||||
def doCreateInboundSSOCredential():
|
def doCreateInboundSSOCredential():
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
|
mode = 'saml'
|
||||||
profile = None
|
profile = None
|
||||||
generateKey = replaceOldest = False
|
generateKey = replaceOldest = False
|
||||||
keySize = 2048
|
keySize = 2048
|
||||||
@@ -46672,7 +46775,11 @@ def doCreateInboundSSOCredential():
|
|||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if myarg == 'profile':
|
if myarg == 'profile':
|
||||||
profile = _convertInboundSSOProfileDisplaynameToName(ci, getString(Cmd.OB_STRING))
|
profile = _convertInboundSSOProfileDisplaynameToName(ci, mode,
|
||||||
|
getString(Cmd.OB_STRING),
|
||||||
|
Ent.INBOUND_SSO_CREDENTIALS)
|
||||||
|
if not profile:
|
||||||
|
return
|
||||||
elif myarg == 'pemfile':
|
elif myarg == 'pemfile':
|
||||||
pemData = readFile(getString(Cmd.OB_FILE_NAME))
|
pemData = readFile(getString(Cmd.OB_FILE_NAME))
|
||||||
elif myarg == 'generatekey':
|
elif myarg == 'generatekey':
|
||||||
@@ -46776,15 +46883,24 @@ def doPrintShowInboundSSOCredentials():
|
|||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
|
||||||
FJQC = FormatJSONQuoteChar(csvPF)
|
FJQC = FormatJSONQuoteChar(csvPF)
|
||||||
|
mode = 'saml'
|
||||||
profiles = []
|
profiles = []
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if myarg in {'profile', 'profiles'}:
|
if myarg in {'profile', 'profiles'}:
|
||||||
profiles = [_convertInboundSSOProfileDisplaynameToName(ci, profile) for profile in getString(Cmd.OB_STRING_LIST).split(',')]
|
errors = 0
|
||||||
|
for profile in getEntityList(Cmd.OB_STRING_LIST, shlexSplit=True):
|
||||||
|
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, profile, Ent.INBOUND_SSO_CREDENTIALS)
|
||||||
|
if name:
|
||||||
|
profiles.append(name)
|
||||||
|
else:
|
||||||
|
errors += 1
|
||||||
|
if errors:
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
if not profiles:
|
if not profiles:
|
||||||
profiles = [p['name'] for p in _getInboundSSOProfiles(ci)]
|
profiles = [p['name'] for p in _getInboundSSOProfiles(ci, mode)]
|
||||||
count = len(profiles)
|
count = len(profiles)
|
||||||
i = 0
|
i = 0
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
@@ -46877,6 +46993,7 @@ def _getInboundSSOAssignmentByTarget(ci, cd, target):
|
|||||||
usageErrorExit(Msg.NO_SSO_PROFILE_ASSIGNED.format(targetType, target))
|
usageErrorExit(Msg.NO_SSO_PROFILE_ASSIGNED.format(targetType, target))
|
||||||
|
|
||||||
def _getInboundSSOAssignmentArguments(ci, cd, body):
|
def _getInboundSSOAssignmentArguments(ci, cd, body):
|
||||||
|
mode = None
|
||||||
rank = 0
|
rank = 0
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
@@ -46884,9 +47001,19 @@ def _getInboundSSOAssignmentArguments(ci, cd, body):
|
|||||||
rank = getInteger(minVal=1)
|
rank = getInteger(minVal=1)
|
||||||
elif myarg == 'mode':
|
elif myarg == 'mode':
|
||||||
body['ssoMode'] = getChoice(INBOUNDSSO_MODE_CHOICE_MAP, mapChoice=True)
|
body['ssoMode'] = getChoice(INBOUNDSSO_MODE_CHOICE_MAP, mapChoice=True)
|
||||||
elif myarg == 'profile':
|
if body['ssoMode'] == 'SAML_SSO':
|
||||||
body['samlSsoInfo'] = {'inboundSamlSsoProfile':
|
mode = 'saml'
|
||||||
_convertInboundSSOProfileDisplaynameToName(ci, getString(Cmd.OB_STRING))}
|
profile = 'inboundSamlSsoProfile'
|
||||||
|
elif body['ssoMode'] == 'OIDC_SSO':
|
||||||
|
mode = 'oidc'
|
||||||
|
profile = 'inboundOidcSsoProfile'
|
||||||
|
elif mode and myarg == 'profile':
|
||||||
|
name = _convertInboundSSOProfileDisplaynameToName(ci, mode,
|
||||||
|
getString(Cmd.OB_STRING),
|
||||||
|
Ent.INBOUND_SSO_ASSIGNMENT)
|
||||||
|
if not name:
|
||||||
|
return None
|
||||||
|
body['samlSsoInfo'] = {profile: name}
|
||||||
elif myarg == 'neverredirect':
|
elif myarg == 'neverredirect':
|
||||||
body['signInBehavior'] = {'redirectCondition': 'NEVER'}
|
body['signInBehavior'] = {'redirectCondition': 'NEVER'}
|
||||||
elif myarg == 'group':
|
elif myarg == 'group':
|
||||||
@@ -46897,7 +47024,7 @@ def _getInboundSSOAssignmentArguments(ci, cd, body):
|
|||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
if 'ssoMode' not in body:
|
if 'ssoMode' not in body:
|
||||||
missingArgumentExit('mode')
|
missingArgumentExit('mode')
|
||||||
if body['ssoMode'] == 'SAML_SSO' and 'samlSsoInfo' not in body:
|
if mode and 'samlSsoInfo' not in body:
|
||||||
missingArgumentExit('profile')
|
missingArgumentExit('profile')
|
||||||
if 'targetGroup' in body:
|
if 'targetGroup' in body:
|
||||||
if 'targetOrgUnit' in body:
|
if 'targetOrgUnit' in body:
|
||||||
@@ -46935,13 +47062,17 @@ def _processInboundSSOAssignmentResult(result, kvlist, ci, cd, function):
|
|||||||
else:
|
else:
|
||||||
entityActionPerformedMessage(kvlist, Msg.ACTION_IN_PROGRESS.format(f'{function} inboundssoassignment'))
|
entityActionPerformedMessage(kvlist, Msg.ACTION_IN_PROGRESS.format(f'{function} inboundssoassignment'))
|
||||||
|
|
||||||
# gam create inboundssoassignment (group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)
|
# gam create inboundssoassignment
|
||||||
# (mode sso_off)|(mode saml_sso profile <SSOProfileItem>)(mode domain_wide_saml_if_enabled) [neverredirect]
|
# (group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)
|
||||||
|
# (mode sso_off)|(mode saml_sso profile <SSOProfileItem>)|(mode oidc_sso profile <SSOProfileName>}|(mode domain_wide_saml_if_enabled)
|
||||||
|
# [neverredirect]
|
||||||
def doCreateInboundSSOAssignment():
|
def doCreateInboundSSOAssignment():
|
||||||
cd = buildGAPIObject(API.DIRECTORY)
|
cd = buildGAPIObject(API.DIRECTORY)
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
body = {'customer': normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID])}
|
body = {'customer': normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID])}
|
||||||
body = _getInboundSSOAssignmentArguments(ci, cd, body)
|
body = _getInboundSSOAssignmentArguments(ci, cd, body)
|
||||||
|
if not body:
|
||||||
|
return
|
||||||
kvlist = [Ent.INBOUND_SSO_ASSIGNMENT, body['customer']]
|
kvlist = [Ent.INBOUND_SSO_ASSIGNMENT, body['customer']]
|
||||||
try:
|
try:
|
||||||
result = callGAPI(ci.inboundSsoAssignments(), 'create',
|
result = callGAPI(ci.inboundSsoAssignments(), 'create',
|
||||||
@@ -46955,8 +47086,10 @@ def doCreateInboundSSOAssignment():
|
|||||||
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedWarning(kvlist, str(e))
|
entityActionFailedWarning(kvlist, str(e))
|
||||||
|
|
||||||
# gam update inboundssoassignment [(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)]
|
# gam update inboundssoassignment <SSOAssignmentName>
|
||||||
# [(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)(mode domain_wide_saml_if_enabled)] [neverredirect]
|
# [(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)]
|
||||||
|
# (mode sso_off)|(mode saml_sso profile <SSOProfileItem>)|(mode oidc_sso profile <SSOProfileName>}|(mode domain_wide_saml_if_enabled)
|
||||||
|
# [neverredirect]
|
||||||
def doUpdateInboundSSOAssignment():
|
def doUpdateInboundSSOAssignment():
|
||||||
cd = buildGAPIObject(API.DIRECTORY)
|
cd = buildGAPIObject(API.DIRECTORY)
|
||||||
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
||||||
@@ -47013,14 +47146,20 @@ def doInfoInboundSSOAssignment():
|
|||||||
return
|
return
|
||||||
name = assignment.get('samlSsoInfo', {}).get('inboundSamlSsoProfile')
|
name = assignment.get('samlSsoInfo', {}).get('inboundSamlSsoProfile')
|
||||||
if name:
|
if name:
|
||||||
profile = _getInboundSSOProfile(ci, name)
|
profile = _getInboundSSOProfileByName(ci, 'saml', name)
|
||||||
if profile:
|
if profile:
|
||||||
assignment['samlSsoInfo']['inboundSamlSsoProfile'] = profile
|
assignment['samlSsoInfo']['inboundSamlSsoProfile'] = profile
|
||||||
|
else:
|
||||||
|
name = assignment.get('oidcSsoInfo', {}).get('inboundOidcSsoProfile')
|
||||||
|
if name:
|
||||||
|
profile = _getInboundSSOProfileByName(ci, 'oidc', name)
|
||||||
|
if profile:
|
||||||
|
assignment['oidcSsoInfo']['inboundOidcSsoProfile'] = profile
|
||||||
_showInboundSSOAssignment(assignment, FJQC, ci, cd)
|
_showInboundSSOAssignment(assignment, FJQC, ci, cd)
|
||||||
|
|
||||||
# gam show inboundssoassignment
|
# gam show inboundssoassignments
|
||||||
# [formatjson]
|
# [formatjson]
|
||||||
# gam print inboundssoassignment [todrive <ToDriveAttribute>*]
|
# gam print inboundssoassignments [todrive <ToDriveAttribute>*]
|
||||||
# [[formatjson [quotechar <Character>]]
|
# [[formatjson [quotechar <Character>]]
|
||||||
def doPrintShowInboundSSOAssignments():
|
def doPrintShowInboundSSOAssignments():
|
||||||
cd = buildGAPIObject(API.DIRECTORY)
|
cd = buildGAPIObject(API.DIRECTORY)
|
||||||
|
|||||||
Reference in New Issue
Block a user