Handle out of domain users better

This commit is contained in:
Ross Scroggs
2016-01-11 22:21:01 -08:00
parent eb5cfde630
commit 0d94dd3fa5

View File

@ -92,8 +92,10 @@ GM_BATCH_QUEUE = u'batq'
GM_EXTRA_ARGS_DICT = u'exad' GM_EXTRA_ARGS_DICT = u'exad'
# Scopes retrieved from gamscopes.json # Scopes retrieved from gamscopes.json
GM_GAMSCOPES_BY_API = u'scop' GM_GAMSCOPES_BY_API = u'scop'
# Current API user
GM_CURRENT_API_USER = u'capu'
# Current API scope # Current API scope
GM_CURRENT_API_SCOPES = u'scoc' GM_CURRENT_API_SCOPES = u'caps'
# Values retrieved from oauth2service.json # Values retrieved from oauth2service.json
GM_OAUTH2SERVICE_KEY = u'oauk' GM_OAUTH2SERVICE_KEY = u'oauk'
GM_OAUTH2SERVICE_ACCOUNT_EMAIL = u'oaae' GM_OAUTH2SERVICE_ACCOUNT_EMAIL = u'oaae'
@ -117,6 +119,7 @@ GM_Globals = {
GM_BATCH_QUEUE: None, GM_BATCH_QUEUE: None,
GM_EXTRA_ARGS_DICT: {u'prettyPrint': False}, GM_EXTRA_ARGS_DICT: {u'prettyPrint': False},
GM_GAMSCOPES_BY_API: {}, GM_GAMSCOPES_BY_API: {},
GM_CURRENT_API_USER: None,
GM_CURRENT_API_SCOPES: [], GM_CURRENT_API_SCOPES: [],
GM_OAUTH2SERVICE_KEY: None, GM_OAUTH2SERVICE_KEY: None,
GM_OAUTH2SERVICE_ACCOUNT_EMAIL: None, GM_OAUTH2SERVICE_ACCOUNT_EMAIL: None,
@ -254,6 +257,7 @@ MESSAGE_PLEASE_AUTHORIZE_SERVICE_ACCOUNT = u'Please authorize your Service accou
MESSAGE_REQUEST_COMPLETED_NO_FILES = u'Request completed but no results/files were returned, try requesting again' MESSAGE_REQUEST_COMPLETED_NO_FILES = u'Request completed but no results/files were returned, try requesting again'
MESSAGE_REQUEST_NOT_COMPLETE = u'Request needs to be completed before downloading, current status is: {0}' MESSAGE_REQUEST_NOT_COMPLETE = u'Request needs to be completed before downloading, current status is: {0}'
MESSAGE_RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = u'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.' MESSAGE_RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = u'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.'
MESSAGE_SERVICE_NOT_APPLICABLE = 'Service not applicable for this address: {0}'
MESSAGE_WIKI_INSTRUCTIONS_OAUTH2SERVICE_JSON = u'Please follow the instructions at this site to setup a Service account.' MESSAGE_WIKI_INSTRUCTIONS_OAUTH2SERVICE_JSON = u'Please follow the instructions at this site to setup a Service account.'
OAUTH_TOKEN_ERRORS = [u'access_denied', u'unauthorized_client: Unauthorized client or scope in request.', u'access_denied: Requested client not authorized.', u'invalid_grant: Not a valid email.', u'invalid_request: Invalid impersonation prn email address.'] OAUTH_TOKEN_ERRORS = [u'access_denied', u'unauthorized_client: Unauthorized client or scope in request.', u'access_denied: Requested client not authorized.', u'invalid_grant: Not a valid email.', u'invalid_request: Invalid impersonation prn email address.']
@ -609,17 +613,20 @@ def doGAMVersion():
platform.platform(), platform.machine(), platform.platform(), platform.machine(),
GM_Globals[GM_GAM_PATH]) GM_Globals[GM_GAM_PATH])
def handleOAuthTokenError(e, soft_errors): def handleOAuthTokenError(e, soft_errors):
if e.message in OAUTH_TOKEN_ERRORS: if e.message in OAUTH_TOKEN_ERRORS:
if soft_errors: if not GM_Globals[GM_CURRENT_API_USER]:
return None
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, MESSAGE_API_ACCESS_DENIED.format(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID], sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, MESSAGE_API_ACCESS_DENIED.format(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID],
u','.join(GM_Globals[GM_CURRENT_API_SCOPES]), GC_Values[GC_ADMIN]))) u','.join(GM_Globals[GM_CURRENT_API_SCOPES]), GC_Values[GC_ADMIN])))
systemErrorExit(12, MESSAGE_API_ACCESS_CONFIG) systemErrorExit(12, MESSAGE_API_ACCESS_CONFIG)
else:
systemErrorExit(19, MESSAGE_SERVICE_NOT_APPLICABLE.format(GM_Globals[GM_CURRENT_API_USER]))
if soft_errors:
sys.stderr.write(u'{0}Authentication Token Error - {1}\n'.format(ERROR_PREFIX, e))
return None
systemErrorExit(18, u'Authentication Token Error - {0}'.format(e)) systemErrorExit(18, u'Authentication Token Error - {0}'.format(e))
def tryOAuth(gdataObject, soft_errors=False): def getGDataOAuthToken(gdataObject):
credentials = oauth2client.client.SignedJwtAssertionCredentials(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_EMAIL], credentials = oauth2client.client.SignedJwtAssertionCredentials(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_EMAIL],
GM_Globals[GM_OAUTH2SERVICE_KEY], GM_Globals[GM_OAUTH2SERVICE_KEY],
scope=GM_Globals[GM_CURRENT_API_SCOPES], user_agent=GAM_INFO, sub=GC_Values[GC_ADMIN]) scope=GM_Globals[GM_CURRENT_API_SCOPES], user_agent=GAM_INFO, sub=GC_Values[GC_ADMIN])
@ -630,17 +637,14 @@ def tryOAuth(gdataObject, soft_errors=False):
except httplib2.ServerNotFoundError as e: except httplib2.ServerNotFoundError as e:
systemErrorExit(4, e) systemErrorExit(4, e)
except oauth2client.client.AccessTokenRefreshError, e: except oauth2client.client.AccessTokenRefreshError, e:
return handleOAuthTokenError(e, soft_errors) return handleOAuthTokenError(e, False)
gdataObject.additional_headers = {u'Authorization': u'Bearer %s' % credentials.access_token} gdataObject.additional_headers = {u'Authorization': u'Bearer %s' % credentials.access_token}
gdataObject.domain = GC_Values[GC_DOMAIN]
return True return True
def checkGDataError(e, service): def checkGDataError(e, service):
# First check for errors that need special handling # First check for errors that need special handling
if e[0].get(u'reason', u'') in [u'Token invalid - Invalid token: Stateless token expired', u'Token invalid - Invalid token: Token not found']: if e[0].get(u'reason', u'') in [u'Token invalid - Invalid token: Stateless token expired', u'Token invalid - Invalid token: Token not found']:
keep_domain = service.domain getGDataOAuthToken(service)
tryOAuth(service)
service.domain = keep_domain
return False return False
if e[0][u'body'].startswith(u'Required field must not be blank:') or e[0][u'body'].startswith(u'These characters are not allowed:'): if e[0][u'body'].startswith(u'Required field must not be blank:') or e[0][u'body'].startswith(u'These characters are not allowed:'):
return e[0]['body'] return e[0]['body']
@ -763,7 +767,7 @@ def callGAPI(service, function, silent_errors=False, soft_errors=False, throw_re
return None return None
sys.exit(int(http_status)) sys.exit(int(http_status))
except oauth2client.client.AccessTokenRefreshError, e: except oauth2client.client.AccessTokenRefreshError, e:
return handleOAuthTokenError(e, False) return handleOAuthTokenError(e, soft_errors)
except httplib2.CertificateValidationUnsupported: except httplib2.CertificateValidationUnsupported:
noPythonSSLExit() noPythonSSLExit()
except TypeError, e: except TypeError, e:
@ -881,6 +885,7 @@ def getAPIversionHttpService(api):
def buildGAPIObject(api, act_as=None, soft_errors=False): def buildGAPIObject(api, act_as=None, soft_errors=False):
svcsub = act_as if act_as else GC_Values[GC_ADMIN] svcsub = act_as if act_as else GC_Values[GC_ADMIN]
api_version, http, service = getAPIversionHttpService(api) api_version, http, service = getAPIversionHttpService(api)
GM_Globals[GM_CURRENT_API_USER] = act_as
GM_Globals[GM_CURRENT_API_SCOPES] = GM_Globals[GM_GAMSCOPES_BY_API].get(api_version, []) GM_Globals[GM_CURRENT_API_SCOPES] = GM_Globals[GM_GAMSCOPES_BY_API].get(api_version, [])
if not GM_Globals[GM_CURRENT_API_SCOPES]: if not GM_Globals[GM_CURRENT_API_SCOPES]:
systemErrorExit(15, MESSAGE_NO_SCOPES_FOR_API.format(service._rootDesc[u'title'])) systemErrorExit(15, MESSAGE_NO_SCOPES_FOR_API.format(service._rootDesc[u'title']))
@ -889,6 +894,8 @@ def buildGAPIObject(api, act_as=None, soft_errors=False):
scope=GM_Globals[GM_CURRENT_API_SCOPES], user_agent=GAM_INFO, sub=svcsub) scope=GM_Globals[GM_CURRENT_API_SCOPES], user_agent=GAM_INFO, sub=svcsub)
try: try:
service._http = credentials.authorize(http) service._http = credentials.authorize(http)
except httplib2.ServerNotFoundError as e:
systemErrorExit(4, e)
except oauth2client.client.AccessTokenRefreshError, e: except oauth2client.client.AccessTokenRefreshError, e:
return handleOAuthTokenError(e, soft_errors) return handleOAuthTokenError(e, soft_errors)
return service return service
@ -899,31 +906,33 @@ GDATA_API_INFO = {
u'email-settings': u'Email Settings API', u'email-settings': u'Email Settings API',
} }
def commonAppsObjInit(appsObj, api): def initGDataObject(gdataObj, api):
getOAuth2ServiceDetails() getOAuth2ServiceDetails()
api, _, api_version = getAPIVersion(api) api, _, api_version = getAPIVersion(api)
GM_Globals[GM_CURRENT_API_USER] = None
GM_Globals[GM_CURRENT_API_SCOPES] = GM_Globals[GM_GAMSCOPES_BY_API].get(api_version, []) GM_Globals[GM_CURRENT_API_SCOPES] = GM_Globals[GM_GAMSCOPES_BY_API].get(api_version, [])
if not GM_Globals[GM_CURRENT_API_SCOPES]: if not GM_Globals[GM_CURRENT_API_SCOPES]:
systemErrorExit(15, MESSAGE_NO_SCOPES_FOR_API.format(GDATA_API_INFO[api])) systemErrorExit(15, MESSAGE_NO_SCOPES_FOR_API.format(GDATA_API_INFO[api]))
tryOAuth(appsObj) getGDataOAuthToken(gdataObj)
gdataObj.domain = GC_Values[GC_DOMAIN]
#Identify GAM to Google's Servers #Identify GAM to Google's Servers
appsObj.source = GAM_INFO gdataObj.source = GAM_INFO
#Show debugging output if debug.gam exists #Show debugging output if debug.gam exists
if GC_Values[GC_DEBUG_LEVEL] > 0: if GC_Values[GC_DEBUG_LEVEL] > 0:
appsObj.debug = True gdataObj.debug = True
return appsObj return gdataObj
def getAdminSettingsObject(): def getAdminSettingsObject():
import gdata.apps.adminsettings.service import gdata.apps.adminsettings.service
return commonAppsObjInit(gdata.apps.adminsettings.service.AdminSettingsService(), u'admin-settings') return initGDataObject(gdata.apps.adminsettings.service.AdminSettingsService(), u'admin-settings')
def getAuditObject(): def getAuditObject():
import gdata.apps.audit.service import gdata.apps.audit.service
return commonAppsObjInit(gdata.apps.audit.service.AuditService(), u'email-audit') return initGDataObject(gdata.apps.audit.service.AuditService(), u'email-audit')
def getEmailSettingsObject(): def getEmailSettingsObject():
import gdata.apps.emailsettings.service import gdata.apps.emailsettings.service
return commonAppsObjInit(gdata.apps.emailsettings.service.EmailSettingsService(), u'email-settings') return initGDataObject(gdata.apps.emailsettings.service.EmailSettingsService(), u'email-settings')
def geturl(url, dst): def geturl(url, dst):
import urllib2 import urllib2