From eb6daf3d07f48f546981d973c96283a292f7c337 Mon Sep 17 00:00:00 2001 From: Irina Lamarr Date: Sat, 16 Dec 2023 19:50:35 -0500 Subject: [PATCH 1/2] Added security headers --- requirements.txt | 3 +++ service/__init__.py | 3 +++ tests/test_routes.py | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/requirements.txt b/requirements.txt index 4a17116..bb4a90c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,3 +27,6 @@ coverage==6.3.2 # Utilities httpie==3.2.1 + +# Security +Flask-Talisman diff --git a/service/__init__.py b/service/__init__.py index a62a9b3..108d95c 100644 --- a/service/__init__.py +++ b/service/__init__.py @@ -6,6 +6,7 @@ """ import sys from flask import Flask +from flask_talisman import Talisman from service import config from service.common import log_handlers @@ -13,6 +14,8 @@ app = Flask(__name__) app.config.from_object(config) +talisman = Talisman(app) + # Import the routes After the Flask app is created # pylint: disable=wrong-import-position, cyclic-import, wrong-import-order from service import routes, models # noqa: F401 E402 diff --git a/tests/test_routes.py b/tests/test_routes.py index f1412e8..b1523bd 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -12,12 +12,14 @@ from service.common import status # HTTP Status Codes from service.models import db, Account, init_db from service.routes import app +from service import talisman DATABASE_URI = os.getenv( "DATABASE_URI", "postgresql://postgres:postgres@localhost:5432/postgres" ) BASE_URL = "/accounts" +HTTPS_ENVIRON = {'wsgi.url_scheme': 'https'} ###################################################################### @@ -34,6 +36,7 @@ def setUpClass(cls): app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URI app.logger.setLevel(logging.CRITICAL) init_db(app) + talisman.force_https = False @classmethod def tearDownClass(cls): @@ -171,3 +174,16 @@ def test_get_account_list(self): self.assertEqual(resp.status_code, status.HTTP_200_OK) data = resp.get_json() self.assertEqual(len(data), 5) + + def test_security_headers(self): + """It should return security headers""" + response = self.client.get('/', environ_overrides=HTTPS_ENVIRON) + self.assertEqual(response.status_code, status.HTTP_200_OK) + headers = { + 'X-Frame-Options': 'SAMEORIGIN', + 'X-Content-Type-Options': 'nosniff', + 'Content-Security-Policy': 'default-src \'self\'; object-src \'none\'', + 'Referrer-Policy': 'strict-origin-when-cross-origin' + } + for key, value in headers.items(): + self.assertEqual(response.headers.get(key), value) From d9b1905ab52138be38f0096357e97ae0ad8b47d3 Mon Sep 17 00:00:00 2001 From: Irina Lamarr Date: Sat, 16 Dec 2023 20:05:15 -0500 Subject: [PATCH 2/2] Added CORS headers --- requirements.txt | 5 ++--- service/__init__.py | 2 ++ tests/test_routes.py | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index bb4a90c..a94916c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,6 +27,5 @@ coverage==6.3.2 # Utilities httpie==3.2.1 - -# Security -Flask-Talisman +flask-talisman +Flask-Cors diff --git a/service/__init__.py b/service/__init__.py index 108d95c..350a3a3 100644 --- a/service/__init__.py +++ b/service/__init__.py @@ -7,6 +7,7 @@ import sys from flask import Flask from flask_talisman import Talisman +from flask_cors import CORS from service import config from service.common import log_handlers @@ -15,6 +16,7 @@ app.config.from_object(config) talisman = Talisman(app) +CORS(app) # Import the routes After the Flask app is created # pylint: disable=wrong-import-position, cyclic-import, wrong-import-order diff --git a/tests/test_routes.py b/tests/test_routes.py index b1523bd..36eeb72 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -187,3 +187,10 @@ def test_security_headers(self): } for key, value in headers.items(): self.assertEqual(response.headers.get(key), value) + + def test_cors_security(self): + """It should return a CORS header""" + response = self.client.get('/', environ_overrides=HTTPS_ENVIRON) + self.assertEqual(response.status_code, status.HTTP_200_OK) + # Check for the CORS header + self.assertEqual(response.headers.get('Access-Control-Allow-Origin'), '*')