GCP Service Accounts

Varun Tomar
4 min readFeb 5, 2022

Overview

Gsuite integration with GCP service accounts. I found a lot of amazing articles on how GCP service accounts, how scopes work in GCP. However, there is not much info on how Service Accounts interact with resources outside GCP like Gdrive, Gmail, Google Groups, and Calendar. Also, didn’t find much info on how the transition happens from GCP to Gsuite. To be clear this is what I was trying to accomplish.

Steps followed:

  • Created a new service account (APIs & Services > Credentials > Create Credentials > Service Account): download the JSON-based key and save it in a secure place.
  • Create a Developer API key (APIs & Services > Credentials > Create Credentials > API Key).
  • Enable the following APIs (APIs and Services > Library):
Google Drive API
Google Docs API
Google Calendar API
Gmail API
Admin SDK
  • Finally, map the client_id of the created service with the required OAuth2 scopes.

Note: This step requires that you have Super Admin role. Navigate to admin home (Security > Advanced Settings > Manage API Client Access), and add the following scopes:

https://www.googleapis.com/auth/documenthttps://www.googleapis.com/auth/drivehttps://mail.google.com/https://www.googleapis.com/auth/admin.directory.grouphttps://www.googleapis.com/auth/apps.groups.settingshttps://www.googleapis.com/auth/calendar (if you need access to Google Meet)

At this stage, it looked like everything would work and we were ready to test. As usual, it didn’t work. I spent a couple of hours troubleshooting the connection and was continuously getting error 403 when trying to access google drive.

web_1       | Traceback (most recent call last):
web_1 | File "/usr/local/lib/python3.8/site-packages/dispatch/plugins/dispatch_google/groups/plugin.py", line 31, in make_call
web_1 | data = getattr(client, func)(**kwargs).execute()
web_1 | File "/usr/local/lib/python3.8/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
web_1 | return wrapped(*args, **kwargs)
web_1 | File "/usr/local/lib/python3.8/site-packages/googleapiclient/http.py", line 898, in execute
web_1 | raise HttpError(resp, content, uri=self.uri)
web_1 | googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/admin/directory/v1/groups?key=xxxx&alt=json returned "Not Authorized to access this resource/api">
web_1 |
web_1 | During handling of the above exception, another exception occurred:
web_1 |
web_1 | Traceback (most recent call last):
web_1 | File "/usr/local/lib/python3.8/site-packages/tenacity/__init__.py", line 394, in call
web_1 | result = fn(*args, **kwargs)
web_1 | File "/usr/local/lib/python3.8/site-packages/dispatch/plugins/dispatch_google/groups/plugin.py", line 43, in make_call
web_1 | raise TryAgain
web_1 | tenacity.TryAgain
web_1 |
web_1 | The above exception was the direct cause of the following exception:
web_1 |

I thought maybe there was an issue with the tool. Wrote a small function to test if I can even write to any google service without using the tool, tried with google sheets. Wrote this(got the code from one of the youtube videos):

# module to use google sheets and authenticate with json(created in step 1 above)import gspread
from oauth2client.service_account import ServiceAccountCredentials# define the scope
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']credentials = ServiceAccountCredentials.from_json_keyfile_name('<path-to-json-file>', scope)
gc = gspread.authorize(credentials)# name of the spreadsheet to access
# NOTE: spreadsheet should exist and must contain some data
wks = gc.open('test-db').sheet1
print(wks.get_all_records())

This dint work, so there was an issue with switching. One thing, that I didn’t realize or dint understand from the documentation is that we need to create a service account on the Gsuite side as well.

On the Gsuite side:

  • Create a service account( no MFA, no password expiry)
  • Create a custom role or use one of the default roles ( in our case default role was not sufficient so we have to create one. The permissions assigned to the role:

Once you have a Service account in Gsuite set, go back to GCP. Under IAM, add the service account that was created in Gsuite as a member of the project and select the role as “Owner”. This is the account that will be used to delegate access from GCP to Gsuite

Final thoughts:

Learning the tricks of the trade with GCP, drop a message, or comment if I missed something or you find something incorrect.

--

--