What permissions are required to GET_TEMPLATE for Firebase Remote Config? - node.js

I have a Firebase Cloud Function that invokes an Admin SDK service account to request the Remote Config template to compare changes to the previous version. I have this working in 2 other Firebase instances, but in this instance, I'm getting this error in the cloud function logs:
Function execution started
rejected token
"status": "PERMISSION_DENIED"
error encountered:
"error": {
"code": 403,
"message": "[AUTHORIZATION_ERROR]: User does not have the following permission: GET_TEMPLATE",
Function execution took 139 ms, finished with status: 'ok'
I have tried adding these permissions to the service account:
Cloud Functions Admin
Editor
Firebase Analytics Viewer
Firebase Remote Config Admin
Service Account Token Creator
I have also tried deploying this cloud function on 3 different service accounts and they all receive the same error.
Any suggestions would be most welcome.

This issue was resolved by adding the required permissions (cloudconfig.configs.get, cloudconfig.configs.update, and firebaseanalytics.resources.googleAnalyticsReadAndAnalyze) to the 'App Engine default service account'. This was confusing because we had thought that the default Firebase Admin SDK 'firebase-adminsdk-*****#projectId.iam.gserviceaccount.com' would be the default service account used to access the Remote Config GET_TEMPLATE. I know for certain we also tried manually specifying this service account when initializing the app in the Cloud Function. We even tried changing the 'Runtime service account' in the Cloud Function -> Edit -> 'Runtime, build, connections and security' settings to use the service account and that didn't work (which seems like that might be a bug). Only adding the correct permissions to the App Engine default service account seemed to work in this instance.

The only Remote Config permissions are cloudconfig.configs.get , cloudconfig.configs.updateand firebaseanalytics.resources.googleAnalyticsReadAndAnalyze
Firebase IAM Permissions lists the roles required for each product.
Also, it is important to note that "To authenticate a service account and authorize it to access Firebase services, you must generate a private key file in JSON format". Steps on how to do it and the same error similar to yours can be found in this thread

my solution was adding the Firebase Remote Config Admin role to the XYZ-123#appspot.gserviceaccount.com. not great that this is buried...!

Related

how to authenticate to google text-to-speech with service account

I am trying to use google text-to-speech and other translation service in my nodejs but when i connect to google api I get this error 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.",
metadata: Metadata {
internalRepr: Map(2) {
'google.rpc.errorinfo-bin' => [Array],
'grpc-status-details-bin' => [Array]
},
options: {}
},
note: 'Exception occurred in retry method that was not classified as transient'
}
so after many research i tried to verify that i am authenticating using my service account credentials. I ran this command
gcloud auth activate-service-account --key-file=./auth/service_acct_key.json
and it shows this
Activated service account credentials for: [firebase-adminsdk-uwecx#xxxxx.iam.gserviceaccount.com]
but when run the server again
node server.js
I still got the error
what is causing this error and how can authenticate correctly ?
With gcloud CLI, you have 2 level of authentication:
The CLI level
The Google Cloud Auth library level (Also named ADC, for Application Default Credential)
When you perform the command gcloud auth .... you are at the CLI level
When you perform the command gcloud auth application-default ... you are at the ADC level.
In your case, you only set the authentication at the CLI level, and, of course, that authentication isn't detected in your NODE app, that use Google Cloud libraries and search credential at ADC level.
When you use service account key file (that is a bad practice, but too often prosed and shared in tutorial, even on Google Cloud tutorials (...)), you have to set an environment variable GOOGLE_APPLICATION_CREDENTIALS with the value equals to the absolute path of your service account key file. Try that
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/auth/service_acct_key.json
node server.js
It should work.

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

The client 'XXX' with object id 'XXX' does not have authorization to perform action 'Microsoft.Media/mediaServices/transforms/write'

I am trying to use the following git repo in order to connect to azure ams, upload a video and stream it:
https://github.com/Azure-Samples/media-services-v3-node-tutorials/blob/main/AMSv3Samples/StreamFilesSample/index.ts
For some reason I am keep getting the following error:
The client 'XXX' with object id 'XXX' does not have authorization to perform action 'Microsoft.Media/mediaServices/transforms/write' over scope '/subscriptions/XXX/resourceGroups/TEST-APP/providers/Microsoft.Media/mediaServices/TESTAMP/transforms/ContentAwareEncoding' or the scope is invalid. If access was recently granted, please refresh your credentials
The AD user is owner but I understand it is a permission issue.
I searched all over the web for hours what permission do I need to grant and where but could not find any solution
The error get thrown here:
let encodingTransform = await mediaServicesClient.transforms.createOrUpdate(resourceGroup, accountName, encodingTransformName, {
name: encodingTransformName,
outputs: [
{
preset: adaptiveStreamingTransform
}
]
});
of course, I have updated the .env file to the correct data of my azure account.
Can anyone point out what am I missing and how to grant this permission?
Thanks!
The error message is referring to your Service Principal that is being used to authenticate against the AMS SDK.
Double check that you entered the GUID values for the service principal ID and Key, and make sure you did not use the friendly name in there.
AADCLIENTID="00000000-0000-0000-0000-000000000000"
AADSECRET="00000000-0000-0000-0000-000000000000"
Also, double check in IAM Access control in the portal that the service principal exists under the Role Assignments for your Media Services account and has Contributor or Owner permission Role first.
If you are in an Enterprise that locks down AAD access - you may need to work with your AAD owner/admin to make these changes and grant the service principal the right roles for your account. That's a bit outside of Media Services, and is just general Azure AAD application creation rights, and role assignments.
If you are still hitting issues, I would file a support ticket and also ask your AAD administrator to assign the role permisssion to your service principal.
As an aside, we are also working on updated Node.js SDK samples for the upcoming (soon!) release of the 10.0.0 Javascript SDK.
See the beta samples here - https://github.com/Azure-Samples/media-services-v3-node-tutorials/tree/10.0.0-beta.1

"Caller does not have permission" trying to create custom token with Firebase Admin SDK

Error
When calling admin.auth().createCustomToken() I am getting the following error:
Error: The caller does not have permission; Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens for more details on how to use and troubleshoot this feature.
The provided documentation leads me to believe that the service account I am initializing the Firebase Admin SDK with does not have sufficient permissions. I don't believe this to be the case, so I want to ask and see if I've missed anything.
Configuration
Firebase Admin SDK is initialized in the backend like so:
admin.initializeApp({
serviceAccountId: 'firebase-adminsdk-xxxxx#my-project-id.iam.gserviceaccount.com'
});
Technically the value is referenced from an env var, but I have confirmed this value to be correct.
The service account being used has the following roles:
roles/firebase.sdkAdminServiceAgent
roles/iam.serviceAccountTokenCreator
Per the documentation, the required permission for creating custom tokens is iam.serviceAccounts.signBlob. This permission is part of the iam.serviceAccountTokenCreator role as per this output:
❯ gcloud beta iam roles describe roles/iam.serviceAccountTokenCreator
description: Impersonate service accounts (create OAuth2 access tokens, sign blobs
or JWTs, etc).
etag: AA==
includedPermissions:
- iam.serviceAccounts.get
- iam.serviceAccounts.getAccessToken
- iam.serviceAccounts.getOpenIdToken
- iam.serviceAccounts.implicitDelegation
- iam.serviceAccounts.list
- iam.serviceAccounts.signBlob
- iam.serviceAccounts.signJwt
- resourcemanager.projects.get
- resourcemanager.projects.list
name: roles/iam.serviceAccountTokenCreator
stage: GA
title: Service Account Token Creator
Lastly, the code in question that is erroring out is as follows:
try {
const loginToken = await admin.auth().createCustomToken(uid);
return response(200).json({ loginToken });
} catch (err) {
...
}
The uid comes from signing in a user via a GoogleUser credential - the provided uid is confirmed to be accurate, and this flow works locally when referencing a JSON key file for the same service account.
Server is running on GKE, in case it could be a cluster permission error.
Any help would be greatly appreciated!
EDIT - RESOLVED
Hiranya's answer did the trick - the K8s deployment had been configured with a service account whose original intent was only to enable Cloud SQL Proxy. Giving this service account the serviceAccountTokenCreator role solved the issue.
You need to make sure the service account that the SDK is authorized with (not the one specified as serviceAccountId) has the token creator role. This is the service account auto-discovered by Google Application Default Credentials. In case of Cloud Functions this is the service account named {project-name}#appspot.gserviceaccount.com. You need to figure out the equivalent service account for GKE and grant it the token creator role.

Getting an "unauthorized_client" when tryging to get a new access token, why?

I'm developing an API using VS 2017, which I'm testing using Postman. I've been following this blog post Getting started with Windows Azure AD Authentication using Postman. I finally got it to give me an access token and a refresh token. About 3 quarters of the way through the post I came across this:
resource : https://management.core.windows.net
which has to be put into Postman (I'm using the Windows app version of Postman). I wasn't sure what that was for, so I left it off. I eventually got an access token and a refresh token, but when I when to get more info for all subscriptions, I got errors saying that I had specified a valid resource. So, I thought what I'd have to do was start over again, but re-authenticating and getting a code from Azure. I did so, and put that into Postman, as the blog post instructs. However, issuing this POST results in this error:
"error": "unauthorized_client",
"error_description": "AADSTS70002: Error validating credentials. AADSTS65005: Invalid resource. The client has requested access to a resource which is not listed in the requested permissions in the client's application registration. Client app ID: d37abf69-42ce-4571-b146-f3422e73f041. Resource value from request: https://management.core.windows.net. Resource app ID: 797f4846-ba00-4fd7-ba43-dac1f8f63013. List of valid resources from app registration: 00000002-0000-0000-c000-000000000000.\r\nTrace ID: 9f028899-6d03-409e-8db4-4e9905000300\r\nCorrelation ID: ec253a1b-9fdc-495f-9310-6b40a42e5d93\r\nTimestamp: 2018-11-19 22:20:02Z",
"error_codes": [
70002,
65005
]
I don't understand why nor what I could have done wrong. I've prespecified the resource as the tutorial instructed, so what have I done wrong?
Looking at the error message, it seems you could have missed adding relevant permissions for "Windows Azure Service Management API" to your app registration.
Steps:
Go to Azure Portal > Azure AD > App registrations > Your app (with app id: d37abf69-42ce-4571-b146-f3422e73f041)
Go to Settings > Required permissions > Add > Select "Windows Azure Service Management API"
Select the relevant permission under Delegated permissions section. Click on select and then "Done". You should get a notification in portal that successfully added permissions. You should see Windows Azure Service Management API listed under required permissions as well.
After these steps, continue as per the blog post you've mentioned with Postman steps to get the access token again.
I found myself in the same situation when i was trying to setup Postman. Its not as complicated as most blogs make seem. I created a tutorial to try to make the process easy.
http://hazelnest.com/blog/blog/2018/11/17/azure-postman-configuration/
https://youtu.be/2bfgeBKRxl4
Hope this helps.

Resources