buildGAPIObject reworked

This gets everything working but does not address the issue of matching
the admins actual scope list.

You'd better define GA_DOMAIN as it used to come out of oauth2.txt if
it wasn't defined.

I had to add Audit API and Site Verification API to the service account
list of APIs and downloaded a new oauth2service.json.
This commit is contained in:
Ross Scroggs
2015-12-30 23:39:04 -08:00
parent abde922b49
commit bf6c2ef266
4 changed files with 57 additions and 104 deletions

View File

@ -1,34 +0,0 @@
{
"kind": "discovery#restDescription",
"discoveryVersion": "v1",
"id": "email-audit:v1",
"name": "email-audit",
"version": "v1",
"revision": "20130823",
"title": "Email Audit API",
"description": "Lets you peform Google Apps Email Audits",
"ownerDomain": "google.com",
"ownerName": "Google",
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"documentationLink": "https://developers.google.com/admin-sdk/email-audit",
"protocol": "rest",
"baseUrl": "https://apps-apis.google.com/",
"rootUrl": "https://apps-apis.google.com/",
"servicePath": "/a/feeds/compliance/audit/",
"auth": {
"oauth2": {
"scopes": {
"https://apps-apis.google.com/a/feeds/compliance/audit/": {
"description": "Manage email audits"
}
}
}
},
"schemas": {
},
"resources": {
}
}

View File

@ -1,34 +0,0 @@
{
"kind": "discovery#restDescription",
"discoveryVersion": "v1",
"id": "email-settings:v1",
"name": "email-settings",
"version": "v1",
"revision": "20130823",
"title": "Email Settings API",
"description": "Lets you manage Google Apps Email Settings",
"ownerDomain": "google.com",
"ownerName": "Google",
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"documentationLink": "https://developers.google.com/admin-sdk/email-settings",
"protocol": "rest",
"baseUrl": "https://apps-apis.google.com/",
"rootUrl": "https://apps-apis.google.com/",
"servicePath": "/a/feeds/emailsettings/2.0/",
"auth": {
"oauth2": {
"scopes": {
"https://apps-apis.google.com/a/feeds/emailsettings/2.0/": {
"description": "Manage email audits"
}
}
}
},
"schemas": {
},
"resources": {
}
}

View File

@ -104,6 +104,8 @@ GM_MAP_ROLE_ID_TO_NAME = u'ri2n'
GM_MAP_ROLE_NAME_TO_ID = u'rn2i'
# Dictionary mapping User ID to Name
GM_MAP_USER_ID_TO_NAME = u'ui2n'
# Current API scope
GM_API_SCOPE = u'scop'
#
GM_Globals = {
GM_SYSEXITRC: 0,
@ -120,6 +122,7 @@ GM_Globals = {
GM_MAP_ROLE_ID_TO_NAME: None,
GM_MAP_ROLE_NAME_TO_ID: None,
GM_MAP_USER_ID_TO_NAME: None,
GM_API_SCOPE: None,
}
#
# Global variables defined by environment variables/signal files
@ -557,10 +560,10 @@ def doGAMVersion():
GM_Globals[GM_GAM_PATH])
def tryOAuth(gdataObject, scope, soft_errors=False):
scope.append(u'email')
# scope.append(u'email') #TODO: What is this for?
credentials = oauth2client.client.SignedJwtAssertionCredentials(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_EMAIL],
GM_Globals[GM_OAUTH2SERVICE_KEY],
scope=scope, user_agent=GAM_INFO, sub=GC_Values[GC_ADMIN]) # TODO lookup admin user from file
scope=scope, user_agent=GAM_INFO, sub=GC_Values[GC_ADMIN])
http = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL],
cache=GC_Values[GC_CACHE_DIR])
try:
@ -586,7 +589,7 @@ def checkGDataError(e, service):
# 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']:
keep_domain = service.domain
tryOAuth(service)
tryOAuth(service, GM_Globals[GM_API_SCOPE])
service.domain = keep_domain
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:'):
@ -762,19 +765,45 @@ API_VER_MAPPING = {
u'datatransfer': u'datatransfer_v1',
u'directory': u'directory_v1',
u'drive': u'v2',
u'email-audit': u'v1',
u'email-settings': u'v1',
u'gmail': u'v1',
u'groupssettings': u'v1',
u'licensing': u'v1',
u'oauth2': u'v2',
u'reports': u'reports_v1',
u'siteVerification': u'v1',
u'email-settings': u'v1',
u'email-audit': u'v1'
}
def getAPIVer(api):
return API_VER_MAPPING.get(api, u'v1')
SERVICE_API_SCOPE_MAPPING = {
u'admin-settings': [u'https://apps-apis.google.com/a/feeds/domain/',],
u'appsactivity': [u'https://www.googleapis.com/auth/activity', u'https://www.googleapis.com/auth/drive'],
u'calendar': [u'https://www.googleapis.com/auth/calendar',],
u'classroom': [u'https://www.googleapis.com/auth/classroom.courses', u'https://www.googleapis.com/auth/classroom.profile.emails', u'https://www.googleapis.com/auth/classroom.profile.photos',],
u'cloudprint': [u'https://www.googleapis.com/auth/cloudprint',],
u'datatransfer': [u'https://www.googleapis.com/auth/admin.datatransfer',],
u'drive': [u'https://www.googleapis.com/auth/drive',],
u'directory': [u'https://www.googleapis.com/auth/admin.datatransfer', u'https://www.googleapis.com/auth/admin.directory.customer', u'https://www.googleapis.com/auth/admin.directory.device.chromeos',
u'https://www.googleapis.com/auth/admin.directory.device.mobile', u'https://www.googleapis.com/auth/admin.directory.device.mobile.action',
u'https://www.googleapis.com/auth/admin.directory.domain', u'https://www.googleapis.com/auth/admin.directory.group', u'https://www.googleapis.com/auth/admin.directory.group.member',
u'https://www.googleapis.com/auth/admin.directory.notifications', u'https://www.googleapis.com/auth/admin.directory.orgunit', u'https://www.googleapis.com/auth/admin.directory.resource.calendar',
u'https://www.googleapis.com/auth/admin.directory.rolemanagement', u'https://www.googleapis.com/auth/admin.directory.user', u'https://www.googleapis.com/auth/admin.directory.user.alias',
u'https://www.googleapis.com/auth/admin.directory.user.security', u'https://www.googleapis.com/auth/admin.directory.userschema',],
u'email-audit': [u'https://apps-apis.google.com/a/feeds/compliance/audit/',],
u'email-settings': [u'https://apps-apis.google.com/a/feeds/emailsettings/2.0/',],
u'gmail': [u'https://mail.google.com/',],
u'groupsettings': [u'https://www.googleapis.com/auth/apps.groups.settings',],
u'licensing': [u'https://www.googleapis.com/auth/apps.licensing',],
u'reports': [u'https://www.googleapis.com/auth/admin.reports.audit.readonly', u'https://www.googleapis.com/auth/admin.reports.usage.readonly',],
u'siteVerification': ['https://www.googleapis.com/auth/siteverification',],
}
def getServiceAPIScope(api):
return SERVICE_API_SCOPE_MAPPING.get(api, [])
def getAPIScope(service):
api_scopes = service._rootDesc[u'auth'][u'oauth2'][u'scopes']
granted_scopes = api_scopes # TODO fix to lookup from file
@ -795,9 +824,7 @@ def getServiceFromDiscoveryDocument(api, version, http=None):
systemErrorExit(4, MESSAGE_NO_DISCOVERY_INFORMATION.format(disc_file))
return googleapiclient.discovery.build_from_document(discovery, base=u'https://www.googleapis.com', http=http)
def buildGAPIObject(api, act_as=None, soft_errors=False):
if not act_as:
act_as = GC_Values[GC_ADMIN] # TODO lookup admin user from file
def getOAuth2ServiceDetails():
if not GM_Globals[GM_OAUTH2SERVICE_KEY]:
json_string = readFile(GC_Values[GC_OAUTH2SERVICE_JSON], continueOnError=True, displayError=True)
if not json_string:
@ -814,39 +841,41 @@ def buildGAPIObject(api, act_as=None, soft_errors=False):
printLine(MESSAGE_WIKI_INSTRUCTIONS_OAUTH2SERVICE_JSON)
printLine(GAM_WIKI_CREATE_CLIENT_SECRETS)
systemErrorExit(17, MESSAGE_OAUTH2SERVICE_JSON_INVALID.format(GC_Values[GC_OAUTH2SERVICE_JSON]))
def buildGAPIObject(api, act_as=None, soft_errors=False):
sub = act_as if act_as else GC_Values[GC_ADMIN]
getOAuth2ServiceDetails()
GM_Globals[GM_API_SCOPE] = getServiceAPIScope(api)
credentials = oauth2client.client.SignedJwtAssertionCredentials(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_EMAIL],
GM_Globals[GM_OAUTH2SERVICE_KEY],
scope=GM_Globals[GM_API_SCOPE], user_agent=GAM_INFO, sub=sub)
http = credentials.authorize(httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL],
cache=GC_Values[GC_CACHE_DIR]))
version = getAPIVer(api)
if api in [u'directory', u'reports', u'datatransfer']:
api = u'admin'
http = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL],
cache=GC_Values[GC_CACHE_DIR])
try:
service = googleapiclient.discovery.build(api, version, http=http, cache_discovery=False)
return googleapiclient.discovery.build(api, version, http=http, cache_discovery=False)
except googleapiclient.errors.UnknownApiNameOrVersion:
service = getServiceFromDiscoveryDocument(api, version, http)
return getServiceFromDiscoveryDocument(api, version, http)
except httplib2.ServerNotFoundError as e:
systemErrorExit(4, e)
scope = getAPIScope(service)
credentials = oauth2client.client.SignedJwtAssertionCredentials(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_EMAIL],
GM_Globals[GM_OAUTH2SERVICE_KEY],
scope=scope, user_agent=GAM_INFO, sub=act_as)
try:
service._http = credentials.authorize(http)
service._http.request.credentials.refresh(http)
except oauth2client.client.AccessTokenRefreshError, e:
if e.message in [u'access_denied',
u'unauthorized_client: Unauthorized client or scope in request.',
u'access_denied: Requested client not authorized.']:
systemErrorExit(5, MESSAGE_CLIENT_API_ACCESS_DENIED.format(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID], u','.join(scope)))
systemErrorExit(5, MESSAGE_CLIENT_API_ACCESS_DENIED.format(GM_Globals[GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID], u','.join(GM_Globals[GM_API_SCOPE])))
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, e))
if soft_errors:
return False
sys.exit(4)
return service
def commonAppsObjInit(appsObj, scope):
if not tryOAuth(appsObj, scope):
getOAuth2ServiceDetails()
GM_Globals[GM_API_SCOPE] = scope
if not tryOAuth(appsObj, GM_Globals[GM_API_SCOPE]):
doRequestOAuth()
tryOAuth(appsObj, scope)
tryOAuth(appsObj, GM_Globals[GM_API_SCOPE])
#Identify GAM to Google's Servers
appsObj.source = GAM_INFO
#Show debugging output if debug.gam exists
@ -856,24 +885,18 @@ def commonAppsObjInit(appsObj, scope):
def getAdminSettingsObject():
import gdata.apps.adminsettings.service
service = getServiceFromDiscoveryDocument(u'admin-settings', u'v1')
scope = service._rootDesc[u'auth'][u'oauth2']['scopes'].keys()
return commonAppsObjInit(gdata.apps.adminsettings.service.AdminSettingsService(),
scope)
getServiceAPIScope(u'admin-settings'))
def getAuditObject():
import gdata.apps.audit.service
service = getServiceFromDiscoveryDocument(u'email-audit', u'v1')
scope = service._rootDesc[u'auth'][u'oauth2']['scopes'].keys()
return commonAppsObjInit(gdata.apps.audit.service.AuditService(),
scope)
getServiceAPIScope(u'email-audit'))
def getEmailSettingsObject():
import gdata.apps.emailsettings.service
service = getServiceFromDiscoveryDocument(u'email-settings', u'v1')
scope = service._rootDesc[u'auth'][u'oauth2']['scopes'].keys()
return commonAppsObjInit(gdata.apps.emailsettings.service.EmailSettingsService(),
scope)
getServiceAPIScope(u'email-settings'))
def geturl(url, dst):
import urllib2

View File

@ -11,8 +11,6 @@ for d in a.datas:
a.datas += [('httplib2/cacerts.txt', 'httplib2\cacerts.txt', 'DATA')]
a.datas += [('cloudprint-v2.json', 'cloudprint-v2.json', 'DATA')]
a.datas += [('admin-settings-v1.json', 'admin-settings-v1.json', 'DATA')]
a.datas += [('email-settings-v1.json', 'email-settings-v1.json', 'DATA')]
a.datas += [('email-audit-v1.json', 'email-audit-v1.json', 'DATA')]
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,