App Engine Managed VM custom runtime app.yaml login: admin - google-app-engine

I am trying to run a Jenkins server in a Docker container, as a GAE Managed VM 'custom runtime'
I want to use the app.yaml to enforce login: admin auth
Docs say:
It isn't necessary to define a handler stanza in your config file. If your application is serving only dynamic requests, the handler stanza can be omitted. If you want to set up a secure URL for dynamic requests, use login: admin with an otherwise empty handler.
If I don't define the handler stanza then Jenkins web UI works fine, but I have no auth on the url.
I have tried the following variations but they all lead to symptom where the Jenkins dashboard loads, but all static files are all broken and can't act because js not loaded
handlers:
- url: /.*
login: admin
handlers:
- login: admin

this is the working stanza:
handlers:
- url: /.*
script: dynamic
login: admin

Related

App Engine matching any "subdomain" to my service

I have a Strapi application on Google App Engine as the Default service.
The default URL App Engine generates is https://my-project.uc.r.appspot.com
When I create any other version for my default service or deploy another service, the new URLs would be something like: https://[identifier]-dot-my-project.uc.r.appspot.com
My problem is that if I replace [identifier] with anything at all it opens my Strapi Application root page.
I don't think this has anything to do with Strapi at all, it's probably a feature of App Engine.
My question is: How do I stop this from happening? I want only proper URLs to be matched. That is, if I create a "dev" version, I should be able to access it with the following URL: https://dev-dot-my-project.uc.r.appspot.com, but I don't want any other URL to be matched, like: https://12345-dot-my-project.uc.r.appspot.com
I am using a Standard Environment with the default app.yaml from Strapi docs
runtime: nodejs16
instance_class: F2
env_variables:
HOST: '0.0.0.0'
NODE_ENV: 'production'
DATABASE_NAME: 'strapi'
DATABASE_USER: 'postgres'
DATABASE_PASSWORD: '<password>'
INSTANCE_CONNECTION_NAME: '<instance_identifier>'
beta_settings:
cloud_sql_instances: '<instance_identifier>'
When the app is deployed to App Engine, the app.yaml is automatically modified to add some default params.
runtime: nodejs16
env: standard
instance_class: F2
handlers:
- url: .*
script: auto
I thought maybe this url: .* was the cause of this and tried to change it to url: /.* (Docs), but App Engine still add the url: .* again anyway at the end and it will have both handlers.
This is expected behavior. Per the documentation
If a request matches the PROJECT_ID.REGION_ID.r.appspot.com portion of the hostname, but includes a service, version, or instance name that does not exist, then the request is routed to the default service.
In your example, when you hit the url - https://12345-dot-my-project.uc.r.appspot.com and it turns out '12345' is not a valid version, the default service - https://my-project.uc.r.appspot.com will take over.
If you really want to block it, you'll have to write code to read the incoming url (i.e. the original url that came in), determine the version and if it's not in your list of versions, you raise an error (maybe return 404). This is basically what you'd do if you were offering a service built on GAE where each of your users had their own custom domain (version of your app) e.g. a blog hosting platform, an ecommerce site (like Shopify)

App Engine - subdomain pointing to particular service

I have two subdomains registered in my App Engine application:
service-a.my-app.com
service-b.my-app.com
I have added all the records (CNAME, A) on the server.
I have three services in my GAE:
default
service-a
service-b
And I want each subdomain to point to the correct service. However, each time I access them, only the default service is used.
Side note: the GAE is running a flexible environment for laravel 5.4 and my dispatch.yaml (located in default service is as follows:
dispatch:
-url: "service-a.my-app.com/*"
service: service-a
-url: "service-b.my-app.com/*"
service: service-b
This worked for me. Hope this helps someone.
GAE Standard:
I have an angular project which will load for any subdomain except one subdomain "api".
The backend is written in Go and all services are under a service named "api"
STEP1: Setting local env
Angular project has the following app.yaml
runtime: python27
api_version: 1
instance_class: F1
handlers:
- url: /
static_files: default/index.html
upload: default/index.html
- url: /
static_dir: default
My service.yaml file resides in a separate directory and has the following
runtime: go
api_version: go1
instance_class: F1
service: api
handlers:
- url: /.*
script: _go_app
secure: always
My dispatch.yaml has the following
dispatch:
- url: "api.MYDOMAINNAME.com/*"
service: api
//Add more subdomain : services mapping here
I deployed all these files using gcloud app deploy command
Step 2 - Configure Custom domains in GAE.
In GAE Console, goto Project Settings > Custom Domains
Add your domain
Verify your domainusing one of the methods provided by Google.
Update CNAME, A and AAA records in your domain service provider's DNS Settings
Step 3 - Configure Sub Domain
Add a subdomain api.MYDOMAINNAME.com
Add the CNAME in your domain service provider's settings.
// add more subdomains if required
Add a Wildcard subdomain *.MYDOMAINNAME.com
Add the CNAME in your domain service provider's settings to redirect * to google.
Finally:
Wait for few minutes for the settings to be applied.
Now your application will redirect MYDOMAINNAME.com, www.MYDOMAINNAME.com , *.MYDOMAINNAME.com to the Angular code
and
api.MYDOMAINNAME.com to your api service
Please note that dispatch.yaml is an app-level configuration, not a service-level one and occasionally updating the service containing it doesn't automatically update the app-level configs.
You should use the specific deployment commands for dispatch.yaml, executed from the directory containing the file:
gcloud app deploy dispatch.yaml if you're using the Cloud SDK
appcfg.py update_dispatch . if you're still using the GAE SDK
See also dispatch.yaml not getting updated.
The same is true for other app-level .yaml config files as well, which is probably one reason for each having its own update/deploy command (and also to allow deploying them independently of any particular app service. Somehow related: Why do I need to deploy a "default" app before I can deploy multiple services in GCP?
Actually the answer was really easy: You just need to map a wildcard subdomain and GAE would the use the service corresponding to the prefix.

Mapping subdomain to a service in Google App Engine project

I have a Google App Engine project with following yaml file
handlers:
- url: /web/.*
script: web_server.app
- url: /api/.*
script: rest_server.app
How do I make sure subdomain, of a domain I own, be served by rest_server.app script.
Example: If I own example.com
I want example.com to be served by web_server.app, and api.example.com to be served by rest_server.app
Is it possible to do that using Google App Engine.
Example:
handlers:
- url: example.com/.*
script: web_server.app
- url: api.example.com/.*
script: rest_server.app
Request routing in the app.yaml can not be used to route based on the URL's domain name, see the url table row in the Handlers element doc section.
Because of that you can't really have a single module/service serving your app while simultaneously stripping the filepath portion of the URL you're currently used in your handlers' url configs for routing requests to one script or the other.
You can obtain what you desire by splitting your app into 2 separate services/modules, each handling one script. One of the modules has to be the default module, I'd make the web one the default.
A dispatch.yaml file would be used to route requests to their respective modules based on the URL hostname.
The web.yaml file would contain:
module: default
handlers:
- url: /.*
script: web_server.app
The rest.yaml file would contain:
module: rest
handlers:
- url: /.*
script: rest_server.app
In the dispatch.yaml file you only need routes for the non-default module(s), requests matching no routes are by default routed to the defaut module:
- url: "api.example.com/*"
module: rest
You can find a more complete example here: https://stackoverflow.com/a/34111170/4495081
You'd then map both your example.com naked domain and api.example.com subdomain to your app. Follow the Adding a custom domain for your application procedure, paying extra attention to the sections which are slightly different when configuring a naked domain vs a subdomain. See also https://stackoverflow.com/a/36317462/4495081
There is one problem, tho - dispatch.yaml routing based on hostnames doesn't work with the local development server, the requests destined for the rest module would actually go to the default module.
A simpler workaround would be to direct the rest module clients to the actual localhost:PORT URL where the local devserver's rest module listens (displayed in the terminal at dev server startup), instead.
This might not be possible in all cases or for all apps. For example it's an issue if the app makes cross-module requests with auto-generated URLs.
In such cases, to work around it you can temporarily insert a small path portion in the rest.yaml URL, only during testing on the local dev server the rest module (you'd need matching changes on the client side and/or the cross-module URL generation logic):
module: rest
handlers:
- url: /api/.*
script: rest_server.app
And then you can add a dispatch.yaml rule that is not host-based and would also with the local dev server. This can be left in there permanently, it doesn't hurt if/when deployed in production when the temporary rest.yaml change is reversed:
- url: "api.example.com/*"
module: rest
- url: "*/api/*"
module: rest

How can I use "login: required" on a Google App Engine app using a custom domain?

I have a Python GAE app on a custom domain. When I add login: required to any handler, the site redirects to the app's appspot.com domain instead of my custom domain. The functionality of the site isn't affected, and all handlers and routes continue to work as expected — just on the appspot.com domain instead.
Example snippet from the app.yaml below. mydomain.com works fine with the custom domain, mydomain.com/test and any other handlers redirect to the appspot.com domain after authentication (myapp.appspot.com/test).
- url: /
script: main.application
- url: /test
script: main.application
login: required
- url: /.*
script: main.application
login: required
Is this a configuration issue with how App Engine is handling the domain, or is this an issue with the redirect used by the login: required setting?
You need to set Authorized redirect URIs in your Developer Console (under API | Credentials) to your custom domain rather than the default appspot.com. So the requests coming from the custom domain would be 'called-back' to the custom domain as well.
Take a look on the attached screenshot on how this is configured for my application.
[]

Can I configure all URLs to be secure on Google App Engine (python app) with just one setting?

Is it possible in the app.yaml to make sure that all requests to my app on http get redirected to https without having to specify secure: always for every url endpoint in my app.
Currently I am doing this:
url: /users/login
script: users_handler.app
secure: always
url: /signin
script: authentication.app
secure: always
url: /users/logout
script: users_handler.app
secure: always
But as new urls are added, its risky as a developer might forget to specify secure always. I would prefer to just specify a global setting that applies to all urls in my app.
If you don not want to use secure in your app.yaml you can accomplish this with webapp2.
https://webapp2.readthedocs.io/en/latest/guide/routing.html#restricting-uri-schemes
And here is a working code eaxmple: How to use WSGI to reroute a user from http to https
I feel like archaeologist, but nonetheless I'll share my findings.
All it has to be made is to add this into app.yaml:
handlers:
- url: /.*
secure: always
script: auto
There is even documentation example with that case. It's exactly the same as mine, but I removed redirection.
I don't believe that is possible. However, I think you can mitigate the problem by restructuring the URLs you have defined in your app.yaml.
The URLs is matched against handlers in your app.yaml starting from the top. So you should specify your one-off URLs and then at the bottom have a catch all setting that routes all URLs that didn't match the other settings to your default handler. You application should then display 404 pages etc. for URLs that don't exist in your application.
Something like this would work:
- url: /signin
script: authentication.app
secure: always
- url: /.*
script: users_handler.app
secure: always
This way you only have to specify a couple handlers for your application and you are much less likely to miss setting secure:always when adding a new URL or setting.
Hope that helps!

Resources