I don't know what this is so confusing for me. I have the following code to access the gmail api from a cloud function. It works. The issue is that I am using a json file of credentials for the app engine service account. But, this is the default service account for cloud functions, so shouldn't I be able to somehow accomplish the same task without needing to use the credential files?
credentials = service_account.Credentials.from_service_account_info(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject("my.email#email.com")
service = build('gmail', 'v1', credentials=delegated_credentials, cache_discovery=False)
I have tried
from google.auth import compute_engine
credentials = compute_engine.Credentials()
service = build('gmail', 'v1', credentials=credentials, cache_discovery=False)
Related
I'm writing application that is supposed to scan each uploaded/modified file that meets some naming criteria. I need to set up a notification channel for entire drive of my organization, even users private directories. I found this resource but it requires authentication token for user (I suppose it's user that resources are being watched) https://developers.google.com/drive/api/v3/push
I have service account that I currently use to mock users I want to interact as https://developers.google.com/identity/protocols/oauth2/service-account
from google.oauth2 import service_account
from googleapiclient.discovery import build
dir_path = os.path.dirname(os.path.realpath(__file__))
SCOPES = [
'https://www.googleapis.com/auth/drive'
]
SERVICE_ACCOUNT_FILE = dir_path + '/../credentials.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject('userMail#org.com')
service = build('drive', 'v3', credentials=delegated_credentials)
That's how I currently access drive as a user I'd like to check. Is there any way to use that newly created service with delegated credentials to get authentication token required for drive push api?
I want to transfer the ETL scripts (I used to run them on a local machine) to the google cloud, using the Google Functions + Google Scheduler.
Scripts move data from/to Google Analytics (this is an example).
I have a problem with the location of the key file (.p12).
I would like to put it in Google Storage and point the way to it.
Currently KEY_FILE_LOCATION = r'c:/local_path/file.p12'.
Connect to google analytics:
def initialize_analyticsreporting():
credentials = ServiceAccountCredentials.from_p12_keyfile(
SERVICE_ACCOUNT_EMAIL, KEY_FILE_LOCATION, scopes=SCOPES)
http = credentials.authorize(httplib2.Http())
analytics = build('analytics', 'v4', http=http, discoveryServiceUrl=DISCOVERY_URI)
return analytics
I would like to use
from google.cloud import storage
client = storage.Client ()
bucket = client.get_bucket ('utk_owox')
.....
But I can not understand how to do it correctly.
Please be aware that Cloud Functions API client libraries that use application default credentials automatically obtain the built-in service account credentials from the Cloud Functions host at runtime. By default, the client authenticates using the YOUR_PROJECT_ID#appspot.gserviceaccount.com service account.
So if you can configure this service account to have appropriate permissions for the resources that you need to access, it is recommended to relay on it.
Example how to upload file to the bucket in python.
Example how to download file from the bucket in python:
def download_blob(bucket_name, source_blob_name, destination_file_name):
"""Downloads a blob from the bucket."""
storage_client = storage.Client()
bucket = storage_client.get_bucket(bucket_name)
blob = bucket.blob(source_blob_name)
blob.download_to_filename(destination_file_name)
print('Blob {} downloaded to {}.'.format(
source_blob_name,
destination_file_name))
Create credentials from the file as described here:
def get_ga_service(bucket):
download_gcs_file('auth.json', '/tmp/auth.json', bucket)
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'/tmp/auth.json',
scopes=['https://www.googleapis.com/auth/analytics',
'https://www.googleapis.com/auth/analytics.edit'])
# Build the service object.
return build('analytics', 'v3', credentials=credentials, cache_discovery=False)
I want to write a file in a Team Drive from a GAE (standard) in Python 37. I added its service account to my Team Drive members. But I cannot use the default App Engine Credentials to write.
I cannot use App Engine APIs because they are not available in GAE Standard for Python 37.
from google.auth import default
from googleapiclient import discovery
from googleapiclient.http import MediaIoBaseUpload
def upload_file_to_teamdrive(fd, file_name, team_drive_id, mime_type='application/text'):
scopes = ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/drive']
# How to get GAE Credentials ?
credentials, project = default(scopes=scopes)
drive = discovery.build('drive', 'v3', credentials=credentials)
media = MediaIoBaseUpload(fd, mimetype=mime_type)
drive.files().create(
supportsTeamDrives=True,
media_body=media,
body={
'parents': [team_drive_id], # ID of the Team Drive,
'name': file_name
},
fields='id'
).execute()
This code throw a 403 response:
googleapiclient.errors.HttpError: https://www.googleapis.com/upload/drive/v3/files?supportsTeamDrives=true&fields=id&alt=json&uploadType=multipart returned "Insufficient Permission: Request had insufficient authentication scopes."
What is the best way to write from GAE to Drive ? How my GAE could be authenticated with its service account ?
Thanks for your help.
The credentials exposed by the App Engine Environment can only authorize Google Cloud scopes, not any other Google API's scope like https://www.googleapis.com/auth/drive.
You need to use a full service account key (ideally with KMS for security) to access those APIs.
You can have a look at the library I created and always use to connect to Google APIs easygoogle
I have struggled to make this work but did half the job.
Actually I can only read messages from Gmail API, If I try to use the gmail.modify Scope I get an error:
HttpAccessTokenRefreshError: unauthorized_client: Unauthorized client or scope in request.
Here is my code:
# init gmail api
credentials_path = os.path.join(settings.PROJECT_DIR, 'settings/gmail_credential.json')
scopes = ['https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.modify']
credentials = ServiceAccountCredentials.from_json_keyfile_name(credentials_path, scopes=scopes)
delegated_credentials = credentials.create_delegated('my_account#gmail.com')
http_auth = delegated_credentials.authorize(Http())
gmail = build('gmail', 'v1', http=http_auth)
In my service account:
I have set all possibles rĂ´les to my service account "......iam.gserviceaccount.com"
I activated DWD: DwD: Google Apps Domain-wide Delegation is enabled.
I have read somewhere that I need a google work account to give permission to my service account to use gmail.Modify on my my_account#gmail email account. Seems very hard way to just modify a message in an email.
I don't know what to do next.
Based from this documentation, you need to use the client ID from your "Developers Console" as the Client Name in the "Manage API client access" when you're setting your API scopes. Google API does not work as expected with your personal account #gmail.com. You should have organization domain account in Google in format you#your_organisation_domain.
Check these threads:
Google API Python unauthorized_client: Unauthorized client or scope in request
Google API OAuth2, Service Account, "error" : "invalid_grant"
I'm using Python 2.7 and the client library for Google API which I am trying to use to get authenticated access to Spreadsheets like so:
# sa == Service Account
scope = 'https://spreadsheets.google.com/feeds'
credentials = SignedJwtAssertionCredentials(sa_id, sa_key, scope)
http = httplib2.Http()
http = credentials.authorize(http)
build('spreadsheets', 'v2', http=http)
Note this is from a client script and not in Google App Engine. The output of the above is:
File "/Library/Python/2.7/site-packages/apiclient/discovery.py", line
196, in build
version)) apiclient.errors.UnknownApiNameOrVersion: name: spreadsheets version: v2
I know I'm doing this wrong, but I'm having trouble finding any examples of authenticating without using ClientLogin and/or the .NET/Java client libraries.
[UPDATE] The answer may be in the following source example, but I noticed on skimming it that it still uses email/password: https://code.google.com/p/gdata-python-client/source/browse/src/gdata/spreadsheet/service.py
The old Python gdata service libraries support ClientLogin, AuthSub and OAuth 1.0 authentication. All of which have been deprecated. If you wish to use the OAuth 2.0 Service Account credentials you'll need to hack something together like:
def buildSpreadsheetService():
scope = 'https://spreadsheets.google.com/feeds'
credentials = SignedJwtAssertionCredentials(sa_id, sa_key, scope)
http = httplib2.Http()
http = credentials.authorize(http)
build('drive', 'v2', http=http)
sheets = gdata.spreadsheet.service.SpreadsheetsService()
sheets.additional_headers = {'Authorization': 'Bearer %s' % http.request.credentials.access_token}
return sheets