I have a google cloud function that I can invoke using gcloud cli using a service account with the necessary IAM permissions
gcloud auth activate-service-account 'service-account-email' --key-file=google_key.json
gcloud functions call opt_manual --data '{some-json}'
this works just fine.
I'm trying to implement a similar call using official ruby sdk https://github.com/googleapis/google-cloud-ruby/tree/main/google-cloud-functions-v1
name = "opt_manual"
data = '{some-json}'
client = ::Google::Cloud::Functions::V1::CloudFunctionsService::Client.new do |config|
config.credentials = "google_key.json"
end
client.get_function ::Google::Cloud::Functions::V1::GetFunctionRequest.new(name: name)
# =>
# Permission denied on resource project opt_manual.. debug_error_string:{
# "created":"#1636730694.210272000",
# "description":"Error received from peer ipv4:142.251.36.202:443",
# "file":"src/core/lib/surface/call.cc",
# "file_line":1070,
# "grpc_message":"Permission denied on resource project opt_manual.",
# "grpc_status":7
# } (Google::Cloud::PermissionDeniedError)
The service account includes the following permissions:
Cloud Functions Admin
Cloud Functions Invoker
Service Account User
Workload Identity User
Cloud function principles include correct service account.
Despite all of that I'm still getting PermissionDeniedError maybe someone had a similar case and remember how it could be fixed? Keep in mind in the same project I access bigquery and cloud storage using official SDK using the same service account without any problem.
Can you replace the following with values and try it instead of opt_manual:
projects/{project}/locations/{location}/functions/opt_manual
Your Service Account likely has too many permissions. You should need only Cloud Functions Invoker (roles/cloudfunctions.invoker).
Explanation the underlying method call is projects.locations.functions.get. Unfortunately, the Ruby API documentation for GetFunctionsRequest doesn't explain this. APIs Explorer is the definitive tool for understanding Google's REST APIs.
Related
I have oAuth 2.0 implemented in java as per recommended in the following link https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth.
The Azure application which I created to get consent was using "Exchange API" earlier. Since I am migrating to a new domain, I thought of Instead of migrating my existing Azure applications I can have them newly created and replace the applicationId wherever required. When I started creating a new application I didn't find "Exchange API" as an option for API Permission, so went with "Graph API" as "Exchange API" was not available.
If I use the old code where the scope is https://outlook.office365.com/Calendars.Read against the new application created (where API Permission is using Graph API) and create an OAuth token with ExchangeService as [ewsClient.Url = https://outlook.office365.com/EWS/Exchange.asmx] it is working as expected.
But when I change my Scope to https://graph.microsoft.com/.default (As I changed the API to Graph in my azure application, I thought my scope also has to be changed accordingly) and having ExchangeService as [ewsClient.Url = https://outlook.office365.com/EWS/Exchange.asmx ] it is throwing 401 at ExchangeService.bindToFolder() method from Microsoft ews-java-api jar.
Any suggestions on
what has to be changed to avoid 401.
Can I still use https://outlook.office365.com/Calendars.Read as scope and https://outlook.office365.com/EWS/Exchange.asmx as my ExchangeService URL even though the azure application which I use to generate the OAuth token is having API permissions through Microsoft Graph?
https://outlook.office365.com/Calendars.Read
This isn't a Scope that will work with EWS it sounds like you maybe use the Outlook V2 endpoint as that would be a valid scope and audience for that API (which has now been depreciated).Depending on what flow you using the only valid scope for EWS are EWS.AccessAsUser.All for delegate flows and full_access_as_app for Application (Client_credentials) flow. In the first doc you linked it give a method of modifying the manifest as they removed the method of adding the permission in the portal. Graph permission won't work in EWS so https://graph.microsoft.com/.default won't be a valid scope it may return a token but that token wont have a valid audience for EWS. If you using the Client_Crendentials flow and you have given full_access_as_app then you need to use https://outlook.office365.com/.default or for delegate flow you use https://outlook.office365.com/EWS.AccessAsUser.All. It sounds like from you code you may have either both EWS or some Outlook V2 code but you need to show some of your code. What might be an easier solve for you it to look at your old manifest and look at the Guid's of the permission being used you can actually cut and paste these into the new manifest then consent to those and everything will work.
So, I've followed the documentation found here.
I then created an oauth 2.0 web application here.
After I took the client ID and I used it in the Manage API Client Access for the GSuite Admin following the documentation here to add the scopes. However, when I go to my app and I hit the "Sign in with Google" I get a:
400 Invalid Scopes
{invalid=['https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/userinfo.email']}
Both of the scopes above have been added to the Manage API Client Access screens.
Any steps I might be missing?
TLDR; Github pipeline + docker build args with spaces are a no-go. Use secrets and envs.
Found the solution. The issue was that I was defining my scopes in the CI pipeline (github yml) and passing it to my docker file as a build arg which was being converted to an ENV. This didn't work well since there was a space in the string. I moved the two scopes to a github secret and exported it as an ENV which is then secure env'd in the docker file.
The main use case is using IPython as CLI to my own Google accounts. What I am really after is minmizing the fussing around between starting the IPython shell and actually issuing usefull calls against the API.
The docs for authenticating with Google APIs focus on setting up application which other user will use to access their data.
This leads to a lengthy Oauth dance involving a browser in order to allow other users to authenticate without compromising their credential.
However, I do not mind sharing my private credentials with myself. I am not planning on sharing the code. If I did share the code I would use something like dotenv to separate the credentials from the code.
Twitter provides developers a second set of credentials
that allows developers to access their own accounts for testing.
Thus it is possible to access ones own account programmatically
by just providing to sets of credentials: the developer credentials that allow the calls to the API and the other credentials that grant access to the developers own data. For example:
from twitter import *
t = Twitter(
auth=OAuth(token, token_key, con_secret, con_secret_key))
# Get your "home" timeline
t.statuses.home_timeline()
# Update your status
t.statuses.update(
status="Tweeting from Python")
Where con_secret* are the developer credentials and
and token* are the account access credentials.
How can I do something equally simple with Google APIs?
Where can I get credentials to access my own account?
How would I use them in Google API?
As an example what would be the simplest procedure for retrieving the contents from one of my own Youtube playlists?
I have com to think that a Python headless browser library could be give me what I need. I have asked a related question on SE Software Recommendations
https://softwarerecs.stackexchange.com/questions/35744/python-headless-browser-library-for-oauth2-authentication-from-ipython-console
I would like to download a set of credentials
Google offers this ability through it's client_secrets.json file. There are different ways to download this, depending on the type of account you want to use (Web application, installed application, Service account). The different techniques can be found here .
Store the credentials locally and keep using them without requiring
new credentials every call
This also isn't a problem, the client secret is valid until you renew it - AFAIK there is no automatic expiry unless you specify otherwise.
Once you have downloaded your client_secrets.json, store the file in a non-public directory (normally inside your project directory/config).
Similar to the downloading of the file, there are different techniques (flow classes) to use the JSON file depending on what type of account you are using. As an example, the below would be used for installed and web applications;
from oauth2client.client import OAuth2WebServerFlow
...
flow = OAuth2WebServerFlow(client_id='your_client_id',
client_secret='your_client_secret',
scope='scope URL here',
redirect_uri='http://example.com/auth_return')
Other flow class examples can be found here
Hope this helps - If you need further information, the official documentation (which be warned, can be incredibly inaccurate and confusing) can be found here https://developers.google.com/api-client-library/python/guide/aaa_oauth
There's a lot of new information regarding how to programatically download Google Play reports using gsutil tool. Google Play uses a bucket to store these reports, just like Google Cloud Storage does. I'm already able to download reports from Google Play bucket without a problem. For example:
gsutil cp gs://pubsite_prod_rev_<my project id>/stats/installs/installs_<my app id>_201502_overview.csv .
On the other hand, gsutil offers a feature to watch Google Cloud Storage buckets, so you can receive notifications every time an object in the bucket changes (gsutil notification watchbucket). I am also able to enable notifications in buckets created in my own Google Cloud projects.
The problem is, I'm not able to enable notifications in my Google Play bucket. Is it even possible? I get an AccessDeniedException: 403 Forbidden error when calling:
gsutil notification watchbucket -i playnotif -t sometoken https://notif.mydomain.com gs://pubsite_prod_rev_<my project id>
I've followed all the steps here, being specially careful with those regarding identifying a domain to receive notifications.
As I mentioned above, I'm already able to do all the process I need, but with my own buckets in Google Cloud, not with the Google Play bucket.
The Google Play project has been linked to a Google Cloud project. It did so automatically when I enabled Google Play API access (Google Play Developer Console -> Configuration (left menu) -> API access).
The Google Play project owner and my own Google Cloud project owner is the same.
This owner has successfully registered and validated the domain used to receive the notifications (following the example, I validated both just in case: notif.mydomain.com and mydomain.com, using https in the Google Webmaster Tools)
These domains have also been whitelisted in the Google Developers Console (left sidebar -> APIs & Auth -> Push).
I've successfully enabled notifications in my own Google Cloud buckets using either the project owner account or a service account I created. I've already tried using both (owner and a corresponding service account) in the Google Play bucket, without success.
Any ideas will be greatly appreciated. Thanks!
EDIT:
I had already followed the steps here, but using different procedures (as explained in the comment below). Following Nikita's suggestion, I tried to follow the steps using the same procedure.
So I configured gsutil (through gcloud) to use the owner account:
gcloud config set account owner-of-play-store-project#gmail.com
and while trying to grant full access to the service account, I encountered this error:
$ gsutil acl ch -u my-play-store-service-account#developer.gserviceaccount.com:FC gs://pubsite_prod_rev_my-bucket-id
CommandException: Failed to set acl for gs://pubsite_prod_rev_my-bucket-id/. Please ensure you have OWNER-role access to this resource.
So, I tried to list the default ACL for this bucket, and found:
$ gsutil defacl get gs://pubsite_prod_rev_my-bucket-id
No default object ACL present for gs://pubsite_prod_rev_my-bucket-id. This could occur if the default object ACL is private, in which case objects created in this bucket will be readable only by their creators. It could also mean you do not have OWNER permission on gs://pubsite_prod_rev_my-bucket-id and therefore do not have permission to read the default object ACL.
[]
Conclusion:
It really makes me think that, even using the project owner account, this account doesn't have the OWNER role on the Play Store bucket. This means ACLs can't be modified, not even listed, as well as notifications can't be enabled since, sadly, we don't really own the bucket.
At the moment, you cannot. Google Play owns these buckets, and end users do not have the bucket FULL_CONTROL access necessary to subscribe to Object Change Notifications.
I am trying to access google adwords api with 'google-adwords-api' ruby gem.
I have configured as per required. I have also set an test mcc account and api application. But still I am not able to access the api. It is giving following error
QuotaCheckError.ACCOUNT_INACTIVE
Also I am trying to set the environment to sandbox which gives following error
Environment 'SANDBOX' does not support version 'v201306' (AdsCommon::Errors::Error)
In documentationn it is mentioned that we can access api with test account even before approval.
Thanks in advance
I got fixed this.
The developer token needed for accessing the ad-words api should be created from production account and not from test account.