Reputation: 11
I am developing a Python 3.7 app which aims to be deployed on Google App Engine. The goal of this app is to query the Google Workspace Enterprise License Manager API in order to retrieve the list of users per Google Workspace license. So to summarize, the main goal of this app is to query the method licenseAssignments.listForProduct of the API.
I already developed an app which manage GDrive file via GSuite API, using a Service Account. So for this new app, and for testing purpose, I keep using the same Service Account. Our GSuite Admin granted this Service Account with the scope
"https://www.googleapis.com/auth/apps.licensing".
I follow the reference guide so the Enterprise License Manager API is enable on my project on GCP, and the API is enabled on Google Workspace Admin console (our GSuite Admin use the Google Workspace Enterprise License Manager API via Powershell successfully).
Here is my code:
from google.oauth2 import service_account
from googleapiclient.discovery import build
CUSTOMER_ID = 'HIDDEN_FOR_SECURITY_PURPOSE'
SERVICE_ACCOUNT_FILE = "service_account_file.json"
SCOPES = "https://www.googleapis.com/auth/apps.licensing"
def get_cred():
try:
creds = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES
)
except Exception as e:
print(e)
return creds
if __name__ == "__main__":
creds = get_cred()
service = build('licensing', 'v1', credentials=creds)
try:
response = service.licenseAssignments().listForProduct(customerId='HIDDEN_FOR_SECURITY_PURPOSE', productId='Google-Apps' ).execute()
except Exception as e:
print(e)
When running this code via App Engine, or in my computer via Jupyter Notebook, I get this error:
('No access token in response.', {'id_token': 'JWT_TOKEN_HIDDEN_FOR_SECURITY_PURPOSE'})
Lib versions:
Thanks for your help!
Edit:
I deployed the following code on GAE:
from google.cloud import bigquery
from google.oauth2 import service_account
from googleapiclient.discovery import build
import requests
import json
import pandas as pd
SERVICE_ACCOUNT_FILE = "service_account_file.json"
SCOPES = ["https://www.googleapis.com/auth/apps.licensing"]
app = Flask(__name__)
def get_cred():
try:
creds = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES
)
except Exception as e:
print(e)
return e
return creds
@app.route("/")
def main():
print("## Start")
creds = get_cred()
service = build("licensing", "v1", credentials=creds)
try:
response = (
service.licenseAssignments()
.listForProduct(customerId="HIDDEN_FOR_SECURITY_PURPOSE", productId="Google-Apps")
.execute()
)
print("## Response={}".format(response))
except Exception as e:
print(e)
print("## End")
return "OK"
if __name__ == "__main__":
# This is used when running locally only. When deploying to Google App
# Engine, a webserver process such as Gunicorn will serve the app. This
# can be configured by adding an `entrypoint` to app.yaml.
app.run(host="127.0.0.1", port=8080, debug=True)
# [END gae_python37_app]
I get the error <HttpError 503 when requesting https://licensing.googleapis.com/apps/licensing/v1/product/Google-Apps/users?customerId=[HIDDEN_FOR_SECURITY_PURPOSE]&alt=json returned "Backend Error". Details: "Backend Error">
.
Upvotes: 0
Views: 1014
Reputation: 1
I had same error 503. To bypass this error you need to impersonate the request. something like this:
LICENZES_SCOPE = ['https://www.googleapis.com/auth/apps.licensing']
client_config = {
'auth_json': 'service_account_file.json',
'account_to_impersonate': '[email protected]'
}
credentials = service_account.Credentials.from_service_account_info(client_config.get('auth_json'), scopes=LICENZES_SCOPE)
credentials_wiht_subject = credentials.with_subject(client_config.get('account_to_impersonate'))
service = googleapiclient.discovery.build('licensing', 'v1', credentials=credentials_wiht_subject)
response = service.licenseAssignments().listForProduct(customerId=primary_domain,productId=product_id).execute()
print(f'{response=}')
Tested by me on windows 11 python 3.10
Upvotes: 0
Reputation: 23
is your service account using Domain wide delegation? and if so is it impersonating a user that has RBAC permissions to view the licenses?
And autenticate against the user you are trying to impersonate, and see if you get a response.
If you dont you likley need to impersonate a Super Admin user, and if your not doing impersonateion that needs to be enabled in the GCP console first, then the scope needs to be autorized on the domain, which you mentioned has happened.
Upvotes: 0