Clean up/standardize OU id/path handling (#748)

This commit is contained in:
Ross Scroggs
2018-07-04 10:17:51 -07:00
committed by Jay Lee
parent 74514b487d
commit 5a1ab0c168

View File

@@ -1959,21 +1959,11 @@ def doCreateAdmin():
if body[u'scopeType'] not in [u'CUSTOMER', u'ORG_UNIT']: if body[u'scopeType'] not in [u'CUSTOMER', u'ORG_UNIT']:
systemErrorExit(3, 'scope type must be customer or org_unit; got %s' % body[u'scopeType']) systemErrorExit(3, 'scope type must be customer or org_unit; got %s' % body[u'scopeType'])
if body[u'scopeType'] == u'ORG_UNIT': if body[u'scopeType'] == u'ORG_UNIT':
orgUnit = sys.argv[6] orgUnit, orgUnitId = getOrgUnitId(sys.argv[6], cd)
if orgUnit[:3] == u'id:': body[u'orgUnitId'] = orgUnitId[3:]
body[u'orgUnitId'] = orgUnit[3:] scope = u'ORG_UNIT {0}'.format(orgUnit)
elif orgUnit[:4] == u'uid:':
body[u'orgUnitId'] = orgUnit[4:]
else:
if orgUnit[0] == u'/':
orgUnit = orgUnit[1:]
body[u'orgUnitId'] = callGAPI(cd.orgunits(), u'get',
customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=orgUnit,
fields=u'orgUnitId')[u'orgUnitId'][3:]
if body[u'scopeType'] == u'CUSTOMER':
scope = u'customer'
else: else:
scope = orgUnit scope = u'CUSTOMER'
print u'Giving %s admin role %s for %s' % (user, role, scope) print u'Giving %s admin role %s for %s' % (user, role, scope)
callGAPI(cd.roleAssignments(), u'insert', callGAPI(cd.roleAssignments(), u'insert',
customer=GC_Values[GC_CUSTOMER_ID], body=body) customer=GC_Values[GC_CUSTOMER_ID], body=body)
@@ -5837,7 +5827,6 @@ def _showFilter(userFilter, j, jcount, labels):
print u' Forwarding Address: {0}'.format(userFilter[u'action'][u'forward']) print u' Forwarding Address: {0}'.format(userFilter[u'action'][u'forward'])
else: else:
print u' ERROR: No Filter actions' print u' ERROR: No Filter actions'
#
def addFilter(users, i): def addFilter(users, i):
body = {} body = {}
@@ -6607,9 +6596,7 @@ def getUserAttributes(i, cd, updateCmd=False):
body[u'agreedToTerms'] = getBoolean(sys.argv[i+1], myarg) body[u'agreedToTerms'] = getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
elif myarg in [u'org', u'ou']: elif myarg in [u'org', u'ou']:
body[u'orgUnitPath'] = sys.argv[i+1] body[u'orgUnitPath'] = getOrgUnitItem(sys.argv[i+1], pathOnly=True)
if body[u'orgUnitPath'][0] != u'/':
body[u'orgUnitPath'] = u'/%s' % body[u'orgUnitPath']
i += 2 i += 2
elif myarg in [u'language', u'languages']: elif myarg in [u'language', u'languages']:
i += 1 i += 1
@@ -7442,7 +7429,8 @@ def doCreateVaultHold():
accounts = sys.argv[i+1].split(u',') accounts = sys.argv[i+1].split(u',')
i += 2 i += 2
elif myarg in [u'orgunit', u'ou']: elif myarg in [u'orgunit', u'ou']:
body[u'orgUnit'] = {u'orgUnitId': doGetOrgInfo(name=sys.argv[i+1], return_attrib=u'orgUnitId')} _, orgUnitId = getOrgUnitId(sys.argv[i+1], None)
body[u'orgUnit'] = {u'orgUnitId': orgUnitId}
i += 2 i += 2
elif myarg == u'starttime': elif myarg == u'starttime':
start_time = getDateZeroTimeOrFullTime(sys.argv[i+1]) start_time = getDateZeroTimeOrFullTime(sys.argv[i+1])
@@ -7584,7 +7572,8 @@ def doUpdateVaultHold():
query = sys.argv[i+1] query = sys.argv[i+1]
i += 2 i += 2
elif myarg in [u'orgunit', u'ou']: elif myarg in [u'orgunit', u'ou']:
body[u'orgUnit'] = {u'orgUnitId': doGetOrgInfo(name=sys.argv[i+1], return_attrib=u'orgUnitId')} _, orgUnitId = getOrgUnitId(sys.argv[i+1], None)
body[u'orgUnit'] = {u'orgUnitId': orgUnitId}
i += 2 i += 2
elif myarg == u'starttime': elif myarg == u'starttime':
start_time = getDateZeroTimeOrFullTime(sys.argv[i+1]) start_time = getDateZeroTimeOrFullTime(sys.argv[i+1])
@@ -7814,18 +7803,17 @@ def doCreateAlias():
def doCreateOrg(): def doCreateOrg():
cd = buildGAPIObject(u'directory') cd = buildGAPIObject(u'directory')
body = {u'name': sys.argv[3]} name = getOrgUnitItem(sys.argv[3], pathOnly=True, absolutePath=False)
if body[u'name'][0] == u'/': parent = u''
body[u'name'] = body[u'name'][1:] body = {}
i = 4 i = 4
body[u'parentOrgUnitPath'] = u'/'
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower() myarg = sys.argv[i].lower()
if myarg == u'description': if myarg == u'description':
body[u'description'] = sys.argv[i+1].replace(u'\\n', u'\n') body[u'description'] = sys.argv[i+1].replace(u'\\n', u'\n')
i += 2 i += 2
elif myarg == u'parent': elif myarg == u'parent':
body[u'parentOrgUnitPath'] = sys.argv[i+1] parent = getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == u'noinherit': elif myarg == u'noinherit':
body[u'blockInheritance'] = True body[u'blockInheritance'] = True
@@ -7835,6 +7823,19 @@ def doCreateOrg():
i += 1 i += 1
else: else:
systemErrorExit(2, '%s is not a valid argument for "gam create org"' % sys.argv[i]) systemErrorExit(2, '%s is not a valid argument for "gam create org"' % sys.argv[i])
if parent.startswith(u'id:'):
parent = callGAPI(cd.orgunits(), u'get',
customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=parent, fields=u'orgUnitPath')[u'orgUnitPath']
if parent == u'/':
orgUnitPath = parent+name
else:
orgUnitPath = parent+u'/'+name
if orgUnitPath.count(u'/') > 1:
body[u'parentOrgUnitPath'], body[u'name'] = orgUnitPath.rsplit(u'/', 1)
else:
body[u'parentOrgUnitPath'] = u'/'
body[u'name'] = orgUnitPath[1:]
parent = body[u'parentOrgUnitPath']
callGAPI(cd.orgunits(), u'insert', customerId=GC_Values[GC_CUSTOMER_ID], body=body) callGAPI(cd.orgunits(), u'insert', customerId=GC_Values[GC_CUSTOMER_ID], body=body)
def _getBuildingAttributes(args, body={}): def _getBuildingAttributes(args, body={}):
@@ -8394,7 +8395,7 @@ def doUpdateCros():
update_body[u'annotatedAssetId'] = sys.argv[i+1] update_body[u'annotatedAssetId'] = sys.argv[i+1]
i += 2 i += 2
elif myarg in [u'ou', u'org']: elif myarg in [u'ou', u'org']:
orgUnitPath = sys.argv[i+1] orgUnitPath = getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == u'action': elif myarg == u'action':
action = sys.argv[i+1].lower().replace(u'_', u'').replace(u'-', u'') action = sys.argv[i+1].lower().replace(u'_', u'').replace(u'-', u'')
@@ -8471,7 +8472,7 @@ def doDeleteMobile():
def doUpdateOrg(): def doUpdateOrg():
cd = buildGAPIObject(u'directory') cd = buildGAPIObject(u'directory')
orgUnitPath = sys.argv[3] orgUnitPath = getOrgUnitItem(sys.argv[3])
if sys.argv[4].lower() in [u'move', u'add']: if sys.argv[4].lower() in [u'move', u'add']:
if sys.argv[5].lower() in usergroup_types: if sys.argv[5].lower() in usergroup_types:
users = getUsersToModify(entity_type=sys.argv[5].lower(), entity=sys.argv[6]) users = getUsersToModify(entity_type=sys.argv[5].lower(), entity=sys.argv[6])
@@ -8483,8 +8484,6 @@ def doUpdateOrg():
print u' moving %s devices to %s' % (len(move_body[u'deviceIds']), orgUnitPath) print u' moving %s devices to %s' % (len(move_body[u'deviceIds']), orgUnitPath)
callGAPI(cd.chromeosdevices(), u'moveDevicesToOu', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=orgUnitPath, body=move_body) callGAPI(cd.chromeosdevices(), u'moveDevicesToOu', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=orgUnitPath, body=move_body)
else: else:
if orgUnitPath != u'/' and orgUnitPath[0] != u'/': # we do want a / at the beginning for user updates
orgUnitPath = u'/%s' % orgUnitPath
current_user = 0 current_user = 0
user_count = len(users) user_count = len(users)
for user in users: for user in users:
@@ -8506,9 +8505,11 @@ def doUpdateOrg():
body[u'description'] = sys.argv[i+1].replace(u'\\n', u'\n') body[u'description'] = sys.argv[i+1].replace(u'\\n', u'\n')
i += 2 i += 2
elif myarg == u'parent': elif myarg == u'parent':
body[u'parentOrgUnitPath'] = sys.argv[i+1] parent = getOrgUnitItem(sys.argv[i+1])
if body[u'parentOrgUnitPath'][0] != u'/': if parent.startswith(u'id:'):
body[u'parentOrgUnitPath'] = u'/'+body[u'parentOrgUnitPath'] body[u'parentOrgUnitId'] = parent
else:
body[u'parentOrgUnitPath'] = parent
i += 2 i += 2
elif myarg == u'noinherit': elif myarg == u'noinherit':
body[u'blockInheritance'] = True body[u'blockInheritance'] = True
@@ -8518,9 +8519,7 @@ def doUpdateOrg():
i += 1 i += 1
else: else:
systemErrorExit(2, '%s is not a valid argument for "gam update org"' % sys.argv[i]) systemErrorExit(2, '%s is not a valid argument for "gam update org"' % sys.argv[i])
if orgUnitPath[0] == u'/': # we don't want a / at the beginning for OU updates callGAPI(cd.orgunits(), u'update', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(makeOrgUnitPathRelative(orgUnitPath)), body=body)
orgUnitPath = orgUnitPath[1:]
callGAPI(cd.orgunits(), u'update', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=orgUnitPath, body=body)
def doWhatIs(): def doWhatIs():
cd = buildGAPIObject(u'directory') cd = buildGAPIObject(u'directory')
@@ -9495,6 +9494,58 @@ def orgUnitPathQuery(path):
return u"orgUnitPath='{0}'".format(path.replace(u"'", u"\\'")) return u"orgUnitPath='{0}'".format(path.replace(u"'", u"\\'"))
return None return None
def makeOrgUnitPathAbsolute(path):
if path == u'/':
return path
if path.startswith(u'/'):
return path.rstrip(u'/')
if path.startswith(u'id:'):
return path
if path.startswith(u'uid:'):
return path[1:]
return u'/'+path.rstrip(u'/')
def makeOrgUnitPathRelative(path):
if path == u'/':
return path
if path.startswith(u'/'):
return path[1:].rstrip(u'/')
if path.startswith(u'id:'):
return path
if path.startswith(u'uid:'):
return path[1:]
return path.rstrip(u'/')
def encodeOrgUnitPath(path):
if path.find(u'+') == -1 and path.find(u'%') == -1:
return path
encpath = u''
for c in path:
if c == u'+':
encpath += u'%2B'
elif c == u'%':
encpath += u'%25'
else:
encpath += c
return encpath
def getOrgUnitItem(orgUnit, pathOnly=False, absolutePath=True):
if pathOnly and (orgUnit.startswith(u'id:') or orgUnit.startswith(u'uid:')):
systemErrorExit(2, '%s is not valid in this context' % orgUnit)
if absolutePath:
return makeOrgUnitPathAbsolute(orgUnit)
return makeOrgUnitPathRelative(orgUnit)
def getOrgUnitId(orgUnit, cd=None):
if cd is None:
cd = buildGAPIObject(u'directory')
orgUnit = getOrgUnitItem(orgUnit)
if orgUnit[:3] == u'id:':
return (orgUnit, orgUnit)
result = callGAPI(cd.orgunits(), u'get',
customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(makeOrgUnitPathRelative(orgUnit)), fields=u'orgUnitId')
return (orgUnit, result[u'orgUnitId'])
def getTopLevelOrgId(cd, orgUnitPath): def getTopLevelOrgId(cd, orgUnitPath):
try: try:
# create a temp org so we can learn what the top level org ID is (sigh) # create a temp org so we can learn what the top level org ID is (sigh)
@@ -9510,7 +9561,7 @@ def getTopLevelOrgId(cd, orgUnitPath):
def doGetOrgInfo(name=None, return_attrib=None): def doGetOrgInfo(name=None, return_attrib=None):
cd = buildGAPIObject(u'directory') cd = buildGAPIObject(u'directory')
if not name: if not name:
name = sys.argv[3] name = getOrgUnitItem(sys.argv[3])
get_users = True get_users = True
show_children = False show_children = False
i = 4 i = 4
@@ -9534,9 +9585,9 @@ def doGetOrgInfo(name=None, return_attrib=None):
topLevelOrgId = getTopLevelOrgId(cd, u'/') topLevelOrgId = getTopLevelOrgId(cd, u'/')
if topLevelOrgId: if topLevelOrgId:
name = topLevelOrgId name = topLevelOrgId
if len(name) > 1 and name[0] == u'/': else:
name = name[1:] name = makeOrgUnitPathRelative(name)
result = callGAPI(cd.orgunits(), u'get', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=name) result = callGAPI(cd.orgunits(), u'get', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(name))
if return_attrib: if return_attrib:
return result[return_attrib] return result[return_attrib]
print_json(None, result) print_json(None, result)
@@ -9774,7 +9825,7 @@ def doUndeleteUser():
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower() myarg = sys.argv[i].lower()
if myarg in [u'ou', u'org']: if myarg in [u'ou', u'org']:
orgUnit = sys.argv[i+1] orgUnit = makeOrgUnitPathAbsolute(sys.argv[i+1])
i += 2 i += 2
else: else:
systemErrorExit(2, '%s is not a valid argument for "gam undelete user"' % sys.argv[i]) systemErrorExit(2, '%s is not a valid argument for "gam undelete user"' % sys.argv[i])
@@ -9848,11 +9899,9 @@ def doDeleteResourceCalendar():
def doDeleteOrg(): def doDeleteOrg():
cd = buildGAPIObject(u'directory') cd = buildGAPIObject(u'directory')
name = sys.argv[3] name = getOrgUnitItem(sys.argv[3])
if name[0] == u'/':
name = name[1:]
print u"Deleting organization %s" % name print u"Deleting organization %s" % name
callGAPI(cd.orgunits(), u'delete', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=name) callGAPI(cd.orgunits(), u'delete', customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(makeOrgUnitPathRelative(name)))
# Send an email # Send an email
def send_email(msg_subj, msg_txt, msg_rcpt=None): def send_email(msg_subj, msg_txt, msg_rcpt=None):
@@ -10468,7 +10517,7 @@ def doPrintOrgs():
listType = u'children' listType = u'children'
i += 1 i += 1
elif myarg == u'fromparent': elif myarg == u'fromparent':
orgUnitPath = sys.argv[i+1] orgUnitPath = getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == u'allfields': elif myarg == u'allfields':
fields = None fields = None
@@ -10501,8 +10550,8 @@ def doPrintOrgs():
missing_parents = set(parentOrgIds) - set(retrievedOrgIds) missing_parents = set(parentOrgIds) - set(retrievedOrgIds)
for missing_parent in missing_parents: for missing_parent in missing_parents:
try: try:
result = callGAPI(cd.orgunits(), u'get', result = callGAPI(cd.orgunits(), u'get', throw_reasons=[u'required'],
customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=missing_parent, fields=get_fields, throw_reasons=[u'required']) customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=missing_parent, fields=get_fields)
orgunits.append(result) orgunits.append(result)
except: except:
pass pass
@@ -10588,7 +10637,7 @@ def doPrintGroupMembers():
customer = GC_Values[GC_CUSTOMER_ID] customer = GC_Values[GC_CUSTOMER_ID]
usedomain = usemember = usequery = None usedomain = usemember = usequery = None
roles = [] roles = []
fields = None fields = u'nextPageToken,members(email,id,role,status,type)'
titles = [u'group'] titles = [u'group']
csvRows = [] csvRows = []
groups_to_get = [] groups_to_get = []
@@ -10641,6 +10690,7 @@ def doPrintGroupMembers():
i += 1 i += 1
group_email = group[u'email'] group_email = group[u'email']
sys.stderr.write(u'Getting members for %s (%s/%s)\n' % (group_email, i, count)) sys.stderr.write(u'Getting members for %s (%s/%s)\n' % (group_email, i, count))
validRoles, listRoles, listFields = _getRoleVerification(u','.join(roles), fields)
group_members = callGAPIpages(cd.members(), u'list', u'members', group_members = callGAPIpages(cd.members(), u'list', u'members',
soft_errors=True, soft_errors=True,
groupKey=group_email, roles=listRoles, fields=listFields, maxResults=GC_Values[GC_MEMBER_MAX_RESULTS]) groupKey=group_email, roles=listRoles, fields=listFields, maxResults=GC_Values[GC_MEMBER_MAX_RESULTS])
@@ -10863,7 +10913,7 @@ def doPrintCrosActivity():
queries = getQueries(myarg, sys.argv[i+1]) queries = getQueries(myarg, sys.argv[i+1])
i += 2 i += 2
elif myarg == u'limittoou': elif myarg == u'limittoou':
orgUnitPath = sys.argv[i+1] orgUnitPath = getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == u'todrive': elif myarg == u'todrive':
todrive = True todrive = True
@@ -10976,7 +11026,7 @@ def doPrintCrosDevices():
queries = getQueries(myarg, sys.argv[i+1]) queries = getQueries(myarg, sys.argv[i+1])
i += 2 i += 2
elif myarg == u'limittoou': elif myarg == u'limittoou':
orgUnitPath = sys.argv[i+1] orgUnitPath = getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == u'todrive': elif myarg == u'todrive':
todrive = True todrive = True
@@ -11428,10 +11478,11 @@ def getUsersToModify(entity_type=None, entity=None, silent=False, member_type=No
users.append(member.get(u'email', member[u'id'])) users.append(member.get(u'email', member[u'id']))
elif entity_type in [u'ou', u'org']: elif entity_type in [u'ou', u'org']:
got_uids = True got_uids = True
ou = entity ou = makeOrgUnitPathAbsolute(entity)
if ou[0] != u'/':
ou = u'/%s' % ou
users = [] users = []
if ou.startswith(u'id:'):
ou = callGAPI(cd.orgunits(), u'get',
customerId=GC_Values[GC_CUSTOMER_ID], orgUnitPath=ou, fields=u'orgUnitPath')[u'orgUnitPath']
query = orgUnitPathQuery(ou) query = orgUnitPathQuery(ou)
page_message = None page_message = None
if not silent: if not silent:
@@ -11440,18 +11491,15 @@ def getUsersToModify(entity_type=None, entity=None, silent=False, member_type=No
members = callGAPIpages(cd.users(), u'list', u'users', page_message=page_message, members = callGAPIpages(cd.users(), u'list', u'users', page_message=page_message,
customer=GC_Values[GC_CUSTOMER_ID], fields=u'nextPageToken,users(primaryEmail,suspended,orgUnitPath)', customer=GC_Values[GC_CUSTOMER_ID], fields=u'nextPageToken,users(primaryEmail,suspended,orgUnitPath)',
query=query, maxResults=GC_Values[GC_USER_MAX_RESULTS]) query=query, maxResults=GC_Values[GC_USER_MAX_RESULTS])
ou = ou.lower()
for member in members: for member in members:
if ou.lower() != member[u'orgUnitPath'].lower(): if (ou == member[u'orgUnitPath'].lower()) and not (checkNotSuspended and member[u'suspended']):
continue
if not checkNotSuspended or not member[u'suspended']:
users.append(member[u'primaryEmail']) users.append(member[u'primaryEmail'])
if not silent: if not silent:
sys.stderr.write(u"%s Users are directly in the OU.\n" % len(users)) sys.stderr.write(u"%s Users are directly in the OU.\n" % len(users))
elif entity_type in [u'ou_and_children', u'ou_and_child']: elif entity_type in [u'ou_and_children', u'ou_and_child']:
got_uids = True got_uids = True
ou = entity ou = makeOrgUnitPathAbsolute(entity)
if ou[0] != u'/':
ou = u'/%s' % ou
users = [] users = []
query = orgUnitPathQuery(ou) query = orgUnitPathQuery(ou)
page_message = None page_message = None
@@ -11462,7 +11510,7 @@ def getUsersToModify(entity_type=None, entity=None, silent=False, member_type=No
customer=GC_Values[GC_CUSTOMER_ID], fields=u'nextPageToken,users(primaryEmail,suspended)', customer=GC_Values[GC_CUSTOMER_ID], fields=u'nextPageToken,users(primaryEmail,suspended)',
query=query, maxResults=GC_Values[GC_USER_MAX_RESULTS]) query=query, maxResults=GC_Values[GC_USER_MAX_RESULTS])
for member in members: for member in members:
if not checkNotSuspended or not member[u'suspended']: if not (checkNotSuspended and member[u'suspended']):
users.append(member[u'primaryEmail']) users.append(member[u'primaryEmail'])
if not silent: if not silent:
sys.stderr.write(u"done.\r\n") sys.stderr.write(u"done.\r\n")