In Google App Engine, I have 3 services, 1 for front end, 2 for back end.
Is there a way to block http calls to my backend services for accounts not from my company's domain (and the service account of the front end), but allow everyone http access to my front end service?
I know there is the firewall option, but this is restricted to IP addresses, I would prefer user based
If it matters all services are python3
There's currently no option to filter traffic to specific App Engine services within a single application/project:
App Engine Firewall filters by source IP ranges but can only be set for the whole app, not per service.
Identity-Aware Proxy can filter access by user account as you'd prefer but also applies to the whole app. Also, it only supports user account and can't be used with service accounts.
One option you may have would be to split your app in 2 different projects. Keep the front-end in one project open to the world and restrict access to the backend services in your other project via firewall rules.
I have seen the following being used in task queues in GAE. Maybe it would help.
If u were using python 2, in standard environment, i think u could have used login handler element in app.yaml file.
You could have added following lines to your app.yaml file:
handlers:
- url: /.*
script: worker.app
login: admin
This prevents other users from accessing this service.
But the same login handler is not available for python3, according to Google Docs.
Just found following in Google Docs:
If a task performs sensitive operations (such as modifying data), you might want to secure the handler URL to prevent a malicious external user from calling it directly. You can prevent users from accessing task URLs by restricting access to App Engine administrators. Task requests themselves are issued by App Engine and can always target a restricted URL.
You can restrict a URL by adding the login: admin element to the handler configuration in your app.yaml file.
You can also call your backend services through cloud tasks or task queues (both are almost the same i guess), in case this only work for cloud tasks.
Find the code usage here:
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/6f5f3bcb81779679a24e0964a6c57c0c7deabfac/appengine/standard/taskqueue/counter
Find details about handler here.
https://cloud.google.com/appengine/docs/standard/python/config/appref#handlers_element
Find details about Cloud task and queue here:
https://cloud.google.com/appengine/docs/standard/python/taskqueue/push/creating-handlers
Related
I have Node JS app running on google app engine.
I have linked a custom domain to it: www.singlelisting.co
BUT
I need wildcard subdomains to also link to the node application
For Example: 6.singlelisting.co or ns324.singlelisting.co
I have not had much luck reading the documentation on google developers site
I am using cloudflare for DNS management and have added * records for all the google A and AAAA records. I believe the problem is have google is seeing the subdomains. Any help would be greatly appreciated
You have two options:
Mapping subdomains: in your App Engine Custom domains config you need to add the following entry *.singlelisting.co and then update the DSN management with the required records (as you probably did). This means that requests through 6.singlelisting.co or ns324.singlelisting.co will be handled by the 6, respectively ns324 service of you App Engine deployment, if available. As the documentation states:
If you set up a wildcard subdomain mapping for your custom domain, then your application serves requests for any subdomain that matches:
.If the user browses a domain that matches a service name, the application serves that service.
By using a dispatch file (more info here): this file will override the routing rules established (or not) through your domains config.
So basically if you do not have services named 6 and ns324 that will automatically handle requests incoming through the wildcard rule *.singlelisting.co, you have to describe the routing using the dispatch.yaml.
My goal is to run a google app engine application with the minimal amount of access to resources it needs. In my case the application will access the datastorage in the project (this is the golang example tutorial using the source code git checkout origin/part4-usingdatastore from https://github.com/GoogleCloudPlatform/appengine-guestbook-go.git)
I did the following
Create a new project, foobarproject3
Created a new app in the project (using golang)
In the project IAM/IAM noticed the
foobarproject3#appspot.gserviceaccount.com, assumed this is the service account, so changed it's role to just BigQuery User. Notice that no Datastorage roles are configured (The UI forces me to provide access to something so I chose BQ)
Followed the tutorial instructions for the using datastore golang app (guestbook application)and deployed the app.
Opened the link to my app: https://foobarproject3.appspot.com/ It failed (this is great, this is what I expected, since the service account does not give the app permissions to read/write datastorage)
Refreshed https://foobarproject3.appspot.com/ and it started to work
There is something basic that I'm not understanding about service account from app engine. Isn't the app engine using these service account to access project resources? Why is the app getting access to datastorage when the service account does not have a policy that would allow access to datastorage?
"My goal is to run a google app engine application with the minimal amount of access to resources it needs."
This is dicey to unpack without more context. What is it that you're trying to achieve that goes beyond App Engine's default behavior?
My experience is that if one starts changing roles without understanding the basics, things go sideways (or South, or West, or Pear-shaped, depending on where you are). So I suspect you shot yourself in the foot in your third bullet.
When you access your app from the browser you are using your own user credentials, not the app's service account. And your user credentials might be exactly the app owner/admin ones, if you created the app using those credentials. See, for example, app.yaml handler login: admin option not effective on standard env python GAE app?
Make sure you log out from the app, or try accessing the app from an incognito browser window or by using a dumb(er) utility to prevent accidental/undesired credential leaking.
The app's service account is for your app to identify itself when it's interacting with other services/apps. From Understanding Service Accounts:
A service account is a special type of Google account that belongs to
your application or a virtual machine (VM), instead of to an
individual end user. Your application assumes the identity of the
service account to call Google APIs, so that the users aren't
directly involved. A service account can have zero or more pairs of
service account keys, which are used to authenticate to Google.
How to restrict access to GAE Flexible site only for all account from my domain in GSuite and eventually other Google accounts that I provide explicitely. AFAIR there where something simillar in Standard GAE version in app.yaml handlers section.
So my scenario:
prodution versions restricted until go-live
dev and stage version restricted permanently
I would like to do this on the IAM level, to reject traffic to the site. But I didn't found anything in docs.
Ok, after rethink the problem and dig deeper in a documentation I found a page about dev environment - https://cloud.google.com/appengine/docs/standard/python/creating-separate-dev-environments.
So my current solution is not to have separate versions like dev, stage and prod and work with them within one project, but to create separate projects for each of environment.
It will also simplify management of DBs - previous I thought about different database in one DB server for particular environment. Now I will have a separate DB instance for it.
Anyway I still have a problem with securing access.
I did it in the same way like in Restrict App Engine access to G Suite accounts on custom domain:
changed Google Authentication to my Google Suite domain
added Custom Domain in my app
added my page domain to my GSuite as a second domain
And I still can connect to my page without auth - even in "Incognito mode" and on others computers and mobiles.
EDIT:
As a workaround I used Django-lockdown module. For the timebeing is more than enough - I have a password, I have a session, I can set it in Middleware or as a decorator for urls.
EDIT 2:
I noticed today a new feature in GAE Flexible - Identity-Aware Proxy.
This is the feature, that I was searching. You can restrict accces by:
Google Account email: user#gmail.com
Google Group: admins#googlegroups.com
Service account: server#example.gserviceaccount.com
Google Apps domain: example.com
I've read some info about authentication, but I would have thought that I could turn off my app's visibility and/or access to the public. This would be useful for alpha testing so surely a setting like this exists? Or do I need to build such things into the app itself?
Without some sort of authentication mechanism your app can't really distinguish between a request coming from you and one coming from someone else.
It might be a good idea to spend a bit of time to analyze your app's authentication requirements and maybe get it done now, while still in alpha.
Depending on the solution it may be fairly simple to integrate.
Google offers multiple authentication options, see What is the difference between Google identity toolkit, Google OAauth and Google+ sign in
I personally opted for the GIT kit for simplicity, flexibility and convenience.
It's possible secure your App's urls so only an authorised user or administrator can access them.
This can be done through the app.yaml file (Python, PHP and Go applications) or the web.xml deployment descriptor (Java applications).
Option A:
Just allow only admin access, in yourapp.yaml
- url: /*
login: admin
script: yourappname.app
Option B:
If you have an static IP (or with a few changes a week), you can detect the IP of the request and let run only from your IP:
class yourHandler(webapp2.RequestHandler):
def get(self):
userIP=self.request.remote_addr
if userIP=="220.123.211.120" # Change this with your static IP
...your code for authorized users.
Option C:
Check request domain (to ensure is called from your own authorized domains), and put some security client side.
class yourHandler(webapp2.RequestHandler):
def get(self):
origin=self.request.headers['Origin']
if origin=="www.yourdomain.com" # Change this with your domain/subdomain
...your code for authorized users.
# I recommend to put also the CORS headers for your own domain
self.response.headers['Access-Control-Allow-Origin'] = "www.yourdomain.com"
Personally, I have a mix of the three options plus a custom authentication to access private content.
By default, every service is born public. Change that, individually, by changing the --ingress setting for the service you want.
gcloud beta app services update <service-name> --ingress <value>
all (default): public to internet.
internal-only: only accessible for resources in the same Cloud Project.
internal-and-cloud-load-balancing: only accessible for resources in the same Cloud Project. And those requests came from configured Cloud Load Balancing.
1 Gateway + a bunch Microservices architecture example:
gcloud beta app services update ms-payment --ingress internal-only
gcloud beta app services update my-backend-gateway --ingress all << default!! Just for example purpose.
In this way, ms-payment is accessible only by resources within the same Cloud Project, even if they are in different VPCs.
Refer the documentation: https://cloud.google.com/appengine/docs/standard/java11/application-security#ingress_controls
I've found recently that you could also use IAP (Identity-Aware Proxy) IA-what? I found a tutorial that implements it on App Engine.
Tutorial for App Engine.
So I didn't want to rely on my own authentication implementation because I'm not an expert, and security it's something very hard to learn in a rush. In a nutshell
Deploy an IAP step 1
Add your app engine (or the whole scope) to your IAP
add your authorized emails on the left panel step 3. For access use:
IAP-Secured Web App User: Grants access to the app and other HTTPS
resources that use IAP.
My Personal opinion here: try to implement as many safety measures as possible (don't rely on one system only), usually they could fail.
I have multiple small to medium sized projects all hosted under my current Rackspace server at apps.foo.com. I would like to move these to an Google App Engine Instance & though I have managed to move a few over, I tend to keep hitting the 10,000 file limit.
Hence I've decided to go with 2 separate App Engine instances though I would like the same domain name to point to them with a setup like apps.foo.com/m1 and apps.foo.com/m2, How can I do this?
I've already migrated the domain name to one instance though I can't figure out how to add another. Please help!
You can't map the same domain to 2 different GAE apps - GAE wouldn't know to which one of the 2 apps hypothetically mapped to the same domain to route an incoming request for the domain.
The request path following the domain is not part of the domain, it is only parsed (following the destination app's parsing rules) after GAE has already selected the destination app based on the request domain.
You might be interested in my recent reply to this Q&A related to reaching deployment quota: Getting error on GAE: Max number of files and blobs is 10000
You can use dispatch to reroute requests to the relevant service.
Deploy your API & WebApp to the same project but as separate services (using the service attribute in the app.yaml file).
Deploy the dispatch
dispatch.yaml
- url: "project-name.appspot.com/api/*"
service: api-service
- url: "project-name.appspot.com/*"
service: web-client-service
For my WebApp's index.html I added also:
<base href="https://project-name.appspot.com/">