Authenticating PubSub Push messages in AppEngine - google-app-engine

Is there a way to know for sure that a message received by app engine is from the Google PubSub service? Currently the PubSub service gets a 302 on the URLs configured as "login: admin" in appengine app.yaml. So it keeps retrying.
I would have expected this to behave like the Tasks in Appengine and automatically authenticate to "login:admin" URLs.

The FAQ recommends that when setting up your PubSub push subscription you put a shared secret token as a request parameter which you check for in your handler.
If you additionally would like to verify that the messages originated from Google Cloud Pub/Sub, you could configure your endpoint to only accept messages that are accompanied by a secret token argument, for example,
https://myapp.mydomain.com/myhandler?token=application-secret.
Since PubSub does not use appengine authentication and we are using the token to authenticate you should not specify a login key in your app.yaml entry for this handler. Here's an example:
main.py
class Handler(webapp2.RequestHandler):
def post(self):
token = self.request.params['token']
if token != 'foo':
self.abort(401, 'Not authorized')
# do stuff
app = webapp2.WSGIApplication([
('/', Handler),
], debug=True)
app.yaml
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app

Related

override wildcard dispatch.yaml entry with a specific path in app engine

I am in a situation where I have one app engine service (service-a) that needs to handle a particular path (domain.com/some/particular/path) and I have another app engine service on the same domain (service-b) that needs to handle all other traffic to that domain (domain.com/*).
I've tried structuring my dispatch.yaml as follows, however no matter what I do the domain.com/some/particular/path ends up getting handled by service-b rather than service-a. In other words, all paths are being routed to service-b.
dispatch:
- url: "domain.com/some/particular/path"
service: service-a
- url: "domain.com/*"
service: service-b
How can I handle this situation?
This seems to be more about your code than the dispatch.yaml file that is roting to service-b. For example, I deployed two services, service 1:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return 'Service 1'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
And service 2:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return 'Service 2'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
With the following dispatch.yaml:
dispatch:
- url: "domain.com/app2/"
service: app2
- url: "domain.com/*"
service: default
If I try to access to domain.com/app2/ it shows NOT FOUND error message. If I change the routing in service 2 from #app.route('/') to #app.route('/app2') it works like a charm.
I think that your dispatch.yaml redirects to your service-a but the code inside that service redirects to domain.com.
BTW, if inside your services all your .yaml files are named app.yaml GAE for an unknown reason redirect to the default service so it's better to name every .yaml as the service it handles.

How to proxy an endpoint, using Google App Engine

I used to have an Nginx proxy that would do below :
location /api {
proxy_pass http://www.myapiexample.com;
}
Then if I made a request to my website at www.example.com/api, it would take me to http://www.myapiexample.com.
With the app engine, and I'm using Nodejs as my backend, how I can achieve the same?
Can't find anything in the docs
UPDATE : If I'm understanding correctly, I can't have my Nginx anymore, so I need to find a way to have the same proxying functionality with App Engine.
You can use dispatch.yaml configuration file if both of your web and api modules are on app engine. dispatch.yaml sends incoming requests to a specific service depending on the path or hostname in the URL.
dispatch:
# Default service serves simple hostname request.
- url: " example.com"
service: default
# Send all api traffic to the api backend.
- url: "*/api/*"
service: api-backend
You can read more about how to use dispatch file.
If your api module is not on app engine you can redirect requests on application level
dispatch:
# Send all api traffic to the api backend.
- url: "*/api/*"
script: router.py
You can write your routing code in router.py something like
class RouteHandler(webapp.RequestHandler):
def get(self):
self.redirect("http://www.myapiexample.com;", True)

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.

Cloud Endpoints Handler SSL redirect blocked by CORS

I would like my Cloud Endpoints API to be called with HTTPS. My app.yaml file contains the following:
# The endpoints handler must be mapped to /_ah/api.
- url: /_ah/api/.*
script: main.api
secure: always
If a client (i.e. website) makes an insecure (HTTP) call to the endpoint URL, App Engine performs a redirect to the secure version (HTTPS)
For example, suppose my App Engine app is at http://api.endpoints.my-app.appspot.com and the API endpoint for making a HTTP GET request to the method mymethod is:
http://api.endpoints.my-app.appspot.com/_ah/api/myapp/v1/mymethod
App Engine redirects to the HTTPS version:
https://api.endpoints.my-app.appspot.com/_ah/api/myapp/v1/mymethod
However, the redirect from is blocked:
blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.
How can I add the required header to my resource (i.e. my Cloud Endpoints API on App Engine)? Google's documentation states CORS is enabled by default on App Engine Standard - which is what I'm using. So I'm unsure why this is even a problem.
You should be able to configure the Access-Control-Allow-Origin header in app.yml. For your case, please try the following to the app.yml file:
handlers:
- url: /_ah/api/.*
script: main.api
secure: always
http_headers:
Access-Control-Allow-Origin: http://localhost:4000
More to read:
app.yml reference
A related SO question

App engine endpoints API - 404 with custom domain

I'm trying to use custom domain with app engine. Everything works fine with localhost and appspot url. But with custom domain endpoints api doesn't work; the API discovery request (https://cc.mdsarowar.me/_ah/api/discovery/v1/apis/conference/v1/rest) returns Not Found with error code 404.
Here is my app.yaml (full code):
- url: /_ah/spi/.*
script: conference.api
secure: optional
And endpoints api (full code):
#endpoints.api( name='conference',
version='v1',
allowed_client_ids=[WEB_CLIENT_ID, API_EXPLORER_CLIENT_ID],
scopes=[EMAIL_SCOPE], hostname = 'cc.mdsarowar.me')
class ConferenceApi(remote.Service):
"""Conference API v0.1"""
........
Thanks in advance.
As per the docs:
Note: Google Cloud Endpoints does not support custom domains.
Edit
There is an open feature request for this so you may want to star it.

Resources