3

I would like to upgrade my app engine python version from Python 2 to Python 3. But in second generation app engine we cannot use login field in the handler in app.yaml to make certain pages in app engine only accessible to admin.

As per the guidelines Google suggests as follows: The login field is not supported. Use Cloud Identity and Access Management for user management.

I am not able to figure how can I use Identity and Access Management to control login access?

Aditya Borde
  • 1,227
  • 2
  • 12
  • 31

4 Answers4

1

Are you trying to have admin only endpoints that can actually be used called by an admin user? Or are you trying to have admin only endpoints that are only meant to run cron jobs and/or enqueue tasks?

If it is the former (i.e. have pages/handlers that will actually be viewed by admin personnel), then the dcumentation here may be what you're looking for. Unfortunately, as I have noticed with app engine documentation, you may have to read pages upon pages of "theory" and never see sample code you can try to actually use. My guess however is that you will probably end up writing a decorator to check user authorization and authentication, found below.

If you are only trying to limit access to endpoints to secure running cron jobs and queueing tasks, then you are probably looking for this and this solution. Basically, you write a decorator to verify if the endpoint/handler is being called by a cron job or a task queue. Here's working code which should be good to run:

# 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)
B B
  • 1,116
  • 2
  • 8
  • 20
0

Now you have to use Cloud IAM Client Librares in your code in order to provide access. You can find an example of how to use it in Python 3 here.

Jaroslav
  • 724
  • 4
  • 17
0

User authentication in most of Google Cloud Platform is very different from the Python 2 App Engine approach. You could fully implement user login in a variety of ways in your app to make this restriction, but you can't just set a property in a .yaml file to do this.

Or, try putting your admin functions all in a separate App Engine service, then use IAP (Identity-Aware Proxy) to restrict access to that service to desired users. This page should help. And here's a codelab I wrote that has detailed steps to protect an entire App Engine app, not just one service, with IAP.

Charles Engelke
  • 5,569
  • 1
  • 29
  • 26
0

Things have changed since this question was asked so providing an updated answer

As of March, 2022

  1. You can still use login:required in app.yaml file and it will force a visitor to login with their gmail account.

  2. Python 3 now supports users API (see announcement) which means that if a page is protected by login: required, you can now call is_current_user_admin() on the route handler to confirm it is your administrator

  3. Even if you don't wish to use the users API, you can still get the details of the logged in user (for pages protected by login:required) by checking for any of the following headersX-Appengine-User-Email, X-Appengine-User-Id. You can refer to my response to this other SO question

NoCommandLine
  • 5,044
  • 2
  • 4
  • 15