From cb8636021c1aeabddc6b624b98f2d3ebfe4e8c25 Mon Sep 17 00:00:00 2001 From: Neyts Zupan Date: Thu, 7 Nov 2024 12:52:52 +0000 Subject: [PATCH] Fix wording (#79) * release 0.10 * refactor whitelist to allowlist --- CHANGES.rst | 15 +++++++++++++++ README.rst | 8 ++++---- pyproject.toml | 2 +- pyramid_heroku/herokuapp_access.py | 14 +++++++------- pyramid_heroku/tests/test_herokuapp_access.py | 16 ++++++++-------- 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a133234..25f5cbd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,21 @@ Changes ======= +0.10.1 +------ + + * Refactor `pyramid_heroku.herokuapp_allowlist` to + `pyramid_heroku.herokuapp_allowlist`. + [zupo] + + +0.10 +---- + + * Enforce HerokuappAccess whitelisting even if list is unset/empty. + [zupo] + + 0.9.2 ----- diff --git a/README.rst b/README.rst index 38bb5bc..0668dcd 100644 --- a/README.rst +++ b/README.rst @@ -8,9 +8,9 @@ pyramid_heroku is a collection of tweens and helpers to successfully run `Pyrami It provides the following: -* ``ClientAddr`` tween that sets real user's IP to ``request.client_addr``. Without this tween you cannot do IP-based geolocation, IP whitelisting, etc. +* ``ClientAddr`` tween that sets real user's IP to ``request.client_addr``. Without this tween you cannot do IP-based geolocation, IP allowlisting, etc. * ``Host`` tween that sets `request.host` to proxied `X-Forwarded-Host` header (note: potential security risk) -* ``HerokuappAccess`` tween that denies access to your app's ``.herokuapp.com`` domain for any non-whitelisted IPs. This is helpful because you don't want anyone outside your team (i.e. usual visitors/users and search bots) to be able to visit ``.heroku.com`` besides the domain the app is deployed on. This is for security and SEO purposes. +* ``HerokuappAccess`` tween that denies access to your app's ``.herokuapp.com`` domain for any non-allowlisted IPs. This is helpful because you don't want anyone outside your team (i.e. usual visitors/users and search bots) to be able to visit ``.heroku.com`` besides the domain the app is deployed on. This is for security and SEO purposes. * ``migrate.py`` script for automatically running alembic migrations on deploy. * ``maintenance.py`` script for controlling Heroku maintenance mode. @@ -46,8 +46,8 @@ Usage example for tweens:: return config.make_wsgi_app() The ``pyramid_heroku.herokuapp_access`` tween depends on -``pyramid_heroku.client_addr`` tween and it requires you to list whitelisted IPs -in the ``pyramid_heroku.herokuapp_whitelist`` setting. +``pyramid_heroku.client_addr`` tween and it requires you to list allowlisted IPs +in the ``pyramid_heroku.herokuapp_allowlist`` setting. The ``pyramid_heroku.client_addr`` tween sets request.client_addr to an IP we can trust. It handles IP spoofing via ``X-Forwarded-For`` headers and diff --git a/pyproject.toml b/pyproject.toml index 8a72999..6b63898 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pyramid_heroku" -version = "0.9.2" +version = "0.10" description = "A bunch of helpers for successfully running Pyramid on Heroku." readme = "README.rst" include = [ "CHANGES.rst", "COPYING.txt" ] diff --git a/pyramid_heroku/herokuapp_access.py b/pyramid_heroku/herokuapp_access.py index 86ed916..04071c0 100644 --- a/pyramid_heroku/herokuapp_access.py +++ b/pyramid_heroku/herokuapp_access.py @@ -1,4 +1,4 @@ -"""Prevent .herokuapp.com access to non-whitelisted IPs""" +"""Prevent .herokuapp.com access to non-allowlisted IPs""" from pyramid.response import Response @@ -10,11 +10,11 @@ def includeme(config): class HerokuappAccess(object): - """Deny access to 'herokuapp.com' urls for IPs that are not whitelisted. + """Deny access to 'herokuapp.com' urls for IPs that are not allowlisted. Denies access to hosts that contain 'herokuapp.com' to ips that are not - whitelisted. Registry settings must contain a key - 'pyramid_heroku.herokuapp_whitelist', whose value must be a list of + allowlisted. Registry settings must contain a key + 'pyramid_heroku.herokuapp_allowlist', whose value must be a list of strings (IPs). For this tween to work, you must include the ClientAddr tween and make sure this tween executes after the ClientAddr tween. @@ -26,13 +26,13 @@ def __init__(self, handler, registry): self.settings = getattr(registry, "settings", {}) def __call__(self, request): - whitelisted_ips = request.registry.settings.get( - "pyramid_heroku.herokuapp_whitelist", [] + allowlisted_ips = request.registry.settings.get( + "pyramid_heroku.herokuapp_allowlist", [] ) if ( "herokuapp.com" in request.headers["Host"] - and request.client_addr not in whitelisted_ips + and request.client_addr not in allowlisted_ips ): if request.registry.settings.get("pyramid_heroku.structlog"): import structlog diff --git a/pyramid_heroku/tests/test_herokuapp_access.py b/pyramid_heroku/tests/test_herokuapp_access.py index 7ce1e97..af2fce2 100644 --- a/pyramid_heroku/tests/test_herokuapp_access.py +++ b/pyramid_heroku/tests/test_herokuapp_access.py @@ -24,7 +24,7 @@ def setUp(self): self.handler = mock.Mock() self.request = testing.DummyRequest() self.request.registry.settings = { - "pyramid_heroku.herokuapp_whitelist": ["1.2.3.4"], + "pyramid_heroku.herokuapp_allowlist": ["1.2.3.4"], "pyramid_heroku.structlog": 1, } structlog.configure(processors=[self.wrap_logger], context_class=dict) @@ -33,7 +33,7 @@ def tearDown(self): tweens_handler.clear() testing.tearDown() - def test_whitelisted_ip(self): + def test_allowlisted_ip(self): from pyramid_heroku.herokuapp_access import HerokuappAccess self.request.client_addr = "1.2.3.4" @@ -42,7 +42,7 @@ def test_whitelisted_ip(self): HerokuappAccess(self.handler, self.request.registry)(self.request) self.handler.assert_called_with(self.request) - def test_non_whitelisted_ip(self): + def test_non_allowlisted_ip(self): from pyramid_heroku.herokuapp_access import HerokuappAccess self.request.client_addr = "6.6.6.6" @@ -80,8 +80,8 @@ def test_other_hostname(self): HerokuappAccess(self.handler, self.request.registry)(self.request) self.handler.assert_called_with(self.request) - def test_herokuapp_whitelist_not_set(self): - "Even if whitelist is not set, the protection should still work." + def test_herokuapp_allowlist_not_set(self): + "Even if allowlist is not set, the protection should still work." from pyramid_heroku.herokuapp_access import HerokuappAccess self.request.client_addr = "6.6.6.6" @@ -91,13 +91,13 @@ def test_herokuapp_whitelist_not_set(self): HerokuappAccess(self.handler, self.request.registry)(self.request) assert not self.handler.called, "handler should not be called" - def test_herokuapp_whitelist_empty(self): - "Even if whitelist is empty, the protection should still work." + def test_herokuapp_allowlist_empty(self): + "Even if allowlist is empty, the protection should still work." from pyramid_heroku.herokuapp_access import HerokuappAccess self.request.client_addr = "6.6.6.6" self.request.headers = {"Host": "foo.herokuapp.com"} - self.request.registry.settings = {"pyramid_heroku.herokuapp_whitelist": []} + self.request.registry.settings = {"pyramid_heroku.herokuapp_allowlist": []} HerokuappAccess(self.handler, self.request.registry)(self.request) assert not self.handler.called, "handler should not be called"