we want to use default application credentials (python code running in GCP) to perform domain-wide delegation to access Gmail/Drive APIs. The main reason for this is that using default credentials alleviates us from needing to create/manage a gcp service account key (which is very sensitive), whereas code running in GCP (appengine/cloud functions) handles key management for us securely.
We know that Google's professional services have published how to do this for accessing Admin SDK APIs here, however, we're not able to make this work with Gmail/Drive APIs.
Does anyone know if this is technically possible, and if so how?
For what I understood from your question you don't want to use a Service Account, but instead some Application Default Credentials (ADC).
Basically, you will always need to use a Service Account, but if you are running your app on Compute Engine, Kubernetes Engine, the App Engine flexible environment, or Cloud Functions, it will not be necessary for you to create it in your own as it is stated HERE.
You will only need to get the credentials needed to your project and then you will able to call the Gmail API as you would normally do:
from google.auth import compute_engine
credentials = compute_engine.Credentials()
Related
I have a Google Cloud Platform Datstore instance and would like to run queries against it from a Python client. All of the examples show how to do this given a service account keyfile:
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json"
However, I plan to run this on a Serverless platform and don't want to include a keyfile with my deployment. Instead I've setup an API key and given it access to Datastore.
How can I then make datastore.Client() aware of this API Key?
from google.cloud import datastore
datastore_client = datastore.Client()
It takes credentials as an optional keyword arg, but I can't figure out how to create the proper credentials object out of an API key.
As an aside
I am amenable to other forms of auth if recommended. Basically I want to deploy a web application in Google Cloud Platform - what is the standard way to manage service accounts such that files don't have to be passed around ad-hoc?
I'm writing an application (web and mobile) where I would like to use WSO2 for user authentication, authorization and SSO.
My mobile app will authenticate the users against the WSO2-is.
All the API's used by the app are google cloud functions written in python.
I would like to bring a security layer to my GCF's.
From my understanding I can use WSO2-am as a bridge between the app and the GCF to provide security, but I would like to leverage the high scalability of the GCF archicteture and avoid the WSO2-am being a bottleneck.
Is it possible use the WSO2-am and make the GCF to check the permissions access against it, allowing the app calling the API directly instead of using the WSO2-am as a bridge ?
If yes, may you provide some documentation/blogpost/whatever that could help ?
In WSO2 APIM, the gateway does all the authentication and authorization stuff when the requests go through it (to the backend).
So, in the case of,
(1) OAuth2 tokens, the gateway talks to the key manager to validate the token, subscription (API-to-Application) and token scopes.
(2) Self-contained JWT tokens, the gateway can do all these validations itself.
So now in your case, since you don't want to send the requests through the gateway, you have to do what gateway does, within the cloud function itself. In that case, the JWT tokens will be the best choice as they can be validated without connecting to the key manager.
In addition to that, the gateway keeps a token cache so that it doesn't have to validate the same token again and again. You can have a similar cache (if possible) within your cloud functions too. However, in your case, you will have to externalize the cache due to the short-lifetime nature of cloud functions.
Here is the gateway code[1] which does the token, scopes and subscription validations. You can use it as a guide to write yours.
[1] https://github.com/wso2/carbon-apimgt/blob/master/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java
I have developed a Google Cloud Function (GCF) in python, which i want to access from a web service deployed on AWS (written in python). While in the development phase of the GCF, It had Cloud Function Invoker permission set to allUsers. I assume that is why it didn't ask for an Authorization Token when called.
I want to revoke this public access and make it so that i can only call this function from the web service code and it is not accessible public-ally.
Possible Approach :In my research i have found out that this can be done using the following steps:
Removing all the unnecessary members who have permissions to the GCF.
Creating a new service account which has restricted access to only use GCF.
Download the service account key (json) and use it in the AWS web application
Set environment variable GOOGLE_APPLICATION_CREDENTIALS equal to the path of that service account key (json) file.
Questions
How to generate the Access token using the service account, which may then be appended as Authorization Bearer within the HTTP call made to the GCF? Without this token the GCF should throw error.
The docs say not to put the service account key in the source code. Then what is the best way to go about it. They suggest to use KMS which seems like an overkill.
Do not embed secrets related to authentication in source code, such as API keys, OAuth tokens, and service account credentials. You can use an environment variable pointing to credentials outside of the application's source code, such as Cloud Key Management Service.
What are the bare minimum permissions i will require for the service account?
Please feel free to correct me if you think my understanding is wrong and there is a better and preferable way to do it.
UPDATE: The web service on AWS will call the GCF in a server-to-server fashion. There is no need to propagate the client-end (end-user) credentials.
In your description, you don't mention who/what will call your GCF. A user? A Compute? Another GCF? However, this page can help you to find code example
Yes, secret in plain text and pushed on GIT is not yet a secret! Here again, I don't know what performing the call. If it's a compute, functions, cloud run, or any service of GCP, don't use JSON file key, but the component identity. I would say, create a service account and set it to this component. Tell me more on where are you deploying if you want more help!
Related to 2: if you have a service account, what the minimal role: cloudfunctions.Invoker. It's the minimal role to invoke function
gcloud beta functions add-iam-policy-binding RECEIVING_FUNCTION \
--member='serviceAccount:CALLING_FUNCTION_IDENTITY' \
--role='roles/cloudfunctions.invoker'
There's a built-in way to setup oauth on App Engine side, and it works great for request coming from my local machine with token generated by GoogleCredentials.get_application_default(), but it does not work for requests from Compute Engine with NotAllowedError exception on App Engine side.
I did multiple attempts to configure requests scopes to include https://www.googleapis.com/auth/userinfo.emails as its required one, but no luck.
Turned out that when you create your instance with Allow API access to all Google Cloud services in the same project. it does not includes required User Info scope.
To include User Info scope, you have to uncheck Allow API access to all Google Cloud services in the same project., go to Access & Security tab and explicitly enable User Info scope.
UPDATE 2018-11-15
The correct way to set email scope now is by using gcloud command:
gcloud compute instances set-service-account INSTANCE-ID --zone=us-central1-f --service-account=PROJECT-ID-compute#developer.gserviceaccount.com --scopes https://www.googleapis.com/auth/userinfo.email,cloud-platform
I'm using GAE remote api to access the data store of my app. The authentication to GAE is made using remote_api_stub.ConfigureRemoteApi with an authentication function that returns a user name and a password.
Is there a way for authenticating using an access_token, for example OAuth or OAuth 2.0?
There is a solution for Google accounts configured to use 2-Step Verification.
At the moment, you are probably seeing a “BadAuthentication InvalidSecondFactor" error thrown, as you are not able to properly login from the shell.
In order to solve this, you will need an App Password that authorizes the app to access your account resources. Follow the tutorial and use the generated password and the username of an admin of the target App Engine app as the credentials for Remote API.
UPDATE:
Additionally, you can take a look at the remote_api_stub.py file from the AppEngine SDK. You'll find a family of methods called _ConfigureRemoteApiWith* (note the leading underscore), such as:
_ConfigureRemoteApiWithKeyFile
_ConfigureRemoteApiWithComputeEngineCredential
_ConfigureRemoteApiWithOAuthCredentials
Methods themselves are well documented, please take a look at their docstrings. They'll let you authenticate with safer methods than usual ASP provided by remote_api_stub.ConfigureRemoteApi().
You can't use OAuth2 to connect to your app with remote_api_stub/shell. This option is not provided.