Failed to authenticate Service Account credential in Google Cloud Prediction API Library for NodeJS - node.js

I was using googleapis library and successfully authenticate my Service Account credentials using JWT. Then I found out google-cloud library, which has specific modules for Prediction API, but failed to authenticate the same Service Account credentials.
I don't use Google Computing Engine or App Engine and working in local developement
I follow code in documentation:
var key = require('./MY_SERVICE_ACCOUNT_CREDENTIALS.json')
var prediction = require('#google-cloud/prediction')({
projectId: 'MY_PROJECT_ID',
credentials: key
})
prediction.getModels((err, models) => {
if (err) {
console.log(err)
return
}
console.log('Models:', models)
})
and it returns:
{ ApiError: Access to project denied: user requires read permissions.
at [here goes stack trace]
code: 401,
errors:
[ { domain: 'global',
reason: 'authError',
message: 'Access to project denied: user requires read permissions.',
locationType: 'header',
location: 'Authorization' } ],
response: undefined,
message: 'Access to project denied: user requires read permissions.' }
I don't know where it goes wrong and I'm not sure if I would need to authenticate with googleapis and integrate it with google-cloud or etc. It's also lack of samples

So I know this is a couple of months old but the error is pretty self explanatory but I also ran into this issue myself.
Essentially your service key isn't given the proper permissions in order to read (or write) information from your project. Look for your service account under IAM & Admin in the Google Cloud Console and add Project → Editor and/or Project → Viewer to the service account you've created. Make sure you press "Save" once you've added those permissions and wait about 20 seconds for those permissions to reflect.

Related

What Permission Scopes required for Google Cloud Platform Channel API - customers.create

Overview
I am getting an error insufficient permission scopes when running customers.create GCP Channel API, but I can't tell what extra permissions/scopes I need to grant my service account.
I have a node.js provisioning some GCP Resources, where one of the main goals is to automatically create a new Billing Subaccount in GCP.
The latest documenation for this suggests creating a customer, them creating entitlements from there. (A customer is passed into the "create entitlements" method).
Expected Results
Execution of the create customer method should have a successful out of a customer object.
Actual Results
When I implement the create customer I get an error:
UnhandledPromiseRejectionWarning: Error: 7 PERMISSION_DENIED: Request had insufficient authentication scopes.
at Object.callErrorFromStatus ...
My implementation
Authentication : service account credential file
I have a service account with an exported key/credential file I use to successfully authenticate other GCP API calls in my application such as projects.create() and projects.serviceAccounts.create() - so I am confident that my service account authentication is set up correctly as far as the node application goes.
Service account authentication in code:
const auth = new google.auth.GoogleAuth({
keyFile: 'MyServiceAccountKey.json',
scopes: [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/apps.order',
'https://www.googleapis.com/auth/cloud-billing'
],
});
Service Account Permissions (Granted at folder level)
Permissions contained within the "Customer Billing Admin" Role:
Channel API Method Execution :
const {CloudChannelServiceClient} = require('#google-cloud/channel').v1;
async function CreateCustomer(options){
const channelClient = new CloudChannelServiceClient();
const authClient = await auth.getClient();
const request = {
parent : "accounts/XXXXX-XXXXX-MYACCOUNT",
customer : {
"name": "Customer Test 1",
},
}
const response = await channelClient.createCustomer(request);
console.log(response);
}
Resolution thoughts
Using the GCP APIs I've found that sometimes I just need to add additional permissions to my service account in the IAM page on the GPC console, and other time I needed to include more scopes in the authentication object in my code. This refercence for the accounts.customers.create says the required scope for this api is https://www.googleapis.com/auth/apps.order, which I have included in my code - so I am at a loss as to what permissions/scopes I am missing. From what I can tell, service account authorization should work with this API.

Pub sub with REST API - the request is missing a valid API Key

I am using the following code to do a test publish to pubsub
var data = {
file: 'ciao',
content_type: 'image/png'
};
needle
.post('https://pubsub.googleapis.com/v1/projects/topic:publish', data, {
multipart: true
},
function(err, resp) {
if (err)
console.log('Error: ' + err.message);
else
console.log('OK.' + JSON.stringify(resp.body));
});
But I get the error
{"error":{"code":403,"message":"The request is missing a valid API key.","status":"PERMISSION_DENIED"}}
Do I need a service account authorized to PubSub? Any hint on how to solve this issue?
You will need to verify the credentials you are using and the account permissions that those credentials have.
One of the popular approach is to have a service-account.json file with the credential information and use it as an enviroment variable GOOGLE_APPLICATION_CREDENTIALS. You can get that file when creating a credential account for your pub/sub application. Examples on how to create that you can find it on this link under Setting up authentication for server to server production applications..
Now you also need to verify the permissions and roles you credential account have. For cloud pub/sub there are lot of roles, like roles/editor or roles/pubsub.editor for the scope of your test run. You can even use a sample called testing_permissions from the official documentation to test your access. For a full lists of permissions and roles please see this site.
For more details you can check the access and authentication page

Google API Node.js Library - Permission denied on `getIamPolicy` for projects in organization

Goal
get and set IAM Policies for auto-provisioned GCP Projects and Service Accounts within said projects using the Node.js Client Library for Google APIs. As well as give a the service account in the project the Dialogflow API Admin role (roles/dialogflow.admin)
Issue
I get the following error when I try to get the IAM policy for a project I just automatically created.
Error: 7 PERMISSION_DENIED: Permission 'resourcemanager.projects.getIamPolicy' denied on resource '//cloudresourcemanager.googleapis.com/projects/va-31b899e6' (or it may not exist).
at Object.callErrorFromStatus (/home/aeglad22/va-project-provisioning/node_modules/#grpc/grpc-js/build/src/call.js:31:26)
at Object.onReceiveStatus (/home/aeglad22/va-project-provisioning/node_modules/#grpc/grpc-js/build/src/client.js:180:52)
at Object.onReceiveStatus (/home/aeglad22/va-project-provisioning/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:365:141)
at Object.onReceiveStatus (/home/aeglad22/va-project-provisioning/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:328:181)
at /home/aeglad22/va-project-provisioning/node_modules/#grpc/grpc-js/build/src/call-stream.js:182:78
at processTicksAndRejections (node:internal/process/task_queues:78:11) {
code: 7,
details: "Permission 'resourcemanager.projects.getIamPolicy' denied on resource '//cloudresourcemanager.googleapis.com/projects/va-31b899e6' (or it may not exist).",
metadata: Metadata {
internalRepr: Map(3) {
'grpc-server-stats-bin' => [Array],
'google.rpc.errorinfo-bin' => [Array],
'grpc-status-details-bin' => [Array]
},
options: {}
},
note: 'Exception occurred in retry method that was not classified as transient'
}
Here is the function I am trying to do this in.
async function setServiceAccountRolesV2(projectID, serviceAccountID){
const authClient = await auth.getClient();
const resourcemanagerClient = new ProjectsClient();
var request = {
resource: "projects/"+projectID,
auth: authClient
}
await resourcemanagerClient.getIamPolicy(request, function(err, response) {
if (err) {
console.error(err);
return;
}
console.log(JSON.stringify(response, null, 2));
});
}
Authentication Info
I am using a service account key to authenticate all of my functions in this node app with. This service account has the following permissions granted at the organization level
This service account I am using to authenticate my app with succeeds at getIamPolicy when I try to get the policy of the project it was created in itself. But I get the error when I try to get the policy of new projects I have created using this "admin project" service account.
Summary
Why is permissions denied when trying to get the IAM Policy of projects I have created programmatically, but successful when getting the policy of the "admin" project that I have this service account and the node.js app running. I thought that if I granted my service account proper permissions at the organization level, and the projects I am creating programmatically were in that same organization, my authenticating service account should inherit all of the right permissions to grant service account roles and change IAM policy in these newly generated accounts.
A potential thought/gut feeling I have that could be completely wrong - is it possible these new projects I'm making don't have IAM Policies at all? so when I try to get and set them there's nothing to change?
Update for clarifications
I have a project that acts as an "administration project" which contain hosts the VM my Node.js app for provisioning GCP resources runs on.
This project is also where I created my service account that the Node.js app authenticates with.
I am creating new projects and service accounts within those projects with this Node.js app.
I have given the aforementioned service account the Owner permission at the organization level.
In my setServiceAccountRolesV2() method, I have tried making the resource my provisioned project manually, as opposed to passed as a parameter to make sure the the project is located correctly. I manually copy and pasted the project ID from one of the auto-provisioned projects into the resource field like this for example
resource: "projects/va-31b899e6",
and I get the same permission denied error (full error message shown above).
However when I try to use this getIamPolicy method with the "admin" project that my node.js app and service account were created in, I get a successful policy return.
resource: "projects/provisioning-admin-339515"
I don't understand why one works, and one doesn't while the service account I'm using to make the call has Owner role at the organization level. The va-31b899e6 project shown above is in fact under the same organization my admin project is.
When I run the gcloud command gcloud projects get-iam-policy va-31b899e6 --format=json > ~/policy.json to check the policy of the api-generated project (not the admin project), I get the following policy back:
{
"bindings": [
{
"members": [
"serviceAccount:tf-admin-sa#provisioner-admin-339515.iam.gserviceaccount.com" ],
"role": "roles/owner"
}
],
"etag": "ByXXh29efSc=",
"version": 1
}
This service account listed in the members is the service account I authenticate my Node app with. Again, Owner granted at the Org level. This to me looks like it should be able to use the get and setIamPolicy methods on this project, as well as any other project in my organization.
New edits to follow trouble shooting tips from answer.
1
Confirmed I am using the correct project in the api call:
async function setServiceAccountRolesV2(projectID, serviceAccountID){
const authClient = await auth.getClient();
const resourcemanagerClient = new ProjectsClient();
var request = {
resource: "projects/va-31b899e6",
auth: authClient
};
await resourcemanagerClient.getIamPolicy(request, function(err, response) {
if (err) {
console.error(err);
return;
}
console.log(JSON.stringify(response, null, 2));
});
}
(project ID copied from GCP Console) : resource: "projects/va-31b899e6",
2
I have verified my credentials are used correctly, I am using a json key file of the service account I created to create more projects and service accounts programmatically. This is how I am authenticating :
const auth = new google.auth.GoogleAuth({
keyFile: 'provisioner-admin-339515-411d1e284a77.json',
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
Then in my function, I create a new instance of auth like this:
const authClient = await auth.getClient();
which is then sent in the request of the api call: auth: authClient
3
Verified permissions for my authenticating service account:
When I run
gcloud projects get-iam-policy va-31b899e6 \
--flatten="bindings[].members" \
--format="table(bindings.role)" \
--filter="bindings.members:tf-admin-sa#provisioner-admin-339515.iam.gserviceaccount.com"
I get the output ROLE: roles/owner
Your service account has too many roles. Most of the roles are redundant and included within other roles that you assigned. For example, Billing Account Administrator contains the permissions of Billing Account User. The role Owner possesses almost all of the roles in your screenshot.
Next, you need to understand the Principle of Least Privilege. Seth Vargo put together a good intro video. In summary, only grant the required privileges and no more. Your service account IAM roles are vast and a serious security weakness.
To solve the problem in your question, follow these steps:
STEP 1:
Confirm that the Project ID is correct in the API call. Make sure you are using the Project ID and not the Project Name. List the projects:
gcloud projects list
STEP 2:
Verify that your code is using the correct credentials (the ones you think you configured). Your question does not show how you are authorizing your code. You are using ADC (Application Default Credentials) which means the credentials could be found from several sources (CLI remembered credentials, the environment variable, metadata server).
If you are using the environment variable GOOGLE_APPLICATION_CREDENTIALS, open the file using the variable and make sure that it is a service account JSON key:
vi $GOOGLE_APPLICATION_CREDENTIALS
If you are using the CLI credentials, verify which identity is being used:
gcloud auth list
As a debugging test, clear the environment variable and use a user identity that has the role Owner and then login. Then retest your application.
unset GOOGLE_APPLICATION_CREDENTIALS
gcloud auth application-default login
STEP 3:
Once you have determined the correct Project ID and which service account your code is using, double-check the roles assigned to the service account at the project level. List the IAM roles with this command. Replace with your Project ID and Service Account Email address:
gcloud projects get-iam-policy <PROJECT_ID> \
--flatten="bindings[].members" \
--format="table(bindings.role)" \
--filter="bindings.members:<SERVICE_ACCOUNT_EMAIL>"
The service account needs one of these roles or similar to view IAM bindings:
roles/browser aka Browser
roles/iam.roleViewer aka Viewer
The service account needs this role or similar to modify IAM bindings:
roles/resourcemanager.projectIamAdmin aka Project IAM Admin
Manage access to projects, folders, and organizations

Authorize with Firebase Rules API

I am trying to access the Firebase Rules API using the Google APIs Node.js Client.
I tried OAuth2 and using an API key both obtained through the gcloud console for my project, but both methods got me: Error: The caller does not have permission
This is how i tried to do it with an API key: https://gist.github.com/dergoegge/1e9cbf980148ef3febecaf0eeeb0e1fa
Are there any special restrictions on that api or am i doing something wrong?
Edit: I also tried using service account credentials https://gist.github.com/dergoegge/665d235819429d74c9d448226ec1eba3
and got
errors:
[ { message: 'Invalid Credentials',
domain: 'global',
reason: 'authError',
location: 'Authorization',
locationType: 'header' } ]
in the response.
I should have read the documentation more before asking.
I did not follow all the steps listed here: https://github.com/googleapis/google-api-nodejs-client#oauth2-client
After that it works.

Accessing Google Directory API with NodeJs

I am having trouble accessing the Google Directory API using node. What I am hoping to do is create and remove users from Groups (and create and list groups and their users). In testing I have managed to access most of the APIs without trouble but the Directory has been impossible.
Firstly, is what I am trying to do even possible?
Secondly, if it is possible, here is a sample of my code; what am I missing?
var google = require('googleapis');
var googleAuth = require('google-oauth-jwt');
var request = require('google-oauth-jwt').requestWithJWT();
request({
url: 'https://www.googleapis.com/admin/directory/v1/groups?domain=mydomainname.com&customer=my_customer',
jwt: {
email: 'created-service-account#developer.gserviceaccount.com',
keyFile: './MyPemFile.pem',
scopes: [
'https://www.googleapis.com/auth/admin.directory.orgunit',
'https://www.googleapis.com/auth/admin.directory.device.chromeos',
'https://www.googleapis.com/auth/admin.directory.user',
'https://www.googleapis.com/auth/admin.directory.group',
'https://www.googleapis.com/auth/drive.readonly'
]}
}, function (err, res, body) {
if (err) console.log("Error", err);
console.log("BODY", JSON.parse(body));
});
I have created a project in the Developer Console. I have created a new clientId (Service Account). I am then presented with a p12 file, which I use openSSL to convert to a pem file (file path for this given in keyFile setting above). The clientId email address created is used in the email setting above.
I have granted the project access to the Admin SDK. I have then gone into Admin Console and in Security -> Advanced -> Manage API client access, I have granted the Service Account access to all the scopes requested in the above code.
Hope, this makes sense, it is difficult to describe the full process. Please comment if you have any questions or need clarity on anything.
When running this code I always get a 403, "Not Authorized to access this resource/api".
Am I using the correct methodology? It is difficult to follow the Google Documentation as not all of help files match the current menu system.

Resources