Skip to content

Instantly share code, notes, and snippets.

@Avantol13
Last active April 30, 2018 20:44
Show Gist options
  • Save Avantol13/ce3b5d9d8eee48006300f64c5b46cd40 to your computer and use it in GitHub Desktop.
Save Avantol13/ce3b5d9d8eee48006300f64c5b46cd40 to your computer and use it in GitHub Desktop.
Issues with Listing Groups in Google Cloud Identity by use of Admin Directory v1 API and Domain Wide Delegation of a Service Account in GCP
from config import GOOGLE_APPLICATION_CREDENTIALS
from config import GOOGLE_APPLICATION_CREDENTIALS_P12
from config import GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client.service_account import ServiceAccountCredentials
def connection_test():
scopes = ["https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.group.readonly",
"https://www.googleapis.com/auth/admin.directory.group.member",
"https://www.googleapis.com/auth/admin.directory.group.member.readonly"]
credentials = ServiceAccountCredentials.from_json_keyfile_name(
GOOGLE_APPLICATION_CREDENTIALS, scopes=scopes
)
# credentials.scopes is empty at this point... ???
# - It's not the scopes I set above
delegated_credentials = credentials.create_delegated(GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL)
# delegated_credentials.scopes is empty here too...
# tried manually setting, still got unauthorized_client error
http_auth = delegated_credentials.authorize(Http())
directory_service = build('admin', 'directory_v1', http=http_auth)
response = directory_service.groups().list().execute()
print(response)
def connection_test_p12():
scopes = ["https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.group.readonly",
"https://www.googleapis.com/auth/admin.directory.group.member",
"https://www.googleapis.com/auth/admin.directory.group.member.readonly"]
credentials = ServiceAccountCredentials.from_p12_keyfile(
GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL,
GOOGLE_APPLICATION_CREDENTIALS_P12,
'notasecret',
scopes=scopes)
print("----------------------------------------------------------")
print("Service account email: " + str(credentials.service_account_email))
print("Service account scope: " + str(credentials.scopes))
print(" Service account id: " + str(credentials.client_id))
print("----------------------------------------------------------")
delegated_credentials = credentials.create_delegated(GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL)
http_auth = delegated_credentials.authorize(Http())
directory_service = build('admin', 'directory_v1', http=http_auth)
response = directory_service.groups().list().execute()
print(response)
if __name__ == "__main__":
connection_test()
connection_test_p12()
# domain used for creation of Cloud Identity and subsequently, as the organization for GCP
from config import GOOGLE_IDENTITY_DOMAIN
# SA credentials that have Owner access on a project in the GCP org
from config import GOOGLE_APPLICATION_CREDENTIALS
# cloud identity admin email is a Super Admin in the domain
from config import GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client.service_account import ServiceAccountCredentials
def connection_test():
scopes = ["https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.group.readonly",
"https://www.googleapis.com/auth/admin.directory.group.member",
"https://www.googleapis.com/auth/admin.directory.group.member.readonly",
"https://www.googleapis.com/auth/admin.directory.user.security"]
credentials = ServiceAccountCredentials.from_json_keyfile_name(
GOOGLE_APPLICATION_CREDENTIALS, scopes=scopes
)
delegated_credentials = credentials.create_delegated(GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL)
http_auth = delegated_credentials.authorize(Http())
directory_service = build('admin', 'directory_v1', http=http_auth)
response = directory_service.groups().list(domain=GOOGLE_IDENTITY_DOMAIN).execute()
print(response)
if __name__ == "__main__":
connection_test()
"""
Traceback (most recent call last):
File "test.py", line 41, in <module>
connection_test()
File "test.py", line 35, in connection_test
domain=GOOGLE_IDENTITY_DOMAIN).execute()
File ".../oauth2client/util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File ".../googleapiclient/http.py", line 837, in execute
method=str(self.method), body=self.body, headers=self.headers)
File ".../googleapiclient/http.py", line 163, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File ".../oauth2client/transport.py", line 153, in new_request
credentials._refresh(orig_request_method)
File ".../oauth2client/client.py", line 765, in _refresh
self._do_refresh_request(http_request)
File ".../oauth2client/client.py", line 834, in _do_refresh_request
raise HttpAccessTokenRefreshError(error_msg, status=resp.status)
oauth2client.client.HttpAccessTokenRefreshError:
unauthorized_client: Client is unauthorized to retrieve access tokens using this method.
"""
# using new updated examples (docs updated 04 APRIL 2018)
# https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
from google.oauth2 import service_account
import googleapiclient.discovery
# domain used for creation of Cloud Identity and subsequently, as the organization for GCP
from config import GOOGLE_IDENTITY_DOMAIN
# SA credentials that have Owner access on a project in the GCP org
from config import GOOGLE_APPLICATION_CREDENTIALS
# cloud identity admin email is a Super Admin in the domain
from config import GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL
SCOPES = [
"https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.group.readonly",
"https://www.googleapis.com/auth/admin.directory.group.member",
"https://www.googleapis.com/auth/admin.directory.group.member.readonly",
"https://www.googleapis.com/auth/admin.directory.user.security"
]
def new_documented_instructions():
credentials = service_account.Credentials.from_service_account_file(
GOOGLE_APPLICATION_CREDENTIALS, scopes=SCOPES)
delegated_credentials = credentials.with_subject(
GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL)
directory_service = googleapiclient.discovery.build(
'admin', 'directory_v1', credentials=delegated_credentials)
response = (
directory_service.groups().list(
domain=GOOGLE_IDENTITY_DOMAIN).execute()
)
print(response)
if __name__ == "__main__":
new_documented_instructions()
"""
Traceback (most recent call last):
File "test.py", line 40, in <module>
new_documented_instructions()
File "test.py", line 34, in new_documented_instructions
domain=GOOGLE_IDENTITY_DOMAIN).execute()
File ".../oauth2client/util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File ".../googleapiclient/http.py", line 837, in execute
method=str(self.method), body=self.body, headers=self.headers)
File ".../googleapiclient/http.py", line 163, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File ".../google_auth_httplib2.py", line 187, in request
self._request, method, uri, request_headers)
File ".../google/auth/credentials.py", line 121, in before_request
self.refresh(request)
File ".../google/oauth2/service_account.py", line 322, in refresh
request, self._token_uri, assertion)
File ".../google/oauth2/_client.py", line 145, in jwt_grant
response_data = _token_endpoint_request(request, token_uri, body)
File ".../google/oauth2/_client.py", line 111, in _token_endpoint_request
_handle_error_response(response_body)
File ".../google/oauth2/_client.py", line 61, in _handle_error_response
error_details, response_body)
google.auth.exceptions.RefreshError: ('unauthorized_client: Client is
unauthorized to retrieve access tokens using this method.',
u'{\n "error" : "unauthorized_client",\n
"error_description" :
"Client is unauthorized to retrieve access tokens using this method."\n}')
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment