Link a GCP project to a billing account using a service account - api

I'm trying to create a new project using GCP's API and link it to a billing account.
I have a service account I use to authenticate to GCP, this service account is a part of project1.
This service account has the following permission on the organization level:
Billing Account User
Project Billing Manager
I also tried to give this service account Organization Administrator, which didn't help as it isn't a permissions issue.
Using the API I've created a new project - project 2, and I was able to enable Cloud Billing API and Deployment Manager API for project 2.
For some reason, when I'm trying to follow the API reference on how to enable billing for a GCP project, the request fails with 403 (Permission Denied).
Here is a sample request I'm trying to make:
curl --location --request PUT 'https://cloudbilling.googleapis.com/v1/projects/project2/billingInfo' --header 'Authorization: Bearer ya29.blablabla' --header 'Content-Type: application/json' --data-raw '{"billingAccountName": "billingAccounts/1234-9248-4321"}'
The reason this request fails is that for some reason it is trying to link project1 (where the service account resides) to this billing account instead of project2.
Here is the response I'm getting:
{ "error": {
"code": 403,
"message": "Cloud Billing API has not been used in project project1_number before or it is disabled. Enable it by visiting
https://console.developers.google.com/apis/api/cloudbilling.googleapis.com/overview?project=project1_number
then retry. If you enabled this API recently, wait a few minutes for
the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developers console API activation",
"url": "https://console.developers.google.com/apis/api/cloudbilling.googleapis.com/overview?project=project1_number"
}
]
},
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SERVICE_DISABLED",
"domain": "googleapis.com",
"metadata": {
"service": "cloudbilling.googleapis.com",
"consumer": "projects/project1_number"
}
}
] } }
If I'm trying to enable the billing API for project1, I'm starting to get 400's with "Unexpected token" message.
Is there a way (using the API) to link project2 to my billing account using a service account that resides on project1?

You have two problems:
The Billing API is not enabled.
The service account does not have permission to access the Billing API.
To enable the Billing API, you must use an identity that has the role Service Usage Admin aka roles/serviceusage.serviceUsageAdmin
Use the Google Cloud Console GUI or use the CLI example:
gcloud services enable cloudbilling.googleapis.com
Is there a way (using the API) to link project2 to my billing account
using a service account that resides on project1?
Using an API, No. Using the GUI, Yes. To allow a service account to access a Billing Account you must complete this task in the Billing Account GUI. For personal Google Cloud Accounts, you cannot add additional members (the limit is one identity).
Tip: If you are expecting to be able to access billing data, you will not be able to. Instead, enable Google Cloud Billing export to BigQuery and then execute queries to retrieve billing data.

Related

GCP text-to-Speech API auth issue

I was trying the above api in postman. Here is the request json:
{
"input":{
"text":"Flutter is awesome!"
},
"voice":{
"languageCode":"en-gb",
"name":"en-GB-Standard-A",
"ssmlGender":"FEMALE"
},
"audioConfig":{
"audioEncoding":"MP3"
}
}
for auth, i chose Bearer in postman auth and first executed the following command in my terminal to get the token:
gcloud auth application-default print-access-token
i pasted this token in auth header, and i received the following response :
{
"error": {
"code": 403,
"message": "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the texttospeech.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/. If you are getting this error with curl or similar tools, you may need to specify 'X-Goog-User-Project' HTTP header for quota and billing purposes. For more information regarding 'X-Goog-User-Project' header, please check https://cloud.google.com/apis/docs/system-parameters.",
"status": "PERMISSION_DENIED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SERVICE_DISABLED",
"domain": "googleapis.com",
"metadata": {
"consumer": "projects/12345678910",
"service": "texttospeech.googleapis.com"
}
}
]
}
}
I am very new to GCP in general and don't know how to navigate this issue. For additional context, i am trying to make a REST API call where i send the text and get a base64encoded string containig audio back. Any help is appreciated.
This is confusing/complex but the error is helpful:
Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the texttospeech.googleapis.com.
NOTE You can try this method using Google's APIs Explorer at this link
text.synthesize.
The issue is that gcloud is an OAuth2 application and tokens issued by gcloud either using gcloud auth print-[access|identity]-token and gcloud auth application-default print-access-token are issued against a Google-managed project (that Google provides for gcloud) and -- importantly -- not one of your own projects.
Google wants to provide gcloud for its users but does not want to provide arbitrary API access (for free) to its users. Hence the "not supported" part of the error.
The solution (as described) is that you should:
Use (or create) your own Google Project
Enable the Text-to-Speech service (API) in this project
Create a Service Account and key
gcloud auth activate-service-account providing the Service Account key
gcloud auth print-access-token to get an access token to invoke the API
See the following link for the steps:
https://cloud.google.com/text-to-speech/docs/libraries

How do I get ID of the current logged-in user in the Sandbox environment from Platform of Trust?

Every user getting registered to the Sandbox gets added to the Platform as an Identity.
How can I get the Identity ID of my user when I log in to the Sandbox environment?
I need this user ID for creating links between identities as is exemplified in this guide after creating group.
Another way is to check request from browser's network after you log in:
https://world-sandbox.oftrust.net/api/me
See the id in response
Using the /me endpoint of Login API in Platform of Trust, you can retrieve the identity ID of the user currently logged in to Sandbox.
Sample request in cURL is:
curl -i -X GET \
-H "Authorization: Bearer eyJ0eXAiOiJ...qW1QhdEsJLNGV2YA" \
"https://api-sandbox.oftrust.net/me"
On success, you should get the following response:
HTTP/1.0 200
{
"#context": "https://standards.oftrust.net/v2/Context/Identity/LegalParty/Person/",
"#type": "Person",
"#id": "33237067-14c3-4801-9e50-bf08406406e2",
"email": "user#example.com",
"role": "developer",
"firstName": "Anna",
"lastName": "Bar"
}
You can get your Bearer token (valid for 24 hours) from the Sandbox environment.
You may need to obtain the identity ID for your user when you are building apps in the Platform and creating authorization flow for the intended users.
You can access the API documentation for Platform of Trust Login API here.

Google API analytics extraction permissions

Problem: cannot access Google Analytics View using API service (json credentials)
PHP Fatal error: Uncaught Google_Service_Exception: {
"error": {
"code": 403,
"message": "User does not have sufficient permissions for this profile.",
"errors": [
{
"message": "User does not have sufficient permissions for this profile.",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}
Detail: When creating a Google analytics account via "Google Account A [analytics]" and creating an API service "Google Account A [developer console - JSON credentials] I can access Analytics data using the API.
I've been given access (Edit, Collaborate, Read & Analyse, Manage Users ) to "Google Account B [Analytics]. Logged into a web browser I can access and see the GoogleAnalytics of Google Account B and have setup a 'Custom View' to access Custom dimensions.
(GA A [Analytics] -> GA A [Dev console]) --- Access OK
(GA B [Analtyics] -> GA A [Permission granted] -> GA A [Dev console]) --- Error
I am assuming if Google Account B created an API service and passed the credentials.json key file things would run smoothly. I want to use this as a last resort as the client will have no idea how to set this up.
I am looking for a reason (and solution to) why Google Account A can see the analytics view of (Google Account B) but the API service of Google Account A cannot access the view.
Original setup/testing: Google Analytics UserID API extraction
Thanks in advance
Answer: A service account in Google API (that is created when setting up the API project) is associated with a user.
This particular user must also be granted access by the owning Google Analytics account.
i.e. Service account xxxx.yyyy#googlepais.com that is created when
setting up a Google API service account.
Something sounds so simple but I was under the impression that since this account was created by a main Google account that already has access that these permissions were implicitly inherited... Not the case but kind of makes sense. And provides a lot more fine grained control.
Once this was granted the API extracted the correct information.

Is it possible to access the Google Cloud Scheduler API using an API key?

Is it possible to access the Google Cloud Scheduler API using an API key?
Method: projects.locations.jobs.create
https://cloud.google.com/scheduler/docs/reference/rest/v1/projects.locations.jobs/create
I am trying to create a Job using curl:
curl -X POST \
'https://cloudscheduler.googleapis.com/v1/projects/my-project/locations/nam5/jobs?key=[MyAwesomeAPIKey]' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "test-awesome-job",
"description": "My first job",
"schedule": "45 23 * * 6",
"timeZone": "utc",
"pubsubTarget": {
"topicName": "projects/my-project/topics/topic-name",
"attributes": {
"name": "39ro"
}
}
}'
but it result in a 401 Unauthorized response:
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
The Cloud Scheduler API uses service account credentials as described in https://cloud.google.com/docs/authentication/production. As the API docs state, a limited number of GCP services support API keys and that does not include Cloud Scheduler.
If you are running the code to interact with the Cloud Scheduler API on App Engine, Cloud Functions, or Cloud Run the service account is built-in and all you need to do is grant that service account permission to interact with Cloud Scheduler via IAM.
The docs have some more streamlined information on getting set up with the Cloud Scheduler client libraries.
I get confused watching the API explorer which suggested as possible credentials
Google OAuth 2.0 or API key and from the "Help me choose" tool from Google Cloud API credentials (https://console.cloud.google.com/apis/credentials), which apparently now reports the correct solution:
For your situation you can use Application Default Credentials,
which provide a simple way to access Google APIs from App Engine or Compute Engine.
previously it showed the API keys as a possible option.
Thanks #Grayside for pointing me out!

ERROR: (gcloud.auth.activate-service-account) Failed to activate the given service account. Please ensure provided key file is valid

I'm trying to follow this guide https://cloud.google.com/speech/docs/getting-started to call GAE speech to text api through curl. But it doesn't seem to work.
I've setup a project and enabled speech to text api. But then when I try to active the service account it fails. I've run diagnostics, tried different accounts, verified the json file (has email), tried gcloud beta init :-(
bash-3.2$ gcloud auth activate-service-account account#project.iam.gserviceaccount.com --key-file=project.json
ERROR: (gcloud.auth.activate-service-account) Failed to activate the given service account. Please ensure provided key file is valid.
The next step though 'gcloud auth print-access-token' returns a token.
But the final step (curl) returns this -
{
"error": {
"code": 403,
"message": "Google Cloud Speech API has not been used in project google.com:cloudsdktool before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/speech.googleapis.com/overview?project=google.com:cloudsdktool then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developers console API activation",
"url": "https://console.developers.google.com/apis/api/speech.googleapis.com/overview?project=google.com:cloudsdktool"
}
]
}
]
}
}
The problem seems to lie in the project(google.com:cloudsdktool instead of mine) used to authenticate the incoming request.
I'm guessing the call to activate-service-account is causing this?
You are getting the error message for google.com:cloudsdktool project because the command you ran with curl gcloud auth print-access-token was using your user account credentials (created by gcloud auth login) and not service account (as you point out that step failed for you).
The command to activate service account is correct (btw you do not need to provide the account, as one from the file will be used)
$ gcloud auth activate-service-account --key-file=project.json
Make sure your project.json is correct file in the right format format. You can create this json key file either in
in https://console.cloud.google.com/iam-admin/serviceaccounts/project?project=YOUR_PROJECT_NAME
gcloud iam service-accounts keys create, see reference guide.
The file will look like
{
"private_key_id": "....",
"private_key": "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----\n",
"client_email": "...",
"client_id": "...",
"type": "service_account"
}
Note that client_email will be used for ACCOUNT in activate-service-account command.