diff --git a/src/gam/__init__.py b/src/gam/__init__.py index 4d90a02f..7a603e93 100755 --- a/src/gam/__init__.py +++ b/src/gam/__init__.py @@ -536,7 +536,7 @@ def SetGlobalVariables(): fileAbsentValue=True) _getOldSignalFile(GC_NO_SHORT_URLS, 'noshorturls.txt') _getOldSignalFile(GC_NO_UPDATE_CHECK, 'noupdatecheck.txt') - _getOldSignalFile(GC_ENABLE_DASA, 'enabledasa.txt') + _getOldSignalFile(GC_ENABLE_DASA, FN_ENABLEDASA_TXT) # Assign directories first for itemName in GC_VAR_INFO: if GC_VAR_INFO[itemName][GC_VAR_TYPE] == GC_TYPE_DIRECTORY: @@ -553,9 +553,25 @@ def SetGlobalVariables(): GC_Values[itemName] = GC_Defaults[itemName] GM_Globals[GM_LAST_UPDATE_CHECK_TXT] = os.path.join( GC_Values[GC_CONFIG_DIR], FN_LAST_UPDATE_CHECK_TXT) + GM_Globals[GM_ENABLEDASA_TXT] = os.path.join( + GC_Values[GC_CONFIG_DIR], FN_ENABLEDASA_TXT) if not GC_Values[GC_NO_UPDATE_CHECK]: doGAMCheckForUpdates() +# domain must be set and customer_id must be set and != my_customer when enable_dasa = true + if GC_Values[GC_ENABLE_DASA]: + if not GC_Values[GC_DOMAIN]: + controlflow.system_error_exit( + 3, + f'Environment variable GA_DOMAIN must be set when {GM_Globals[GM_ENABLEDASA_TXT]} is present' + ) + if not GC_Values[GC_CUSTOMER_ID] or GC_Values[GC_CUSTOMER_ID] == MY_CUSTOMER: + controlflow.system_error_exit( + 3, + f'Environment variable CUSTOMER_ID must be set and not equal to {MY_CUSTOMER} when {GM_Globals[GM_ENABLEDASA_TXT]} is present\n' + 'Your customer ID can be found at admin.google.com > Account settings > Profile.' + ) + # Globals derived from config file values GM_Globals[GM_OAUTH2SERVICE_JSON_DATA] = None @@ -951,7 +967,7 @@ def buildGAPIObject(api): GC_Values[GC_DOMAIN] = _getValueFromOAuth('hd', credentials=credentials) if GC_Values[GC_DOMAIN] == 'Unknown': GC_Values[GC_DOMAIN] = getEmailAddressDomain( - _getValueFromOAuth('email')) + _get_admin_email()) if not GC_Values[GC_CUSTOMER_ID]: GC_Values[GC_CUSTOMER_ID] = MY_CUSTOMER return service @@ -2877,7 +2893,7 @@ def getPermissionId(argstr): permissionId = f'{permissionId}@{GC_Values[GC_DOMAIN].lower()}' # We have to use v2 here since v3 has no permissions.getIdForEmail equivalent # https://code.google.com/a/google.com/p/apps-api-issues/issues/detail?id=4313 - _, drive2 = buildDriveGAPIObject(_getValueFromOAuth('email')) + _, drive2 = buildDriveGAPIObject(_get_admin_email()) return gapi.call(drive2.permissions(), 'getIdForEmail', email=permissionId, @@ -8487,13 +8503,24 @@ def doCreateResoldCustomer(): f'Created customer {result["customerDomain"]} with id {result["customerId"]}' ) - def _getValueFromOAuth(field, credentials=None): if not credentials: credentials = auth.get_admin_credentials() return credentials.get_token_value(field) +def _get_admin_email(): + if GC_Values[GC_ENABLE_DASA]: + if not GC_Values[GC_ADMIN_EMAIL]: + GC_Values[GC_ADMIN_EMAIL] = os.environ.get('GA_ADMIN_EMAIL', GC_Defaults[GC_ADMIN_EMAIL]) + if not GC_Values[GC_ADMIN_EMAIL]: + controlflow.system_error_exit( + 3, + f'Environment variable GA_ADMIN_EMAIL must be set when {GM_Globals[GM_ENABLEDASA_TXT]} is present' + ) + return GC_Values[GC_ADMIN_EMAIL] + return _getValueFromOAuth('email') + def doGetUserInfo(user_email=None): def user_lic_result(request_id, response, exception): @@ -8507,7 +8534,7 @@ def doGetUserInfo(user_email=None): user_email = normalizeEmailAddressOrUID(sys.argv[3]) i = 4 else: - user_email = _getValueFromOAuth('email') + user_email = _get_admin_email() getSchemas = getAliases = getGroups = getLicenses = True projection = 'full' customFieldMask = viewType = None @@ -9179,7 +9206,7 @@ def send_email(subject, api_body = {} default_sender = default_recipient = False if not user: - user = _getValueFromOAuth('email') + user = _get_admin_email() userId, gmail = buildGmailGAPIObject(user) if not gmail: return @@ -9504,7 +9531,7 @@ def doPrintUsers(): def doPrintShowAlerts(): - _, ac = buildAlertCenterGAPIObject(_getValueFromOAuth('email')) + _, ac = buildAlertCenterGAPIObject(_get_admin_email()) alerts = gapi.get_all_pages(ac.alerts(), 'list', 'alerts') titles = [] csv_rows = [] @@ -9518,7 +9545,7 @@ def doPrintShowAlerts(): def doPrintShowAlertFeedback(): - _, ac = buildAlertCenterGAPIObject(_getValueFromOAuth('email')) + _, ac = buildAlertCenterGAPIObject(_get_admin_email()) feedback = gapi.get_all_pages(ac.alerts().feedback(), 'list', 'feedback', @@ -9528,7 +9555,7 @@ def doPrintShowAlertFeedback(): def doCreateAlertFeedback(): - _, ac = buildAlertCenterGAPIObject(_getValueFromOAuth('email')) + _, ac = buildAlertCenterGAPIObject(_get_admin_email()) valid_types = gapi.get_enum_values_minus_unspecified( ac._rootDesc['schemas']['AlertFeedback']['properties']['type']['enum']) alertId = sys.argv[3] @@ -9542,7 +9569,7 @@ def doCreateAlertFeedback(): def doDeleteOrUndeleteAlert(action): - _, ac = buildAlertCenterGAPIObject(_getValueFromOAuth('email')) + _, ac = buildAlertCenterGAPIObject(_get_admin_email()) alertId = sys.argv[3] kwargs = {} if action == 'undelete': diff --git a/src/gam/display.py b/src/gam/display.py index af65c0b3..630de67d 100644 --- a/src/gam/display.py +++ b/src/gam/display.py @@ -220,7 +220,7 @@ def write_csv_file(csvRows, titles, list_type, todrive): except IOError as e: controlflow.system_error_exit(6, e) if todrive: - admin_email = gam._getValueFromOAuth('email') + admin_email = gam._get_admin_email() _, drive = gam.buildDrive3GAPIObject(admin_email) if not drive: print(f'''\nGAM is not authorized to create Drive files. Please run: diff --git a/src/gam/gapi/calendar.py b/src/gam/gapi/calendar.py index 39ee6350..db8cfd34 100644 --- a/src/gam/gapi/calendar.py +++ b/src/gam/gapi/calendar.py @@ -37,7 +37,7 @@ def buildCalendarDataGAPIObject(calname): if not calname.endswith('.calendar.google.com'): cal = gam.buildGAPIServiceObject('calendar', calendarId, False) if cal is None: - _, cal = buildCalendarGAPIObject(gam._getValueFromOAuth('email')) + _, cal = buildCalendarGAPIObject(gam._get_admin_email()) return (calendarId, cal) diff --git a/src/gam/gapi/cloudidentity/__init__.py b/src/gam/gapi/cloudidentity/__init__.py index 88002b63..1aec65dc 100644 --- a/src/gam/gapi/cloudidentity/__init__.py +++ b/src/gam/gapi/cloudidentity/__init__.py @@ -5,5 +5,5 @@ def build(api='cloudidentity'): return gam.buildGAPIObject(api) def build_dwd(api='cloudidentity'): - admin = gam._getValueFromOAuth('email') + admin = gam._get_admin_email() return gam.buildGAPIServiceObject(api, admin, True) diff --git a/src/gam/gapi/reports.py b/src/gam/gapi/reports.py index b221ca0d..f3edc06e 100644 --- a/src/gam/gapi/reports.py +++ b/src/gam/gapi/reports.py @@ -56,7 +56,7 @@ def showUsageParameters(): kwargs = {} elif report == 'user': endpoint = rep.userUsageReport() - kwargs = {'userKey': gam._getValueFromOAuth('email')} + kwargs = {'userKey': gam._get_admin_email()} else: controlflow.expected_argument_exit('usageparameters', ['user', 'customer'], report) diff --git a/src/gam/var.py b/src/gam/var.py index 1c5f9e30..8d190210 100644 --- a/src/gam/var.py +++ b/src/gam/var.py @@ -37,6 +37,7 @@ ERROR_PREFIX = 'ERROR: ' WARNING_PREFIX = 'WARNING: ' UTF8 = 'utf-8' UTF8_SIG = 'utf-8-sig' +FN_ENABLEDASA_TXT = 'enabledasa.txt' FN_EXTRA_ARGS_TXT = 'extra-args.txt' FN_LAST_UPDATE_CHECK_TXT = 'lastupdatecheck.txt' MY_CUSTOMER = 'my_customer' @@ -1063,6 +1064,8 @@ GM_CURRENT_API_SCOPES = 'scoc' # Values retrieved from oauth2service.json GM_OAUTH2SERVICE_JSON_DATA = 'oajd' GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID = 'oaci' +# Full path to enabledasa.txt +GM_ENABLEDASA_TXT = 'enda' # File containing time of last GAM update check GM_LAST_UPDATE_CHECK_TXT = 'lupc' # Dictionary mapping OrgUnit ID to Name @@ -1102,6 +1105,7 @@ GM_Globals = { GM_CURRENT_API_SCOPES: [], GM_OAUTH2SERVICE_JSON_DATA: None, GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID: None, + GM_ENABLEDASA_TXT: '', GM_LAST_UPDATE_CHECK_TXT: '', GM_MAP_ORGUNIT_ID_TO_NAME: None, GM_MAP_ROLE_ID_TO_NAME: None, @@ -1135,6 +1139,8 @@ GC_CLIENT_SECRETS_JSON = 'client_secrets_json' GC_CONFIG_DIR = 'config_dir' # custmerId from gam.cfg or retrieved from Google GC_CUSTOMER_ID = 'customer_id' +# Enable Delegated Admin Service Accounts admin user +GC_ADMIN_EMAIL = 'admin_email' # If debug_level > 0: extra_args[u'prettyPrint'] = True, # httplib2.debuglevel = gam_debug_level, appsObj.debug = True GC_DEBUG_LEVEL = 'debug_level' @@ -1188,6 +1194,7 @@ GC_CA_FILE = 'ca_file' TLS_MIN = 'TLSv1_2' if hasattr(ssl.SSLContext(), 'minimum_version') else None GC_Defaults = { + GC_ADMIN_EMAIL: '', GC_AUTO_BATCH_MIN: 0, GC_BATCH_SIZE: 50, GC_CACHE_DIR: '', @@ -1238,6 +1245,9 @@ GC_VAR_TYPE = 'type' GC_VAR_LIMITS = 'lmit' GC_VAR_INFO = { + GC_ADMIN_EMAIL: { + GC_VAR_TYPE: GC_TYPE_STRING + }, GC_AUTO_BATCH_MIN: { GC_VAR_TYPE: GC_TYPE_INTEGER, GC_VAR_LIMITS: (0, None)