Skip to content

Commit

Permalink
Merge 7a3f678 into 3c69a5d
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskuehl committed Aug 24, 2017
2 parents 3c69a5d + 7a3f678 commit c5511f0
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 47 deletions.
1 change: 1 addition & 0 deletions .activate.sh
1 change: 1 addition & 0 deletions .deactivate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
deactivate
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
*.egg-info
*.py[co]
.*.sw[a-z]
.cache
.coverage
.tox
.venv.touch
/venv*
/venv
coverage-html
dist
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- repo: https://github.com/pre-commit/pre-commit-hooks
sha: 44e1753f98b0da305332abe26856c3e621c5c439
sha: v0.9.2
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Expand All @@ -11,7 +11,7 @@
- id: requirements-txt-fixer
- id: flake8
- repo: https://github.com/asottile/reorder_python_imports
sha: 017e2f64306853ec7f000db52b8280da27eb3b96
sha: v0.3.5
hooks:
- id: reorder-python-imports
language_version: python3.5
language_version: python3.6
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: python
python: 3.5
python: 3.6
env: # These should match the tox env list
- TOXENV=py27
- TOXENV=py35
- TOXENV=py36
- TOXENV=pypy
install: pip install coveralls tox
script: tox
Expand Down
17 changes: 5 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
REBUILD_FLAG =

.PHONY: all
all: venv test

.PHONY: venv
venv: .venv.touch
tox -e venv $(REBUILD_FLAG)
venv:
tox -e venv

.PHONY: tests test
tests: test
test: .venv.touch
test:
tox $(REBUILD_FLAG)

.venv.touch: setup.py requirements-dev.txt
$(eval REBUILD_FLAG := --recreate)
touch .venv.touch

.PHONY: clean
clean:
find . -iname '*.pyc' -delete
find . -name '*.pyc' -delete
rm -rf .tox
rm -rf ./venv-*
rm -f .venv.touch
rm -rf ./venv
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,37 @@ framework.
## Usage


If you're reading from a traditional `mod_rpaf` config file:

```python
from wsgi_mod_rpaf import from_apache_config
from wsgi_mod_rpaf import wsgi_mod_rpaf_middleware

...

app = wsgi_mod_rpaf_middleware(app, '/path/to/rpaf.conf')
app = wsgi_mod_rpaf_middleware(
app,
trusted_networks=from_apache_config('/path/to/rpaf.conf'),
)
```

Alternatively, you can supply the networks yourself:

```python
import ipaddress

...

app = wsgi_mod_rpaf_middleware(
app,
trusted_networks={
ipaddress.ip_network('127.0.0.1'),
ipaddress.ip_network('10.0.0.0/8'),
},
)
```


## Supported directives

### `RPAFproxy_ips`
Expand Down
1 change: 0 additions & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
coverage
flake8
mock
pre-commit
pytest
webtest
2 changes: 0 additions & 2 deletions testing/rpaf.conf

This file was deleted.

30 changes: 24 additions & 6 deletions tests/wsgi_mod_rpaf_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import absolute_import
from __future__ import unicode_literals

import io
import ipaddress

import pytest
Expand All @@ -10,19 +9,34 @@
import wsgi_mod_rpaf


def test_parse_file():
f = io.StringIO(
def test_from_apache_config(tmpdir):
conf = tmpdir.join('conf')
conf.write(
'\n'
'# I am a comment\n'
'# This is an ip without a mask\n'
'RPAFproxy_ips 1.2.3.4\n'
'# This is an ip with a mask\n'
'RPAFproxy_ips 10.0.0.0/8\n'
)
ret = wsgi_mod_rpaf._parse_file(f)
assert ret == (
ret = wsgi_mod_rpaf.from_apache_config(conf.strpath)
assert ret == {
ipaddress.ip_network('1.2.3.4'), ipaddress.ip_network('10.0.0.0/8'),
}


def test_from_apache_config_custom_directive(tmpdir):
conf = tmpdir.join('conf')
conf.write(
'RPAF_ProxyIPs 1.2.3.4\n'
'RPAF_ProxyIPs 10.0.0.0/8\n'
)
ret = wsgi_mod_rpaf.from_apache_config(
conf.strpath, directive='RPAF_ProxyIPs',
)
assert ret == {
ipaddress.ip_network('1.2.3.4'), ipaddress.ip_network('10.0.0.0/8'),
}


def remote_addr_app(environ, start_response):
Expand All @@ -33,7 +47,11 @@ def remote_addr_app(environ, start_response):
@pytest.yield_fixture
def wrapped_app():
yield webtest.TestApp(wsgi_mod_rpaf.wsgi_mod_rpaf_middleware(
remote_addr_app, 'testing/rpaf.conf',
remote_addr_app,
trusted_networks={
ipaddress.ip_network('127.0.0.1'),
ipaddress.ip_network('10.0.0.0/8'),
},
))


Expand Down
6 changes: 4 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
[tox]
project = wsgi_mod_rpaf
# These should match the travis env list
envlist = py27,py35,pypy
envlist = py27,py36,pypy
tox_pip_extensions_ext_venv_update = true
tox_pip_extensions_ext_pip_custom_platform = true

[testenv]
deps = -rrequirements-dev.txt
Expand All @@ -13,7 +15,7 @@ commands =
pre-commit run --all-files

[testenv:venv]
envdir = venv-{[tox]project}
envdir = venv
commands =

[pep8]
Expand Down
38 changes: 23 additions & 15 deletions wsgi_mod_rpaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,32 @@ def text_to_wsgi(s):
return s


PROXY_IPS_DIRECTIVE = 'RPAFproxy_ips '
def from_apache_config(path, directive='RPAFproxy_ips'):
"""Parse trusted networks out of a mod_rpaf-compatible config.
Different versions of mod_rpaf have different directive names. For example,
newer versions use the directive "RPAF_ProxyIPs".
"""
directive += ' '
networks = set()

def _parse_file(f):
networks = []
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
assert line.startswith(PROXY_IPS_DIRECTIVE), line
line = line[len(PROXY_IPS_DIRECTIVE):]
networks.append(ipaddress.ip_network(line))
with io.open(path) as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
assert line.startswith(directive), line
line = line[len(directive):]
networks.add(ipaddress.ip_network(line))

return tuple(networks)
return frozenset(networks)


UNPARSEABLE_IP = type(str('UNPARSEABLE_IP'), (object,), {'__slots__': ()})()


def _safe_parse_ip(s):
"""Returns None if it is not a valid IP"""
"""Returns UNPARSEABLE_IP if it is not a valid IP"""
try:
return ipaddress.ip_address(s)
except ValueError:
Expand Down Expand Up @@ -78,9 +83,12 @@ def _rewrite_environ(environ, networks):
return environ


def wsgi_mod_rpaf_middleware(app, conf):
with io.open(conf) as conf_file:
networks = _parse_file(conf_file)
def wsgi_mod_rpaf_middleware(app, **kwargs):
networks = kwargs.pop('trusted_networks')
assert not kwargs, 'Extra arguments provided: {}'.format(kwargs)

for network in networks:
assert isinstance(network, ipaddress.IPv4Network), network

def wsgi_mod_rpaf_app(environ, start_response):
if (
Expand Down

0 comments on commit c5511f0

Please sign in to comment.