问题
Currently building an app on app engine standard environment, with python 3.7 and the flask framework. I need to schedule some tasks which will require the app to run several sensitive endpoints periodically.
I want to limit access to these endpoints to the application itself, preventing (non-admin) users from accessing these. In the Python 2 version of app engine, it is possible by specifying login: admin
in the app.yaml
file like so:
# app.yaml for google app engine standard env python 2
handlers:
- url: /this_is/my_protected/endpoint
script: main.app
login: admin
However, in the Python 3.7 incarnation of the app engine environment, this is no longer possible.
I understand that it may be necessary to do the authentication in the main.py
file of my flask app, but I'm not certain where to start. I already have firebase auth working, and the app is authenticating users fine for several user facing endpoints. However I am not certain how to go about authenticating my own app-engine application (or possibly the service account) to run several of its own endpoints. I've tried checking the docs, but they're either sparse, or I simply can't find the information I require.
Is there a straightforward way to accomplish this?
回答1:
As suggested in a comment, here's my simplified (simplistic?) solution to make it such that specific flask end points in google app engine are only accessibly by application code or app engine service accounts. The answer is based on the documentation regarding validating cron requests and validating task requests.
Basically, we write a decorator that will validate whether or not X-Appengine-Cron: true
is in the headers (implying that the end point is being called by your code, not a remote user). If the header is not found, then we do not run the protected function.
# python
# main.py
from flask import Flask, request, redirect, render_template
app = Flask(__name__)
# Define the decorator to protect your end points
def validate_cron_header(protected_function):
def cron_header_validator_wrapper(*args, **kwargs):
# https://cloud.google.com/appengine/docs/standard/python3/scheduling-jobs-with-cron-yaml#validating_cron_requests
header = request.headers.get('X-Appengine-Cron')
# If you are validating a TASK request from a TASK QUEUE instead of a CRON request, then use 'X-Appengine-TaskName' instead of 'X-Appengine-Cron'
# example:
# header = request.headers.get('X-Appengine-TaskName')
# Other possible headers to check can be found here: https://cloud.google.com/tasks/docs/creating-appengine-handlers#reading_app_engine_task_request_headers
# If the header does not exist, then don't run the protected function
if not header:
# here you can raise an error, redirect to a page, etc.
return redirect("/")
# Run and return the protected function
return protected_function(*args, **kwargs)
# The line below is necessary to allow the use of the wrapper on multiple endpoints
# https://stackoverflow.com/a/42254713
cron_header_validator_wrapper.__name__ = protected_function.__name__
return cron_header_validator_wrapper
@app.route("/example/protected/handler")
@validate_cron_header
def a_protected_handler():
# Run your code here
your_response_or_error_etc = "text"
return your_response_or_error_etc
@app.route("/yet/another/example/protected/handler/<myvar>")
@validate_cron_header
def another_protected_handler(some_var=None):
# Run your code here
return render_template("my_sample_template", some_var=some_var)
来源:https://stackoverflow.com/questions/61959706/how-to-limit-access-to-google-app-engine-flask-endpoints-to-just-application-cod