chromepolicy cleanup

This commit is contained in:
Jay Lee
2021-03-18 10:01:35 -04:00
parent 93700c01a8
commit d90c884cf2
2 changed files with 132 additions and 84 deletions

View File

@ -1,24 +1,23 @@
"""Chrome Browser Cloud Management API calls""" """Chrome Browser Cloud Management API calls"""
import json
import sys import sys
import googleapiclient.errors
import gam import gam
from gam.var import * from gam.var import GC_CUSTOMER_ID, GC_Values, MY_CUSTOMER
from gam import controlflow from gam import controlflow
from gam import gapi from gam import gapi
from gam.gapi import errors as gapi_errors from gam.gapi import errors as gapi_errors
from gam.gapi.directory import orgunits as gapi_directory_orgunits from gam.gapi.directory import orgunits as gapi_directory_orgunits
from gam import utils from gam import utils
import googleapiclient.errors
def _get_customerid(): def _get_customerid():
customer = GC_Values[GC_CUSTOMER_ID] customer = GC_Values[GC_CUSTOMER_ID]
if customer != MY_CUSTOMER and customer[0] != 'C': if customer != MY_CUSTOMER and customer[0] != 'C':
customer = 'C' + customer customer = 'C' + customer
return f'customers/{customer}' return f'customers/{customer}'
def _get_orgunit(orgunit): def _get_orgunit(orgunit):
@ -33,12 +32,26 @@ def build():
def print_policies(): def print_policies():
cp = build() svc = build()
customer = _get_customerid() customer = _get_customerid()
if len(sys.argv) < 4: orgunit = '/'
orgunit = '/' printer_id = None
else: app_id = None
orgunit = sys.argv[3] i = 3
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg in ['orgunit', 'ou']:
orgunit = sys.argv[i+1]
i += 2
elif myarg == 'printerid':
printer_id = sys.argv[i+1]
i += 2
elif myarg == 'appid':
app_id = sys.argv[i+1]
i += 2
else:
msg = f'{myarg} is not a valid argument to "gam print chromepolicy"'
controlflow.system_error_exit(3, msg)
orgunit = _get_orgunit(orgunit) orgunit = _get_orgunit(orgunit)
namespaces = [ namespaces = [
'chrome.users', 'chrome.users',
@ -48,18 +61,22 @@ def print_policies():
# 'chrome.devices.managedGuest.apps', # 'chrome.devices.managedGuest.apps',
# 'chrome.devices.kiosk', # 'chrome.devices.kiosk',
# 'chrome.devices.kiosk.apps', # 'chrome.devices.kiosk.apps',
# 'chrome.printers', 'chrome.printers',
] ]
body = { body = {
'policyTargetKey': { 'policyTargetKey': {
'targetResource': orgunit, 'targetResource': orgunit,
} }
} }
if printer_id:
body['policyTargetKey']['additionalTargetKeys'] = {'printer_id': printer_id}
elif app_id:
body['policyTargetKey']['additionalTargetKeys'] = {'app_id': app_id}
throw_reasons = [gapi_errors.ErrorReason.FOUR_O_O,] throw_reasons = [gapi_errors.ErrorReason.FOUR_O_O,]
for namespace in namespaces: for namespace in namespaces:
body['policySchemaFilter'] = f'{namespace}.*' body['policySchemaFilter'] = f'{namespace}.*'
try: try:
policies = gapi.get_all_pages(cp.customers().policies(), 'resolve', policies = gapi.get_all_pages(svc.customers().policies(), 'resolve',
items='resolvedPolicies', items='resolvedPolicies',
throw_reasons=throw_reasons, throw_reasons=throw_reasons,
customer=customer, customer=customer,
@ -67,8 +84,6 @@ def print_policies():
except googleapiclient.errors.HttpError: except googleapiclient.errors.HttpError:
policies = [] policies = []
for policy in policies: for policy in policies:
#print(json.dumps(policy, indent=2))
#print()
name = policy.get('value', {}).get('policySchema', '') name = policy.get('value', {}).get('policySchema', '')
print(name) print(name)
values = policy.get('value', {}).get('value', {}) values = policy.get('value', {}).get('value', {})
@ -78,24 +93,22 @@ def print_policies():
print(f' {setting}: {value}') print(f' {setting}: {value}')
print() print()
def build_schemas(cp=None): def build_schemas(svc=None):
if not cp: if not svc:
cp = build() svc = build()
parent = _get_customerid() parent = _get_customerid()
schemas = gapi.get_all_pages(cp.customers().policySchemas(), 'list', schemas = gapi.get_all_pages(svc.customers().policySchemas(), 'list',
items='policySchemas', parent=parent) items='policySchemas', parent=parent)
schema_objects = {} schema_objects = {}
for schema in schemas: for schema in schemas:
schema_name = schema.get('name', '').split('/')[-1] schema_name = schema.get('name', '').split('/')[-1]
#print(schema)
#continue
schema_dict = { schema_dict = {
'name': schema_name, 'name': schema_name,
'description': schema.get('policyDescription', ''), 'description': schema.get('policyDescription', ''),
'settings': {}, 'settings': {},
} }
for mt in schema.get('definition', {}).get('messageType', {}): for mtype in schema.get('definition', {}).get('messageType', {}):
for setting in mt.get('field', {}): for setting in mtype.get('field', {}):
setting_name = setting.get('name', '') setting_name = setting.get('name', '')
setting_dict = { setting_dict = {
'name': setting_name, 'name': setting_name,
@ -103,7 +116,8 @@ def build_schemas(cp=None):
'descriptions': [], 'descriptions': [],
'type': setting.get('type'), 'type': setting.get('type'),
} }
if setting_dict['type'] == 'TYPE_STRING' and setting.get('label') == 'LABEL_REPEATED': if setting_dict['type'] == 'TYPE_STRING' and \
setting.get('label') == 'LABEL_REPEATED':
setting_dict['type'] = 'TYPE_LIST' setting_dict['type'] = 'TYPE_LIST'
if setting_dict['type'] == 'TYPE_ENUM': if setting_dict['type'] == 'TYPE_ENUM':
type_name = setting['typeName'] type_name = setting['typeName']
@ -112,95 +126,116 @@ def build_schemas(cp=None):
setting_dict['enums'] = [enum['name'] for enum in an_enum['value']] setting_dict['enums'] = [enum['name'] for enum in an_enum['value']]
setting_dict['enum_prefix'] = utils.commonprefix(setting_dict['enums']) setting_dict['enum_prefix'] = utils.commonprefix(setting_dict['enums'])
prefix_len = len(setting_dict['enum_prefix']) prefix_len = len(setting_dict['enum_prefix'])
setting_dict['enums'] = [enum[prefix_len:] for enum in setting_dict['enums'] if not enum.endswith('UNSPECIFIED')] setting_dict['enums'] = [enum[prefix_len:] for enum \
in setting_dict['enums'] \
if not enum.endswith('UNSPECIFIED')]
break break
for fd in schema.get('fieldDescriptions', []): for fdesc in schema.get('fieldDescriptions', []):
if fd.get('field') == setting_name: if fdesc.get('field') == setting_name:
setting_dict['descriptions'] = [d['description'] for d in fd.get('knownValueDescriptions', [])] setting_dict['descriptions'] = [d['description'] \
for d in \
fdesc.get('knownValueDescriptions', \
[])]
break break
elif setting_dict['type'] == 'TYPE_MESSAGE': elif setting_dict['type'] == 'TYPE_MESSAGE':
print(setting_dict)
continue continue
else: else:
setting_dict['enums'] = None setting_dict['enums'] = None
for fd in schema.get('fieldDescriptions', []): for fdesc in schema.get('fieldDescriptions', []):
if fd.get('field') == setting_name: if fdesc.get('field') == setting_name:
if 'knownValueDescriptions' in fd: if 'knownValueDescriptions' in fdesc:
setting_dict['descriptions'] = fd['knownValueDescriptions'] setting_dict['descriptions'] = fdesc['knownValueDescriptions']
elif 'description' in fd: elif 'description' in fdesc:
setting_dict['descriptions'] = [fd['description']] setting_dict['descriptions'] = [fdesc['description']]
schema_dict['settings'][setting_name.lower()] = setting_dict schema_dict['settings'][setting_name.lower()] = setting_dict
schema_objects[schema_name.lower()] = schema_dict schema_objects[schema_name.lower()] = schema_dict
for obj in schema_objects.values():
print(json.dumps(obj, indent=2))
return schema_objects return schema_objects
def print_schemas(): def print_schemas():
cp = build() svc = build()
schemas = build_schemas(cp) schemas = build_schemas(svc)
for val in schemas.values(): for value in schemas.values():
print(f'{val.get("name")} - {val.get("description")}') print(f'{value.get("name")} - {value.get("description")}')
for v in val['settings'].values(): for val in value['settings'].values():
vtype = v.get('type') vtype = val.get('type')
print(f' {v.get("name")}: {vtype}') print(f' {val.get("name")}: {vtype}')
if vtype == 'TYPE_ENUM': if vtype == 'TYPE_ENUM':
enums = v.get('enums', []) enums = val.get('enums', [])
descriptions = v.get('descriptions', []) descriptions = val.get('descriptions', [])
#print(' ', ', '.join(v.get('enums'))) for i in range(len(val.get('enums', []))):
for i in range(len(v.get('enums', []))):
print(f' {enums[i]} - {descriptions[i]}') print(f' {enums[i]} - {descriptions[i]}')
elif vtype == 'TYPE_BOOL': elif vtype == 'TYPE_BOOL':
pvs = v.get('descriptions') pvs = val.get('descriptions')
for pv in pvs: for pvi in pvs:
if isinstance(pv, dict): if isinstance(pvi, dict):
pvalue = pv.get('value') pvalue = pvi.get('value')
pdescription = pv.get('description') pdescription = pvi.get('description')
print(f' {pvalue} - {pdescription}') print(f' {pvalue} - {pdescription}')
elif isinstance(pv, list): elif isinstance(pvi, list):
print(f' {pv[0]}') print(f' {pvi[0]}')
else: else:
description = v.get('descriptions') description = val.get('descriptions')
if len(description) > 0: if len(description) > 0:
print(f' {description[0]}') print(f' {description[0]}')
print() print()
def delete_policy(): def delete_policy():
cp = build() svc = build()
customer = _get_customerid() customer = _get_customerid()
schemas = build_schemas(cp) schemas = build_schemas(svc)
orgunit = None orgunit = '/'
printer_id = None
app_id = None
i = 3 i = 3
body = {'requests': []} body = {'requests': []}
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower() myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'orgunit': if myarg in ['orgunit', 'ou']:
orgunit = _get_orgunit(sys.argv[i+1]) orgunit = sys.argv[i+1]
i += 2
elif myarg == 'printerid':
printer_id = sys.argv[i+1]
i += 2
elif myarg == 'appid':
app_id = sys.argv[i+1]
i += 2 i += 2
elif myarg in schemas: elif myarg in schemas:
body['requests'].append({'policySchema': schemas[myarg].name}) body['requests'].append({'policySchema': schemas[myarg]['name']})
i += 1 i += 1
else: else:
controlflow.system_error_exit(3, f'{myarg} is not a valid argument to "gam delete chromepolicy"') msg = f'{myarg} is not a valid argument to "gam delete chromepolicy"'
if not orgunit: controlflow.system_error_exit(3, msg)
controlflow.system_error_exit(3, 'You must specify an orgunit.') orgunit = _get_orgunit(orgunit)
for request in body['requests']: for request in body['requests']:
request['policyTargetKey'] = {'targetResource': orgunit} request['policyTargetKey'] = {'targetResource': orgunit}
gapi.call(cp.customers().policies().orgunits(), 'batchInherit', customer=customer, body=body) if printer_id:
request['policyTargetKey']['additionalTargetKeys'] = {'printer_id': printer_id}
elif app_id:
request['policyTargetKey']['additionalTargetKeys'] = {'app_id': app_id}
gapi.call(svc.customers().policies().orgunits(), 'batchInherit', customer=customer, body=body)
def update_policy(): def update_policy():
cp = build() svc = build()
customer = _get_customerid() customer = _get_customerid()
schemas = build_schemas(cp) schemas = build_schemas(svc)
i = 3 i = 3
body = {'requests': []} body = {'requests': []}
orgunit = None orgunit = None
printer_id = None
app_id = None
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower() myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'orgunit': if myarg in ['orgunit', 'ou']:
orgunit = _get_orgunit(sys.argv[i+1]) orgunit = _get_orgunit(sys.argv[i+1])
i += 2 i += 2
elif myarg == 'printerid':
printer_id = sys.argv[i+1]
i += 2
elif myarg == 'appid':
app_id = sys.argv[i+1]
i += 2
elif myarg in schemas: elif myarg in schemas:
body['requests'].append({'policyValue': {'policySchema': schemas[myarg]['name'], body['requests'].append({'policyValue': {'policySchema': schemas[myarg]['name'],
'value': {}}, 'value': {}},
@ -208,27 +243,31 @@ def update_policy():
i += 1 i += 1
while i < len(sys.argv): while i < len(sys.argv):
field = sys.argv[i].lower() field = sys.argv[i].lower()
if field == 'orgunit' or '.' in field: if field in ['orgunit', 'ou', 'printerid', 'appid'] or '.' in field:
break # field is actually a new policy name or orgunit break # field is actually a new policy, orgunit or app/printer id
expected_fields = ', '.join(schemas[myarg]['settings']) expected_fields = ', '.join(schemas[myarg]['settings'])
if field not in expected_fields: if field not in expected_fields:
controlflow.system_error_exit(4, f'Expected {myarg} field of {expected_fields}. Got {field}.') msg = f'Expected {myarg} field of {expected_fields}. Got {field}.'
controlflow.system_error_exit(4, msg)
cased_field = schemas[myarg]['settings'][field]['name'] cased_field = schemas[myarg]['settings'][field]['name']
value = sys.argv[i+1] value = sys.argv[i+1]
vtype = schemas[myarg]['settings'][field]['type'] vtype = schemas[myarg]['settings'][field]['type']
if vtype in ['TYPE_INT64', 'TYPE_INT32', 'TYPE_UINT64']: if vtype in ['TYPE_INT64', 'TYPE_INT32', 'TYPE_UINT64']:
if not value.isnumeric(): if not value.isnumeric():
controlflow.system_error_exit(7, f'Value for {myarg} {field} must be a number, got {value}') msg = f'Value for {myarg} {field} must be a number, got {value}'
controlflow.system_error_exit(7, msg)
value = int(value) value = int(value)
elif vtype in ['TYPE_BOOL']: elif vtype in ['TYPE_BOOL']:
value = gam.getBoolean(value, field) value = gam.getBoolean(value, field)
elif vtype in ['TYPE_ENUM']: elif vtype in ['TYPE_ENUM']:
value = value.upper() value = value.upper()
enum_values = schemas[myarg].settings[field].enums enum_values = schemas[myarg]['settings'][field]['enums']
if value not in enum_values: if value not in enum_values:
expected_enums = ', '.join(enum_values) expected_enums = ', '.join(enum_values)
controlflow.system_error_exit(8, f'Expected {myarg} {field} value to be one of {expected_enums}, got {value}') msg = f'Expected {myarg} {field} value to be one of ' \
prefix = schemas[myarg].settings[field].enum_prefix f'{expected_enums}, got {value}'
controlflow.system_error_exit(8, msg)
prefix = schemas[myarg]['settings'][field]['enum_prefix']
value = f'{prefix}{value}' value = f'{prefix}{value}'
elif vtype in ['TYPE_LIST']: elif vtype in ['TYPE_LIST']:
value = value.split(',') value = value.split(',')
@ -236,9 +275,19 @@ def update_policy():
body['requests'][-1]['updateMask'] += f'{cased_field},' body['requests'][-1]['updateMask'] += f'{cased_field},'
i += 2 i += 2
else: else:
controlflow.system_error_exit(4, f'{myarg} is not a valid argument to "gam update chromepolicy"') msg = f'{myarg} is not a valid argument to "gam update chromepolicy"'
controlflow.system_error_exit(4, msg)
if not orgunit: if not orgunit:
controlflow.system_error_exit(3, 'You must specify an orgunit') controlflow.system_error_exit(3, 'You must specify an orgunit')
for request in body['requests']: for request in body['requests']:
request['policyTargetKey'] = {'targetResource': orgunit} request['policyTargetKey'] = {'targetResource': orgunit}
gapi.call(cp.customers().policies().orgunits(), 'batchModify', customer=customer, body=body) if printer_id:
for request in body['requests']:
request['policyTargetKey']['additionalTargetKeys'] = {'printer_id': printer_id}
elif app_id:
for request in body['requests']:
request['policyTargetKey']['additionalTargetKeys'] = {'app_id': app_id}
gapi.call(svc.customers().policies().orgunits(),
'batchModify',
customer=customer,
body=body)

View File

@ -1,10 +1,9 @@
"""Methods related to Cloud Identity User Invitation API""" """Methods related to Cloud Identity User Invitation API"""
# pylint: disable=unused-wildcard-import wildcard-import
import sys import sys
import googleapiclient import googleapiclient
from gam.var import * from gam.var import GC_CUSTOMER_ID, GC_Values, MY_CUSTOMER
from gam import controlflow from gam import controlflow
from gam import display from gam import display
from gam import gapi from gam import gapi