I have an API that I host through Google Cloud. The main entry point for the API is an App Engine instance (standard), which then needs to be able to call various cloud functions to execute its tasks.
To make the cloud functions secure, I want to set the ingress controls to "Allow internal only".
I've deployed the cloud functions and the App Engine in the same region (us-central1), but every time the App Engine instance tries to call a cloud function, it gets a 403 error. I've tried setting up a VPC connector for the App Engine, but that isn't helping.
Here's the app.yaml file:
service: my-test-app
runtime: nodejs10
env_variables:
STAGE: "dev"
instance_class: F1
vpc_access_connector:
name: "projects/my-test-project/locations/us-central1/connectors/test-vpc-connector"
The key cloud function configuration is the Ingress Setting. I have it set to Allow internal traffic only. If I set it to Allow all traffic, everything works (just highly insecure!)
Any suggestions on what I might be missing?
I found the solution! If I set the App Engine to a flex environment, everything works. It looks like the standard environment was the issue.
Related
I'm trying to configure my Google App Engine instance with Cloudflare for Saas, and more precisely Cloudflare's SSL for SaaS offering. The objective being that I can provide to my customer a "custom domain" (also known as "vanity domain"), such that they don't go to dashboard.mywebsite.com, but instead app.customerwebsite.com.
Configuration part
To make sure that my App Engine instance is correctly serving content on dashboard.mywebsite.com, I've made the following:
On Google Cloud side:
I've configured the custom domain dashboard.mywebsite.com.
I've let Google manage the SSL configuration (no custom key/certificate)
Here is my app.yaml configuration file:
runtime: nodejs14
env_variables:
NODE_ENV: 'production'
basic_scaling:
max_instances: 10
idle_timeout: 5m
On Cloudflare side:
I've updated the DNS records so that dashboard.mywebsite.com is perfectly working
I've configured the SSL on the Full mode (while I've tried with Flexible as well - both work)
I waited for a few hours and I confirm that dashboard.mywebsite.com resolves correctly and serves my content (from Google App Engine).
Next, custom domains
According to Cloudflare documentation, I had to register the fallback origin (i.e. dashboard.website.com) and then configure a custom hostname (e.g. app.customerwebsite.com). Which I did.
Now, according to Cloudflare documentation again, my customer has to create a CNAME record. Which I did with a domain of mine:
app.customerwebsite.com CNAME dashboard.mycompany.com
The issue
I waited a few hours again. Then, when I open app.customerwebsite.com in my browser, it shows a Google 404 error page instead of my dashboard. Which makes me think that Cloudflare successfully "redirects" the traffic to Google, but App Engine refuses to serve it. Probably because it doesn't know app.customerwebsite.com?
Any thoughts that would help?
As you noticed, the issue is not related to Cloudflare, but App Engine. The problem with your configuration is that, when App Engine receives a request, based on the Host header, it forwards the request to the right instance.
App Engine lets you map any custom domains that has been previously validated by Google. But in your situation, that would mean you have to register each custom domain of your customers on your App Engine instance. That's too cumbersome (if even possible).
What you need to do instead is the following:
enable a static IP address with Google Cloud
change your DNS record from dashboard CNAME ghs.googlehosted.com to dashboard A YOUR_IP_ADDRESS
configure a Google Cloud Load Balancer to map requests received on that IP address to your App Engine instance.
Google's documentation has a great guide on how to setup a load balancer with Cloud Run. By changing a few settings it works great with App Engine. As an extra help, below is the configuration details of our load balancer that allows us to provide vanity domains / custom domains to our customers through Google Cloud:
Again, the load balancer is here responsible to map all requests received by your IP address (no matter the Host header) straight to your App Engine instance.
As a best practice, it might be useful to push a dispatch.yaml file to your instance:
dispatch:
- url: '*/*'
service: default
Which tells App Engine to send all requests to the default service. It works a bit like a wildcard virtual hosts on an Apache server.
I have a Google Cloud project which has the following resources:
App Engine Standard Environment, which hosts the frontend (basically react-app).
A private Google Cloud function
Now, I though of the following scenarios to call the function from the react-app
Set Allow only internal traffic to Cloud function: Only App Engine flexible environments can call the function, so ruled out
Authentication using CORS: The clients can still call the function.
making the cloud function public: Would let everyone invoke the function, which is not recommended for private API
Invoking function using Google Cloud API: This would expose my Google Cloud API keys in the frontend.
So is there a work around to call a Cloud function from an App Engine Standard environment
You can't call a Cloud Functions (or Cloud Run) with ingress = internal only with App Engine. See my answer here
To secure your cloud functions, you can rely on the IAM service. If your App Engine service call your cloud functions (I mean you have backend code that run on App Engine, not static JS file that run in the user browser), you can grant only the App Engine service account (you can now customize the service account to run with your App Engine service) the permission to call your cloud function.
Of course, your cloud functions is publicly exposed but only the authenticated and authorised traffic will be routed to your Cloud Functions. All the bad traffic (from internet or from other unauthorised services) will be rejected automatically by GFE (Google Front End) and before invoking your Cloud Functions. Therefore you will pay only for the valid traffic, all the bad traffic is discarded by google.
If the code runs on the user browser (because your App Engine serves only static files), you can use a proxy layer to add security filtering, like API Gateway.You can have a look to this answer
I have standard app engine which makes an api call to another app engine within same shared VPC and project but the response is 403 forbidden error. Also the standard app engine to which i am making api call as gcloud app services update service-name --ingress=internal-only but as soon as i updated the configuration of the appEngine as gcloud app services update service-name --ingress=all. All the API calls are successfull.
Note : as required by gcp a serverless connector as been created and it is being used.
Questions
1 . How to communicate between Standard AppEngine to another Standard AppEngine within shared VPC?
2 . How can i communicate between AppEngnies with gcloud app services update service-name --ingress=internal-only configuration.
When you set the ingress to internal, you tell to App Engine: accept the traffic only coming from the VPCs of this project.
Thus, you need to tell to your other App Engine services: Reach this (App Engine) service only through the VPC else you will be forbidden.
Firstly, when you deploy on serverless environment, App Engine, Cloud Run or Cloud Functions, you are on the Google Cloud VPC, not on your project VPC.
Therefore, you have to set the egress to your App Engine to use the VPC. You need to plug a VPC connector to make this bridge between the GOOGLE serverless VPC world and your VPC.
However, it won't work. Indeed, when you set that on App Engine, only the traffic to the private IP use the serverless VPC connector, but not the public IPs. You haven't the capacity to set the VPC egress to all to route all the traffic through the VPC, public and private (as you can do with Cloud Functions and Cloud Run)
Thus, the App Engine, with serverless VPC connector or not, will contact the internal App Engine service through internet and not through the VPC and you will get a 403 every time.
In conclusion, you can't do that with App Engine, have a look to Cloud Run or Cloud Functions for this type of set up. You can also review your security design and don't rely on the origine of the traffic (from the VPC) but on the authentication of the traffic (use identity token and IAM service to ensure the communication security).
This is now possible to reach other App Engine services (configured with internal traffics only) thanks to Serverless VPC.
In app.yaml add to all the services which need to talk to each others (in and/or out connection):
vpc_access_connector:
name: projects/PROJECT_ID/locations/LOCATION/connectors/CONNECTOR
egress_setting: all-traffic
The doc : https://cloud.google.com/appengine/docs/standard/go/connecting-vpc.
I'm trying to set up a project with an App Engine service that talks to a Cloud SQL database with Private IP connectivity. This is achievable through the Serverless VPC Access of Google Cloud, that allows App Engine and Cloud Functions to interact with resources in your private VPC.
For some unexplicable reason, I was able to interrogate the DB from a test Cloud Function, but not from App Engine, where I get a connection refused error. Since it works on Cloud Functions, it makes me think that the Serverless VPC Access is properly configured, but I still can't understand why it doesn't work with App Engine.
The App Engine app is deployed using gcloud app deploy. I also tried gcloud beta app deploy as somebody suggested but nothing changed.
Everything (App Engine, Cloud Function, Cloud SQL) is in the same region, europe-west1. I am not using the gcloud default network but a custom network, with a single subnetwork in the same region.
If you have any remote idea on what could possibly be misconfigured, please let me know as I really am losing hope on this. Thanks!
How can I deploy multiple applications from same or different language/runtime originating from a single project in google cloud app engine?
Deploying Multiple Services to Google Cloud App engine.
Create the following files in the app root directory
Create app.yaml file with content:
runtime: nodejs14
service: default
Create myserviceone.yaml file with content:
runtime: nodejs14
service: myserviceone
Create myservicetwo.yaml file with content:
runtime: nodejs14
service: myservicetwo
Deploy using command
gcloud app deploy --project your_project_id app.yaml myserviceone.yaml myservicetwo.yaml
This will deploy the default service as well as my service one and my service two. Check out your cloud console.
You can access them using:
https://myserviceone-dot-yourProjectID.appspot.com/ or
http://myserviceone.yourProjectID.appspot.com/
https://myservicetwo-dot-yourProjectID.appspot.com/ or
http://myservicetwo.yourProjectID.appspot.com/
Today, App Engine has a one-to-one correspondence with a Google Cloud Console project. You cannot deploy multiple "apps" in the same project. However, you might still be able to do what you want depending on your application(s).
App Engine has the concept of "services," which are independent aspects of your application. Your App Engine app can have many services and each service can have its own language/runtime and even be on different App Engine environments.
You could have say a Python service on App Engine standard environment that is used to serve your simple Flask site, could have service that serves an API written in Java 8 on the Standard Environment, and could have yet another service in say Node.js running in the App Engine flexible environment.
Your "default" service is defined in your app.yaml file. Your other services can be defined in different folders and can have either an app.yaml with their service definitions or you could name them something else like backend.yaml. See this simple Python project for the layout of the configuration files.
For more conceptual information about services on App Engine, see Microservices Architecture on Google App Engine.