Giter Site home page Giter Site logo

gae-secure-scaffold-python3's Introduction

Secure Scaffold

Introduction

This is not an officially supported Google product.

Secure Scaffold helps you build websites on Google's App Engine standard platform with security features enabled by default. It is designed for both static websites which have no dynamic back-end code, and Python web applications.

The scaffold consists of:

  • A Cookiecutter template for starting a static website project.
  • Examples of App Engine websites: a static-only website; a mostly static website with back-end logic to redirect users depending on the Accept-Language header; a Flask application that uses CSP nonces, CSRF-protected forms, and more security features.
  • A Python library for creating a Flask website with secure defaults. This uses the Flask-SeaSurf library to enable CSRF protection, and the Flask-Talisman library to enable CSP (Content Security Policy) headers and other security features.

Using the website template

Secure Scaffold provides a Cookiecutter template. Install the Cookiecutter command, then create a project from the template - you will be prompted for a project name. Project names must start with a letter and use lower-case letters and numbers and dashes, for example "my-project-1":

cookiecutter https://github.com/google/gae-secure-scaffold-python3.git

Cookiecutter will create a new folder with your project name. Inside the folder is a configuration for a static website, with instructions for deploying the website to App Engine.

Website examples

We have included examples of websites that use the Secure Scaffold. We hope you find these useful when building your own websites!

  • A static site - uses app.yaml to serve a home page and all assets from a directory, with HTTPS and secure headers.
  • A mostly-static site which redirects requests depending on the Accept-Language header - uses app.yaml to serve the static assets and configures a root page handler that redirects visitors to /intl/<code>.
  • A secure Flask application - uses securescaffold to create an application with secure defaults, and demonstrates how to customise the application and extend it for common uses.

Using the secure scaffold Python library

Installation and quick start

Add the library to requirements.txt:

# requirements.txt
https://github.com/google/gae-secure-scaffold-python3/archive/master.zip

Better is to pin to a specific tag or revision. For example:

https://github.com/google/gae-secure-scaffold-python3/archive/1.1.0.zip

Install the library in your Python development environment:

pip install https://github.com/google/gae-secure-scaffold-python3/archive/master.zip

Import the library and use it to create a Flask application:

# main.py
import securescaffold

app = securescaffold.create_app(__name__)

@app.route("/")
def hello():
  return "<h1>Hello</h1>"

The line app = securescaffold.create_app(__name__) creates a Flask application which includes the Flask-SeaSurf and Flask-Talisman libraries. It also reads an initial configuration from securescaffold.settings.

The included examples show how to start the datastore emulator and the Flask server for local development and how to start and stop the emulator when writing tests. N.B. the emulator is for testing and local development only. Do not use it when deploying your application to App Engine.

Configuring your application with FLASK_SETTINGS_FILENAME

When you create a Flask app with app = securescaffold.create_app(__name__) the configuration is read from securescaffold.settings and the filename in the FLASK_SETTINGS_FILENAME environment variable (if it exists).

You can customise your application by creating a Python file. Then set the environment variable FLASK_SETTINGS_FILENAME to point to your Python file. When your code calls securescaffold.create_app(__name__), your custom configuration will be read from the Python file.

# Custom settings in "settings.py"
SESSION_COOKIE_NAME = "my-custom-cookie"

And add the environment variable to app.yaml:

# app.yaml
runtime: python37

handlers:
  - url: /.*
    script: auto

env_variables:
  FLASK_SETTINGS_FILENAME: "settings.py"

See Configuration Handling in the Flask documentation for more details.

Changing the CSP configuration

Secure Scaffold uses Flask-Talisman's Google policy as the default CSP policy. You can customise the CSP policy by adding these variables to your custom configuration:

Configuration name Talisman equivalent Default value
CSP_POLICY content_security_policy GOOGLE_CSP_POLICY
CSP_POLICY_NONCE_IN content_security_policy_nonce_in None
CSP_POLICY_REPORT_URI content_security_policy_report_uri None
CSP_POLICY_REPORT_ONLY content_security_policy_report_only None

See the Flask-Talisman documentation for details of how to use these settings.

CSRF protection with Flask-SeaSurf

The Flask-SeaSurf library provides CSRF protection. An instance of SeaSurf is assigned to the Flask application as app.csrf. You can use this to decorate a request handler as exempt from CSRF protection:

# main.py
import securescaffold

app = securescaffold.create_app(__name__)

@app.csrf.exempt
@app.route("/csp-report", methods=["POST"])
def csp_report():
  """CSP report handlers accept POST requests with no CSRF token."""
  return ""

See the Flask-SeaSurf documentation for details of configuration and use.

Authenticating users with IAP

App Engine supports the IAP service (Identity-Aware Proxy). When IAP is enabled and configured to require authentication, you can use Secure Scaffold to get the signed-in user's email address. This is equivalent to the Users API that was available with the Python 2.7 runtime, but which is not available on the Python 3 runtime.

# main.py
import securescaffold
from securescaffold.contrib.appengine import users

app = securescaffold.create_app(__name__)

@app.route("/")
def hello():
    user = users.get_current_user()

    if user:
        email = user.email()
        user_id = user.user_id()

        return "Hello signed-in user"

  return "Not signed-in"

Securing request handlers and cron tasks

You must decorate a cron request handler with @securescaffold.cron_only to prevent unauthorized requests.

Secure Scaffold (thanks to Flask-Talisman) configures HTTP requests to be redirected to use HTTPS. However App Engine's cron scheduler will make HTTP requests to your cron request handlers (not HTTPS), and the cron requests will fail if your application tries to redirect the request to use HTTPS.

An instance of Talisman is assigned to the Flask application as app.talisman. You can use this to allow HTTP requests to a cron request handler.

# main.py
import securescaffold

app = securescaffold.create_app(__name__)

@app.route("/cron")
@app.talisman(force_https=False)
@securescaffold.cron_only
def cron_task():
    # This request handler is protected by the `securescaffold.cron_only`
    # decorator so will only be called if the request is from the cron
    # scheduler or from an App Engine project admin.
    return ""

Secure Scaffold includes the following decorators to help prevent unauthorised access to your request handlers:

  • securescaffold.admin_only Checks the request was made by a signed-in App Engine admin. If not, the request receives a 403 forbidden response. N.B. you must restrict access to your website with IAP to allow administrators to sign-in.
  • securescaffold.cron_only Checks the request was made by the Cron / Tasks scheduler or by a signed-in App Engine admin. If not, the request receives a 403 forbidden response.
  • securescaffold.tasks_only Same as the securescaffold.cron_only decorator.

Third-party credits

This project is built on other projects. Here are some of them:

gae-secure-scaffold-python3's People

Contributors

cyberphobia avatar davidwtbuxton avatar dependabot[bot] avatar insgadget avatar justinatpsycle avatar kencanak avatar leitea-google avatar lweichselbaum avatar matir avatar mikispag avatar miuraken avatar n1ruragu avatar neo avatar pames avatar skezo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gae-secure-scaffold-python3's Issues

Can't setup X-Frame-Options (?)

Hi!

It looks like it's not possible to customize the value of the X-Frame-Options header. The get_talisman_config() function seems to only pick up a selection of settings, which does not include the frame-options one.

I need this because I'm building component that will be embedded in a website on another domain, in an iframe.

Am I missing something ?

Document how to use CSRF with SPAs

Please document how to use this secure scaffold with single page applications, e.g. Angular and React SPAs. These would typically serve the static HTML directly from AppEngine (not through Python templating), which makes it impossible to inject the CSRF token. To make things more complicated, the CSRF token can also not be read from client-side JavaScript, because the secure scaffold defaults set the cookie to HttpOnly.

As far as I can tell, setting the cookie to HttpOnly does not add to the protection in a major way - e.g. see https://docs.djangoproject.com/en/3.0/ref/settings/#csrf-cookie-httponly.

Preserve query params on redirect

Issue

Currently, any query string set on the redirect path is not preserved when redirected.

Behaviour

Current: /?foo=bar -> /intl/en/
Expected: /?foo=bar -> /intl/en/?foo=bar

Setup

# Follows github.com/google/gae-secure-scaffold-python3/blob/master/examples/language-redirect/main.py

app = securescaffold.create_app(__name__)
app.add_url_rule("/", "lang_redirect", securescaffold.views.lang_redirect)

app.config["LOCALES"] = ["en"]
app.config["LOCALES_REDIRECT_TO"] = "/intl/{locale}/"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.