CBCM API, Device API update Client State, v5.30

This commit is contained in:
Jay Lee
2020-12-05 19:44:48 -05:00
parent 4fda0b6aaa
commit c8e76d5727
8 changed files with 705 additions and 6 deletions

179
src/gam/gapi/cbcm.py Normal file
View File

@@ -0,0 +1,179 @@
"""Chrome Browser Cloud Management API calls"""
import csv
import os.path
import sys
import gam
from gam.var import *
from gam import controlflow
from gam import display
from gam import fileutils
from gam import gapi
from gam.gapi.directory import orgunits as gapi_directory_orgunits
from gam import utils
def build():
return gam.buildGAPIObject('cbcm')
def info():
cbcm = build()
device_id = sys.argv[3]
projection = 'BASIC'
fields = None
i = 4
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg in ['basic', 'full']:
projection = myarg.upper()
i += 1
elif myarg == 'fields':
fields = sys.argv[i+1]
i += 2
else:
controlflow.invalid_argument_exit(sys.argv[i], 'gam info browser')
browser = gapi.call(cbcm.chromebrowsers(), 'get',
customer=GC_Values[GC_CUSTOMER_ID],
fields=fields, deviceId=device_id,
projection=projection)
display.print_json(browser)
def move():
cbcm = build()
body = {'resource_ids': []}
i = 3
resource_ids = []
batch_size = 600
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'ids':
resource_ids.extend(sys.argv[i + 1].split(','))
i += 2
elif myarg == 'query':
query = sys.argv[i + 1]
page_message = gapi.got_total_items_msg('Browsers', '...\n')
browsers = gapi.get_all_pages(cbcm.chromebrowsers(), 'list',
'browsers', page_message=page_message,
customer=GC_Values[GC_CUSTOMER_ID],
query=query, projection='BASIC',
fields='browsers(deviceId),nextPageToken')
ids = [browser['deviceId'] for browser in browsers]
resource_ids.extend(ids)
i += 2
elif myarg == 'file':
with fileutils.open_file(sys.argv[i+1], strip_utf_bom=True) as filed:
for row in filed:
rid = row.strip()
if rid:
resource_ids.append(rid)
i += 2
elif myarg == 'csvfile':
drive, fname_column = os.path.splitdrive(sys.argv[i+1])
if fname_column.find(':') == -1:
controlflow.system_error_exit(
2, 'Expected csvfile FileName:FieldName')
(filename, column) = fname_column.split(':')
with fileutils.open_file(drive + filename) as filed:
input_file = csv.DictReader(filed, restval='')
if column not in input_file.fieldnames:
controlflow.csv_field_error_exit(column,
input_file.fieldnames)
for row in input_file:
rid = row[column].strip()
if rid:
resource_ids.append(rid)
i += 2
elif myarg in ['ou', 'orgunit', 'org']:
org_unit = gapi_directory_orgunits.getOrgUnitItem(sys.argv[i + 1])
body['org_unit_path'] = org_unit
i += 2
elif myarg == 'batchsize':
batch_size = int(sys.argv[i+1])
i += 2
else:
controlflow.invalid_argument_exit(sys.argv[i],
'gam update browsers')
if 'org_unit_path' not in body:
controlflow.missing_argument_exit('ou', 'gam update browsers')
elif not resource_ids:
controlflow.missing_argument_exit('query or ids',
'gam update browsers')
# split moves into max 600 devices per batch
for chunk in range(0, len(resource_ids), batch_size):
body['resource_ids'] = resource_ids[chunk:chunk + batch_size]
print(f' moving {len(body["resource_ids"])} browsers to ' \
f'{body["org_unit_path"]}')
gapi.call(cbcm.chromebrowsers(), 'moveChromeBrowsersToOu',
customer=GC_Values[GC_CUSTOMER_ID], body=body)
def print_():
cbcm = build()
projection = 'BASIC'
query = None
fields = None
titles = []
csv_rows = []
todrive = False
sort_headers = False
i = 3
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'query':
query = sys.argv[i+1]
i += 2
elif myarg == 'projection':
projection = sys.argv[i + 1].upper()
i += 2
elif myarg == 'todrive':
todrive = True
i += 1
elif myarg == 'sortheaders':
sort_headers = True
i += 1
elif myarg == 'fields':
fields = sys.argv[i + 1]
i += 2
else:
controlflow.invalid_argument_exit(sys.argv[i],
'gam print browsers')
if fields:
fields = f'browsers({fields}),nextPageToken'
page_message = gapi.got_total_items_msg('Browsers', '...\n')
browsers = gapi.get_all_pages(cbcm.chromebrowsers(), 'list',
'browsers', page_message=page_message,
customer=GC_Values[GC_CUSTOMER_ID],
query=query, projection=projection,
fields=fields)
for browser in browsers:
browser = utils.flatten_json(browser)
for a_key in browser:
if a_key not in titles:
titles.append(a_key)
csv_rows.append(browser)
if sort_headers:
display.sort_csv_titles(['name',], titles)
display.write_csv_file(csv_rows, titles, 'Browsers', todrive)
def update():
cbcm = build()
device_id = sys.argv[3]
body = {'deviceId': device_id}
attributes = ['user', 'location', 'notes', 'assetid']
i = 4
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg in attributes:
attribute = f'annotated{myarg.capitalize()}'
body[attribute] = sys.argv[i+1]
i += 2
else:
controlflow.invalid_argument_exit(sys.argv[i],
'gam print browsers')
result = gapi.call(cbcm.chromebrowsers(), 'update', deviceId=device_id,
customer=GC_Values[GC_CUSTOMER_ID], body=body,
projection='BASIC', fields="deviceId")
print(f'Updated browser {result["deviceId"]}')

View File

@@ -3,6 +3,7 @@ import sys
import googleapiclient
import gam
from gam.var import *
from gam import controlflow
from gam import display
@@ -11,7 +12,7 @@ from gam import gapi
from gam import utils
from gam.gapi import errors as gapi_errors
from gam.gapi import cloudidentity as gapi_cloudidentity
from gam.gapi.directory import customer as gapi_directory_customer
def _get_device_customerid():
customer = GC_Values[GC_CUSTOMER_ID]
@@ -49,6 +50,7 @@ def create():
result = gapi.call(ci.devices(), 'create', customer=customer, body=body)
print(f'Created device {result["response"]["name"]}')
def _get_device_name():
name = sys.argv[3]
if name == 'id':
@@ -65,9 +67,15 @@ def info():
device = gapi.call(ci.devices(), 'get', name=name, customer=customer)
device_users = gapi.get_all_pages(ci.devices().deviceUsers(), 'list',
'deviceUsers', parent=name, customer=customer)
for device_user in device_users:
parent = device_user['name']
client_states = gapi.get_all_pages(ci.devices().deviceUsers().clientStates(), 'list', 'clientStates', parent=parent, customer=customer)
display.print_json(device)
print('Device Users:')
display.print_json(device_users)
print('Client States:')
display.print_json(client_states)
def _generic_action(action, device_user=False):
ci = gapi_cloudidentity.build_dwd()
@@ -87,30 +95,126 @@ def _generic_action(action, device_user=False):
op = gapi.call(endpoint, action, name=name, **kwargs)
print(op)
def delete():
_generic_action('delete')
def cancel_wipe():
_generic_action('cancelWipe')
def wipe():
_generic_action('wipe')
def approve_user():
_generic_action('approve', True)
def block_user():
_generic_action('block', True)
def cancel_wipe_user():
_generic_action('cancelWipe', True)
def delete_user():
_generic_action('delete', True)
def wipe_user():
_generic_action('wipe', True)
def update_state():
ci = gapi_cloudidentity.build_dwd()
gapi_directory_customer.setTrueCustomerId()
customer = _get_device_customerid()[10:]
client_id = f'{customer}-gam'
body = {}
i = 3
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'id':
deviceuser = sys.argv[i+1]
i += 2
elif myarg == 'clientid':
client_id = f'{customer}-{sys.argv[i+1]}'
i += 2
elif myarg in ['assettag', 'assettags']:
body['assetTags'] = sys.argv[i+1].split(',')
if body['assetTags'] == ['clear']:
# TODO: this doesn't work to clear
# existing values. Figure out why.
body['assetTags'] = [None]
i += 2
elif myarg in ['compliantstate', 'compliancestate']:
comp_states = gapi.get_enum_values_minus_unspecified(
ci._rootDesc['schemas']['GoogleAppsCloudidentityDevicesV1ClientState']['properties']['complianceState']['enum'])
body['complianceState'] = sys.argv[i+1].upper()
if body['complianceState'] not in comp_states:
controlflow.expected_argument_exit('compliant_state',
', '.join(comp_states),
sys.argv[i+1])
i += 2
elif myarg == 'customid':
body['customId'] = sys.argv[i+1]
i += 2
elif myarg == 'healthscore':
health_scores = gapi.get_enum_values_minus_unspecified(
ci._rootDesc['schemas']['GoogleAppsCloudidentityDevicesV1ClientState']['properties']['healthScore']['enum'])
body['healthScore'] = sys.argv[i+1].upper()
if body['healthScore'] == 'CLEAR':
body['healthScore'] = None
if body['healthScore'] and body['healthScore'] not in health_scores:
controlflow.expected_argument_exit('health_score',
', '.join(health_scores),
sys.argv[i+1])
i += 2
elif myarg == 'customvalue':
allowed_types = ['boolValue', 'numberValue', 'stringValue']
value_type = f'{sys.argv[i+1].lower()}Value'
if value_type not in allowed_types:
controlflow.expected_argument_exit('custom_value',
', '.join(allowed_types),
sys.argv[i+1])
key = sys.argv[i+2]
value = sys.argv[i+3]
if value_type == 'boolValue':
value = gam.getBoolean(value, key)
elif value_type == 'numberValue':
value = int(value)
if 'keyValuePairs' not in body:
body['keyValuePairs'] = {}
body['keyValuePairs'][key] = {value_type: value}
i += 4
elif myarg in ['managedstate']:
managed_states = gapi.get_enum_values_minus_unspecified(
ci._rootDesc['schemas']['GoogleAppsCloudidentityDevicesV1ClientState']['properties']['managed']['enum'])
body['managed'] = sys.argv[i+1].upper()
if body['managed'] == 'CLEAR':
body['managed'] = None
if body['managed'] and body['managed'] not in managed_states:
controlflow.expected_argument_exit('managed_state',
', '.join(managed_states),
sys.argv[i+1])
i += 2
elif myarg in ['scorereason']:
body['scoreReason'] = sys.argv[i+1]
if body['scoreReason'] == 'clear':
body['scoreReason'] = None
i += 2
else:
controlflow.invalid_argument_exit(sys.argv[i], 'gam update deviceuserstate')
name = f'{deviceuser}/clientStates/{client_id}'
updateMask = ','.join(body.keys())
result = gapi.call(ci.devices().deviceUsers().clientStates(), 'patch',
name=name, customer=f'customers/{customer}', updateMask=updateMask, body=body)
display.print_json(result)
def print_():
ci = gapi_cloudidentity.build_dwd()
customer = _get_device_customerid()

View File

@@ -27,13 +27,13 @@ def info():
'get',
customerId=GC_Values[GC_CUSTOMER_ID],
resourceId=resourceId)
if 'deviceId' in info:
if 'deviceId' in device_info:
device_info['deviceId'] = device_info['deviceId'].encode('unicode-escape').decode(
UTF8)
attrib = 'securityPatchLevel'
if attrib in info and int(device_info[attrib]):
if attrib in device_info and int(device_info[attrib]):
device_info[attrib] = utils.formatTimestampYMDHMS(device_info[attrib])
display.print_json(info)
display.print_json(device_info)