I am trying to use the Google Cloud Resource Manager API to test whether the authenticated user has permissions to a given project. I have read the [Google Cloud Resource Manager API documentation][1] and have tried sending requests, all which fail with the following error:
{ "error": { "code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT" } }
The POST request is:
https://cloudresourcemanager.googleapis.com/v1/projects/{projectId}:testIamPermissions
where {projectId} is a defined projectId from the Google Cloud Developer Console. I am aware that I can use the project.list method and determine if the given projectId is present in the list of projects for the user. I want to understand how to use the project.testIamPermissions request and determine which permission the user has on the project. [1]: https://cloud.google.com/resource-manager/reference/rest/v1/projects/testIamPermissions
In order to use the Cloud Resource Manager API methods organizations.testIamPermissions or projects.testIamPermissions, you need to provide the resource you'd like to check in the URL and then the permissions you'd like to check in the body.
So, for example, if I want to test if I, the authenticated user, have access to a particular permission (ex. compute.instances.create) on a particular project (ex. my-project) then, I would POST this:
{
"permissions": [
"compute.instances.create"
]
}
to the URL:
https://cloudresourcemanager.googleapis.com/v1/projects/my-project:testIamPermissions
which would give me the following response:
{
"permissions": [
"compute.instances.create"
]
}
because I do in fact have permissions to create new instances in my-project.
However, if I did not have permission to create new instances, the response would look like:
{
}
Try it here via the API Explorer.
If your goal is to find the test of all permissions that the user has on the project, then you have to provide the full list of all project level permissions in your request body and the response will include the subset of those permissions that the user has.
Hope this helps!
Related
My user account can use the Google Classroom web UI to see all the announcements for a given course. Trying to pull them programmatically using the Google Classroom API.
I've set up an app with Oauth consent screen covering (for test purposes) ALL the scopes listed under the Google Classroom API, and can run the consent flow with my user account to get an access token.
I can successfully GET course details by curl'ing https://classroom.googleapis.com/v1/courses/<my course ID> using the access token obtained from the oauth flow. However, when I GET https://classroom.googleapis.com/v1/courses/<my course ID>/announcements with the same token, I get the following:
{
"error": {
"code": 403,
"message": "Request had insufficient authentication scopes.",
"status": "PERMISSION_DENIED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT",
"domain": "googleapis.com",
"metadata": {
"method": "google.classroom.v1.Work.ListAnnouncements",
"service": "classroom.googleapis.com"
}
}
]
}
}
Behaviour is same in using both client libraries as well as raw REST calls.
Am I missing an auth scope (I switched them all on), am I just not allowed to do this since I'm not the course owner, or am I doing something else wrong? Advice please!
You apear to be using the courses.get method
In order to access this method your application needs to be authorized with one of the following scopes.
You also appear to be using the courses.announcements.list method
This method requires that your application be authorized with one of the following scopes.
The error message "Request had insufficient authentication scopes." means exactly what it says. The access token you are using was not authorized with one of the scopes needed for the courses.announcements.list endpoint there for you can not use it.
You need to delete the access token you have now and request authorization of the user using the proper scope for this method. Always make sure to delete your old token. When changing scopes in code your app does not always request authorization again if you just change the scopes in the code. You need to force it to request authorization again.
All the scopes
you should not be requesting all of the scopes of the user only the scopes that you need. If you only need readonly access make sure not to request write.
I had forgotten that my code explicitly defines the scopes when configuring the client that then builds the oauth request URL:
config, err = google.ConfigFromJSON(b, classroom.ClassroomCoursesReadonlyScope)
Changed to
config, err = google.ConfigFromJSON(b, classroom.ClassroomCoursesReadonlyScope, **classroom.ClassroomAnnouncementsReadonlyScope**)
and it works fine.
I am trying to test the Google Cloud Logging API on the "Try this API" feature that Google Cloud Platform has on their documentation, but I get this response back:
{
"error": {
"code": 403,
"message": "The caller does not have permission",
"status": "PERMISSION_DENIED"
}
}
I know that my response body is correct because it works with OAuth 2.0 but fails when I use API Key.
Auth 2.0:
Working request using OAuth 2.0
API Key:
Non-Working request using API Key
Google docs says that they generate their own API Key for this "Try this API" feature. https://developers.google.com/explorer-help/
Since Google is using their own API Key, I do not understand why I am getting a response status of PERMISSION_DENIED.
Edit:
Here is a link to the Try this API feature in Google Cloud Platform if you would like to give it a try. https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write?apix_params=%7B%22resource%22%3A%7B%22entries%22%3A%5B%7B%22logName%22%3A%22projects%2F%5BPROJECT_ID%5D%2Flogs%2Frequests%22%2C%22resource%22%3A%7B%22type%22%3A%22http_load_balancer%22%2C%22labels%22%3A%7B%7D%7D%7D%5D%7D%7D
Here is the python request that I am using in my code to create an entry:
import requests
entry = {
"entries": [
{
"logName": "projects/[PROJECT_ID]/logs/requests",
"resource": {
"type": "http_load_balancer",
"labels": {}
}
}
]
}
requests.post('https://logging.googleapis.com/v2/entries:write?key=[YOUR_API_KEY]', data=json.dumps(entry))
The API key was created from my user that has "logs writer", "logs viewer", and "logging admin" permissions. This theoretically should be all the permissions I need to make the post request. However, it is still returning a "PERMISSION_DENIED" status.
Any help would be much appreciated. Thank you in advance.
It looks like you are making a request to write data which isn't publicly writable. API Keys have no concept of user, they are only identifying you are allowed to call an API. So it looks like your API key request is working to the extent it can, but the response is telling you: I don't know who you are so I can't let you do this.
OAuth 2.0 is the solution here, as it acts on behalf of your account (you have to give consent), allowing the API to verify you have permission to take this action.
Service accounts are another option, to act on behalf of your project instead of your user, but they aren't practical from a web UI.
Hi I am new to service now.I have an demo instance "demonowprod.service-now.com" when I try to retrieve data from rest API URL it throws authentication fail message like below.
https://demochannel.service-now.com/api/now/table/incident?sysparm_limit=1
{
"error": {
"detail": "Required to provide Auth information",
"message": "User Not Authenticated"
},
"status": "failure"
}
Any help will be appreciated.
So you have two or one instances?
At first you say your instance name is demonowprod.service-now.com in your query you call demochannel.service-now.com.
The credentials used for API calls are your user credentials. Of course you need to have read access on the incident table when querying it.
I think what you need to do is create a service account of sorts and assign the "rest_service" role to that account. Use this credential when connecting from the other instance of SN. User accounts are created by either admins or user_admins under User Administration > Users.
See http://wiki.servicenow.com/index.php?title=REST_API#gsc.tab=0
I am trying to manually write a log entry using Google Cloud Logging API.
Before doing this via code, I am first trying to do it using the Google APIs Explorer. Here is a screen shot of the request I've built using this tool:
In projectsId I have the Google Project Id that I've copied from the
Google Developer Console.
Likewise for metadata.projectId.
In metadata.userId I have the Client Id of the same Service account that I'm using to authenticate (OAuth2) against the Google Logging API.
Google Logging API is enabled for the project.
The Service account belong to the project and has the "Can edit" permission.
I'm 99% sure that I've setup OAuth2 correctly for the request.
When I execute this request, I get the following response:
{
"error":
{
"code": 400,
"message": "Unsupported service specified",
"status": "INVALID_ARGUMENT"
}
}
Why? and how can I fix this?
The error message was actually telling me exactly which argument was invalid - The serviceName I supplied was bogus ("test").
As soon as I set the serviceName to be "compute.googleapis.com", the problem went away and I received a 200 status code indicating success.
I use google-api-php-client library to access webmaster tools data. When I wanted to list sitemaps, it appeared Fatal error: Uncaught exception 'Google_Service_Exception'(403) User does not have sufficient permission for site. See also: https://support.google.com/webmasters/answer/2451999.'
I add the service account email address as a restrict user for my site, but error still exists.
Finally I find the answer:
A service account is not like a regular Google account. You cannot use it to access specific resources even if you give that specific address "access" to it. See here for the different ways you can authorize your requests to the Webmaster API.
For me the problem was not the actual permission, but the way the domain name is passed. Here is my Node.js example, but the same goes for PHP:
import {JWT} from 'google-auth-library';
const client = new JWT(
null,
'service-account.json',
null,
['https://www.googleapis.com/auth/webmasters.readonly'],
);
const res = await client.request({
url: 'https://www.googleapis.com/webmasters/v3/sites/sc-domain:yourdomain.com/searchAnalytics/query',
method: 'POST',
data: {
"startDate": "2020-04-01",
"endDate": "2020-05-01",
"dimensions": ["country", "device"]
}
});
console.log(res.data);
Notice the syntax sc-domain:yourdomain.com. Passing 'yourdomain.com' will result in the error User does not have sufficient permission for site yourdomain.com.
Make sure you added the service-account email as user in search console: https://search.google.com/search-console/users
A service account is not like a regular Google account. You cannot use it to access specific resources even if you give that specific address "access" to it.
You need to manage the service permissions via Webmaster Admin. Add your service account
whatever#developer.gserviceaccount.com
there.