Allow underscores in account/user in tempauth via encoding.
This patch introduces a new user format to tempauth which starts with "user64_" and in which the account and user are base64 encoded (sans padding equal signs): user64_<account_b64>_<user_b64> = <key> [group] [group] [...] [storage_url] This allows unambiguous parsing and adds the ability to have a user or account name containing underscores. The handling of tempauth configuration is fully backward compatible and this only adds new, optional functionality. Also beefed up unit tests to get full coverage of the user parsing code in tempauth's __init__(). Change-Id: Id06304934ab8055a28921f2e1aa3c58a2036d8f8
This commit is contained in:
parent
f0bd91dd14
commit
5582f166c2
@ -644,6 +644,12 @@ is::
|
||||
|
||||
user_<account>_<user> = <key> [group] [group] [...] [storage_url]
|
||||
|
||||
or if you want to be able to include underscores in the ``<account>`` or
|
||||
``<user>`` portions, you can base64 encode them (with *no* equal signs) in a
|
||||
line like this::
|
||||
|
||||
user64_<account_b64>_<user_b64> = <key> [group] [group] [...] [storage_url]
|
||||
|
||||
There are special groups of::
|
||||
|
||||
.reseller_admin = can do anything to any account for this auth
|
||||
@ -669,6 +675,9 @@ Here are example entries, required for running the tests::
|
||||
user_test2_tester2 = testing2 .admin
|
||||
user_test_tester3 = testing3
|
||||
|
||||
# account "test_y" and user "tester_y" (note the lack of padding = chars)
|
||||
user64_dGVzdF95_dGVzdGVyX3k = testing4 .admin
|
||||
|
||||
------------------------
|
||||
Memcached Considerations
|
||||
------------------------
|
||||
|
@ -106,6 +106,9 @@ use = egg:swift#tempauth
|
||||
# allow_overrides = true
|
||||
# Lastly, you need to list all the accounts/users you want here. The format is:
|
||||
# user_<account>_<user> = <key> [group] [group] [...] [storage_url]
|
||||
# or if you want underscores in <account> or <user>, you can base64 encode them
|
||||
# (with no equal signs) and use this format:
|
||||
# user64_<account_b64>_<user_b64> = <key> [group] [group] [...] [storage_url]
|
||||
# There are special groups of:
|
||||
# .reseller_admin = can do anything to any account for this auth
|
||||
# .admin = can do anything within the account
|
||||
|
@ -54,6 +54,11 @@ class TempAuth(object):
|
||||
user_test_tester = testing .admin
|
||||
user_test2_tester2 = testing2 .admin
|
||||
user_test_tester3 = testing3
|
||||
# To allow accounts/users with underscores you can base64 encode them.
|
||||
# Here is the account "under_score" and username "a_b" (note the lack
|
||||
# of padding equal signs):
|
||||
user64_dW5kZXJfc2NvcmU_YV9i = testing4
|
||||
|
||||
|
||||
See the proxy-server.conf-sample for more information.
|
||||
|
||||
@ -86,7 +91,15 @@ class TempAuth(object):
|
||||
conf.get('allow_overrides', 't').lower() in TRUE_VALUES
|
||||
self.users = {}
|
||||
for conf_key in conf:
|
||||
if conf_key.startswith('user_'):
|
||||
if conf_key.startswith('user_') or conf_key.startswith('user64_'):
|
||||
account, username = conf_key.split('_', 1)[1].split('_')
|
||||
if conf_key.startswith('user64_'):
|
||||
# Because trailing equal signs would screw up config file
|
||||
# parsing, we auto-pad with '=' chars.
|
||||
account += '=' * (len(account) % 4)
|
||||
account = base64.b64decode(account)
|
||||
username += '=' * (len(username) % 4)
|
||||
username = base64.b64decode(username)
|
||||
values = conf[conf_key].split()
|
||||
if not values:
|
||||
raise ValueError('%s has no key set' % conf_key)
|
||||
@ -100,8 +113,8 @@ class TempAuth(object):
|
||||
ip = '127.0.0.1'
|
||||
url += ip
|
||||
url += ':' + conf.get('bind_port', '8080') + '/v1/' + \
|
||||
self.reseller_prefix + conf_key.split('_')[1]
|
||||
self.users[conf_key.split('_', 1)[1].replace('_', ':')] = {
|
||||
self.reseller_prefix + account
|
||||
self.users[account + ':' + username] = {
|
||||
'key': key, 'url': url, 'groups': values}
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
|
@ -20,6 +20,7 @@ except ImportError:
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from time import time
|
||||
from base64 import b64encode
|
||||
|
||||
from webob import Request, Response
|
||||
|
||||
@ -578,20 +579,74 @@ class TestAuth(unittest.TestCase):
|
||||
class TestParseUserCreation(unittest.TestCase):
|
||||
def test_parse_user_creation(self):
|
||||
auth_filter = auth.filter_factory({
|
||||
'reseller_prefix': 'ABC',
|
||||
'bind_ip': '1.2.3.4',
|
||||
'user_test_tester3': 'testing',
|
||||
'user_has_url': 'urlly .admin http://a.b/v1/DEF_has',
|
||||
'user_admin_admin': 'admin .admin .reseller_admin',
|
||||
})(FakeApp())
|
||||
self.assertEquals(auth_filter.users, {
|
||||
'admin:admin': {
|
||||
'url': 'http://127.0.0.1:8080/v1/AUTH_admin',
|
||||
'groups': ['.admin', '.reseller_admin'],
|
||||
'url': 'http://1.2.3.4:8080/v1/ABC_admin',
|
||||
'groups': ['.admin', '.reseller_admin'],
|
||||
'key': 'admin'
|
||||
}, 'test:tester3': {
|
||||
'url': 'http://127.0.0.1:8080/v1/AUTH_test',
|
||||
'groups': [],
|
||||
'url': 'http://1.2.3.4:8080/v1/ABC_test',
|
||||
'groups': [],
|
||||
'key': 'testing'
|
||||
}, 'has:url': {
|
||||
'url': 'http://a.b/v1/DEF_has',
|
||||
'groups': ['.admin'],
|
||||
'key': 'urlly'
|
||||
},
|
||||
})
|
||||
|
||||
def test_base64_encoding(self):
|
||||
auth_filter = auth.filter_factory({
|
||||
'reseller_prefix': 'ABC',
|
||||
'bind_ip': '1.2.3.4',
|
||||
'user64_%s_%s' % (
|
||||
b64encode('test').rstrip('='),
|
||||
b64encode('tester3').rstrip('=')):
|
||||
'testing .reseller_admin',
|
||||
'user64_%s_%s' % (
|
||||
b64encode('user_foo').rstrip('='),
|
||||
b64encode('ab').rstrip('=')):
|
||||
'urlly .admin http://a.b/v1/DEF_has',
|
||||
})(FakeApp())
|
||||
self.assertEquals(auth_filter.users, {
|
||||
'test:tester3': {
|
||||
'url': 'http://1.2.3.4:8080/v1/ABC_test',
|
||||
'groups': ['.reseller_admin'],
|
||||
'key': 'testing'
|
||||
}, 'user_foo:ab': {
|
||||
'url': 'http://a.b/v1/DEF_has',
|
||||
'groups': ['.admin'],
|
||||
'key': 'urlly'
|
||||
},
|
||||
})
|
||||
|
||||
def test_bind_ip_all_zeroes(self):
|
||||
auth_filter = auth.filter_factory({
|
||||
'reseller_prefix': 'ABC',
|
||||
'bind_ip': '0.0.0.0',
|
||||
'user_admin_admin': 'admin .admin .reseller_admin',
|
||||
})(FakeApp())
|
||||
self.assertEquals(auth_filter.users, {
|
||||
'admin:admin': {
|
||||
'url': 'http://127.0.0.1:8080/v1/ABC_admin',
|
||||
'groups': ['.admin', '.reseller_admin'],
|
||||
'key': 'admin',
|
||||
},
|
||||
})
|
||||
|
||||
def test_key_with_no_value(self):
|
||||
self.assertRaises(ValueError, auth.filter_factory({
|
||||
'user_test_tester3': 'testing',
|
||||
'user_bob_bobby': '',
|
||||
'user_admin_admin': 'admin .admin .reseller_admin',
|
||||
}), FakeApp())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user