I have a nodejs app deployed on Google App Engine, which trigger http cloud functions, thought simple http call (using axios) to get data from Google Cloud Sql.
Everyone that will use the site will be able to see the http request and to replicate it.
What is the best way to secure my google cloud functions to be called only from google app engine?
The best way is to deploy a private function.
When you deploy your function with the cli use the --no-allow-unauthenticated param. This feature is in Beta
On the console, you can't you when you deploy your function. However, you can delete the access to all user in the functions list page
Click on the function line (not the name of the function, the line)
Show the info panel in the upper right corner
Delete allUsers from the cloud function invoker.
Now authorize only AppEngine to access to your function
In the console, at the same place (Function Invoker), add the AppEngine default service account : #appspot.gserviceaccount.com
With the cli, use this command
gcloud beta functions add-iam-policy-binding <Your Function Name> \
--member='serviceAccount:<your project id>#appspot.gserviceaccount.com' \
--role='roles/cloudfunctions.invoker'
Now only the user/service account with the role cloudfunctions.invoker could invoke your function.
I feel the post mentioned by #Denis T does mention options for your scenario. Since you commented it does not work for your scenario, did you consider restricting access to Cloud Function to only the App Engine default service account? How to do this is mentioned in the answer quoted by Denis.
Related
I created an API using Python + FastAPI and deployed it to Google App Engine and I would like to measure the cost for each request made.
I saw there is a header "x-appengine-estimated-cpm-us-dollars" that show up when logged in with the owner account on GAE, but I didn't see it when accessed the API using the browser "https://example.uc.r.appspot.com/api"
Any idea how to can I see this header or a way to get an estimated cost for each request made?
Note: the deployed script is an API, not a website with auth like the one mentioned here (Usage of X-AppEngine-Estimated-CPM-US-Dollars in AppEngine)
According to the documentation:
If you access dynamic pages on your site while signed in using an administrator account, App Engine includes per-request statistics in the response headers
And then shows the description for this particular header, therefore, this is not something that is available for APIs hosted in AppEngine.
You could alternatively use the Cloud Billing API to gather some information, although not exactly the same.
I'm trying to find a way to dynamically create a project on Google App Engine using Go following this example.
However, the documentation isn't very clear (at least for me) in how to proceed to authenticate the user and the Go example goes as far as saying:
// TODO: Fill required fields.
I also had a look at the Go Client Library Documentation which made things even more confusing to me.
Has anyone used this API before or have found a way to programatically create a project in App Engine?
When you initialize the API by calling cloudresourcemanager.New(hc), you pass an http client, that in the case of this example is authenticated by using the default credentials from the system. These credentials come from the default service account of App Engine or Compute Engine (not sure about the second though), depending on the environment you are in. If you are outside of Google Cloud, you can follow the instructions on the example:
// 2. This sample uses Application Default Credentials for authentication.
// If not already done, install the gcloud CLI from
// https://cloud.google.com/sdk/ and run
// 'gcloud beta auth application-default login'
If you do this, the default credentials will be taken from the user you used to log in on the command gcloud beta auth application-default login. Another possibility would be changing the code to generate the credentials by calling JWTConfigFromJson1, that would explicitly load your credentials from a json file. Here2 you can see an example of how to initialize an http client using this method.
I have mistakenly deleted the default "app engine service account" for my project - {id}#appspot.gserviceaccount.com
Is there a way to recover it without resetting/recreating my project on Google Cloud Platform?
Unfortunately at this time, there is no way to recover the default App Engine service account. The solution is as you say creating a new project and redeploying your code there.
Should you wish to see this deletion prevented or default service account recreation made possible in the future, I strongly urge you to file a feature request on the App Engine public issue tracker while providing this example as a business case.
UPDATE: As filed by the OP, a feature request now exists on the App Engine public issue tracker as Issue 13085. Please star this issue to receive updates on its progress.
UPDATE 2: As part of the App Engine Admin API, one can now use the apps.repair API to attempt to address issues of default Cloud Storage buckets and App Engine service accounts. I would recommend trying this API before creating a new project and redeploying. I'm leaving this as an addendum and not the primary solution as it's not guaranteed to solve the issue.
UPDATE 3 It is now possible to undelete service accounts. As per the Undeleting a service account documentation, a service account may be restored if:
The service account was deleted less than 30 days ago
and
There is no existing service account with the same name as the deleted service account.
You can now recover the deleted service accounts from https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/undelete
you have to get the UniqueID of the service account from https://console.cloud.google.com/home/activity
Recover
You can undelete service accounts. You will need the service account's unique ID. If you don't have it, you can find it on Google Cloud Logging.
You can find Logging service here on the side menu:
Then you will need to filter by date and type service account to find the exact moment the service was deleted.
Then you can either
Option 1: Use Google Cloud Command Line
You can run the command line by installing it on your computer (https://cloud.google.com/sdk/docs/install). Or you can run it online using the Active Shell offered by Google Cloud Platform.
The command you want to run is the following.
gcloud beta iam service-accounts undelete 12345678901234567890
Option 2: Use Google Cloud API
Using curl, call the API with the following command.
You will need to change API_KEY, PROJECT_ID and SERVICE_ACCOUNT_UID for real values.
curl -X POST \
-H "Authorization: Bearer API_KEY \
-H "Content-Type: application/json; charset=utf-8" \
-d "" \
"https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_UID:undelete"
You can get the API_KEY from Google Cloud Command Line:
gcloud auth application-default print-access-token
Again you can either have gcloud installed on your local machine or you can use it online with the Active Shell.
If you don't know the default service account UniqueID, there is another solution.
Simply disable the App Engine Admin API and enable the same after some time. This will create a new default service account. Please note that this will delete all the associated resources.
(To enable/disable an API: Menu -> API & Services -> Dashboard -> Enable APIs and Services -> Search for that API -> Enable/Disable)
Your Account is deleted less than 30 days you can recover it via cloud console
Go to Cloud Console Open Terminal :
Write :
gcloud beta iam service-accounts undelete 100214681451516381413
100214681451516381413 this is the Deleted Account UID .
If You Don't know the Deleted Account ID then GO IAM and Search With Your Deleted Email Address you will find-out the UID there .
Thanks .
I am trying to use Google Objectify for Datastore (https://github.com/objectify/objectify). My app is not hosted on GAE, but I still make use of Datastore, so I need to use the remote API. Right now, I use the low level API and connect successfully like this :
DatastoreOptions options = DatastoreOptions.builder()
.projectId("PROJECT_NAME")
.authCredentials(AuthCredentials.createApplicationDefaults()).build();
Datastore client = options.service();
And the library used is http://googlecloudplatform.github.io/gcloud-java/0.2.0/index.html. My application defaults for "AuthCredentials.createApplicationDefaults()" is in my home folder in development as well as on the server.
In the doc I saw for Objectify, I did not see anyway of specifying the connection like above, thus no way of telling to use the credentials file in our home folder. The code I see for Objectify is mostly like this Objectify.ofy(). So I see no way with this method of telling to use the auth credentials defaults.
Thank you very much.
Use the Google App Engine remote api:
https://cloud.google.com/appengine/docs/java/tools/remoteapi
You could try gcloud-java datastore module.
http://googlecloudplatform.github.io/gcloud-java/0.2.0/index.html
But I encounter some performance issues on outside of Google Sandbox (GAE-Compute Engine)
I have a Google App Engine web app that runs the majority of my site. However, for certain functions, I need a linux machine. I would like my Google App Engine app to automatically spin-up a Google Compute Instance on certain events.
I understand that you can add Google Compute instances using the Compute Engine REST API. However, in order to access the Google Compute REST API, you need to get an access token using the OAuth2 authentication process.
How can I programmatically get an access token from within Google App Engine?
It seems that all of the authentication methods require a window to appear so you can type in your username and password, which is impractical from within Google App Engine.
Here is a complete example of using service accounts and App Engine cron tasks to stop instances after they've been running for a while:
(opposite of starting instances, but the authorization code will be the same)
https://github.com/GoogleCloudPlatform/compute-appengine-timeout-python
AppAssertionCredentials handles the access token using this code:
# Obtain App Engine AppAssertion credentials and authorize HTTP connection.
# https://developers.google.com/appengine/docs/python/appidentity/overview
credentials = AppAssertionCredentials(
scope='https://www.googleapis.com/auth/compute')
HTTP = credentials.authorize(httplib2.Http(memcache))
# Build object for the 'v1beta15' version of the GCE API.
# https://developers.google.com/compute/docs/reference/v1beta13/
compute = build('compute', 'v1beta15', http=HTTP)
You should be able to use the service account associated with your project to authenticate to the Compute Engine API and launch VMs.
Documentation on service accounts suggests that the following python code should fetch a service account token.
import httplib2
import discovery
from oauth2client.appengine import AppAssertionCredentials
...
credentials = AppAssertionCredentials(
scope='https://www.googleapis.com/auth/compute')
auth_http = credentials.authorize(httplib2.Http())
compute_service = discovery.build('compute', 'v1beta15', http=auth_http)
I'd thought that the Google I/O demo from this year where they built a video-sharing site was going to be available, but I don't see it on GitHub yet. There are a number of demos that use AppEngine to control GCE, but most of them seem to use the user's project and credentials, rather the app's own credentials.
Obviously, you probably don't want to spin up a VM on direct user input unless you've got a very large budget or some form of rate limiting in place, but it's quite helpful to spin up a VM now and then when you've got a lot of computation to do. (Transcoding, etc.)