Skip to content

Commit

Permalink
Add support for user based default access
Browse files Browse the repository at this point in the history
  • Loading branch information
krakan committed Mar 2, 2023
1 parent 16cc352 commit 738fa84
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 2 deletions.
20 changes: 20 additions & 0 deletions docs/manual/access-control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,26 @@ For example, this header may be set based on IP range, or based on password auth

Further examples of how to set this header will be provided in the deployments section.

One may also specify default access for different users by adding sub keys to the ``default_access`` setting::

collections:
test:
...
default_access:
default: block
admin: allow

Note that the ``default`` entry will be applied both if the user name is empty and if it actually is ``default``.
If the ``default`` entry is missing, it will be assumed to be ``allow``::

collections:
test:
...
default_access:
guest: block

This works whether the ``default_access`` is specified at the top level or for a specific collection.

**Note: Do not use the user-based rules without configuring proper authentication on an Apache or Nginx frontend to set or remove this header, otherwise the 'X-Pywb-ACL-User' can easily be faked.**

See the :ref:`config-acl-header` section in Usage for examples on how to configure this header.
Expand Down
19 changes: 18 additions & 1 deletion pywb/warcserver/access_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ def __init__(self, access_source, default_access='allow', embargo=None):
self.default_rule['access'] = default_access
self.default_rule['default'] = 'true'

if isinstance(self.default_rule['access'], dict):
if 'default' not in self.default_rule['access']:
self.default_rule['access']['default'] = 'allow'

self.embargo = self.parse_embargo(embargo)

def parse_embargo(self, embargo):
Expand Down Expand Up @@ -273,7 +277,17 @@ def find_access_rule(self, url, ts=None, urlkey=None, collection=None, acl_user=
if acl_key < tld:
break

return last_obj if last_obj else self.default_rule

if last_obj:
return last_obj

if isinstance(self.default_rule['access'], dict):
default_rule = dict(self.default_rule)
user = acl_user if acl_user in default_rule['access'] else 'default'
default_rule['access'] = default_rule['access'][user]
return default_rule

return self.default_rule

def __call__(self, res, acl_user):
"""Wraps the cdx iter in the supplied tuple returning a
Expand Down Expand Up @@ -334,6 +348,9 @@ def wrap_iter(self, cdx_iter, acl_user):
if not access:
access = self.default_rule['access']

if isinstance(access, dict):
access = self.default_rule['access']['default']

if access == 'allow_ignore_embargo':
access = 'allow'

Expand Down
2 changes: 2 additions & 0 deletions sample_archive/access/user-default.aclj
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
com,example)/ - {"access": "block", "user": "staff"}
com,example)/ - {"access": "allow", "user": "staff2"}
9 changes: 8 additions & 1 deletion tests/config_test_access.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ collections:
archive_paths: ./sample_archive/warcs/
acl_paths: ./sample_archive/access/pywb.aclj

default_access: block
default_access:
default: block

pywb-acl-list:
index_paths: ./sample_archive/cdx/
Expand Down Expand Up @@ -62,6 +63,12 @@ collections:
acl_paths:
- ./sample_archive/access/pywb.aclj

pywb-acl-user-default:
index_paths: ./sample_archive/cdx/
archive_paths: ./sample_archive/warcs/
acl_paths: ./sample_archive/access/user-default.aclj

default_access:
staff2: block


8 changes: 8 additions & 0 deletions tests/test_acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,13 @@ def test_allowed_different_coll_acl_dir(self):

assert '"http://httpbin.org/anything/resource.json"' in resp.text

def test_user_default(self):
headers = {"X-Pywb-ACL-User": "staff"}
self.testapp.get('/pywb-acl-user-default/mp_/http://www.iana.org/', headers=headers, status=200)
self.testapp.get('/pywb-acl-user-default/mp_/http://www.example.com/', headers=headers, status=451)

headers = {"X-Pywb-ACL-User": "staff2"}
self.testapp.get('/pywb-acl-user-default/mp_/http://www.iana.org/', headers=headers, status=451)
self.testapp.get('/pywb-acl-user-default/mp_/http://www.example.com/', headers=headers, status=200)


0 comments on commit 738fa84

Please sign in to comment.