tempauth: Add .reseller_reader group
Change-Id: I8c5197ed327fbb175c8a2c0e788b1ae14e6dfe23
This commit is contained in:
@@ -388,8 +388,9 @@ use = egg:swift#tempauth
|
|||||||
# user64_<account_b64>_<user_b64> = <key> [group] [group] [...] [storage_url]
|
# user64_<account_b64>_<user_b64> = <key> [group] [group] [...] [storage_url]
|
||||||
# There are special groups of:
|
# There are special groups of:
|
||||||
# .reseller_admin = can do anything to any account for this auth
|
# .reseller_admin = can do anything to any account for this auth
|
||||||
|
# .reseller_reader = can GET/HEAD anything in any account for this auth
|
||||||
# .admin = can do anything within the account
|
# .admin = can do anything within the account
|
||||||
# If neither of these groups are specified, the user can only access containers
|
# If none of these groups are specified, the user can only access containers
|
||||||
# that have been explicitly allowed for them by a .admin or .reseller_admin.
|
# that have been explicitly allowed for them by a .admin or .reseller_admin.
|
||||||
# The trailing optional storage_url allows you to specify an alternate url to
|
# The trailing optional storage_url allows you to specify an alternate url to
|
||||||
# hand back to the user upon authentication. If not specified, this defaults to
|
# hand back to the user upon authentication. If not specified, this defaults to
|
||||||
@@ -397,6 +398,7 @@ use = egg:swift#tempauth
|
|||||||
# to what the requester would need to use to reach this host.
|
# to what the requester would need to use to reach this host.
|
||||||
# Here are example entries, required for running the tests:
|
# Here are example entries, required for running the tests:
|
||||||
user_admin_admin = admin .admin .reseller_admin
|
user_admin_admin = admin .admin .reseller_admin
|
||||||
|
user_admin_auditor = admin_ro .reseller_reader
|
||||||
user_test_tester = testing .admin
|
user_test_tester = testing .admin
|
||||||
user_test_tester2 = testing2 .admin
|
user_test_tester2 = testing2 .admin
|
||||||
user_test_tester3 = testing3
|
user_test_tester3 = testing3
|
||||||
|
@@ -54,12 +54,13 @@ in a line like this::
|
|||||||
|
|
||||||
user64_<account_b64>_<user_b64> = <key> [group] [...] [storage_url]
|
user64_<account_b64>_<user_b64> = <key> [group] [...] [storage_url]
|
||||||
|
|
||||||
There are two special groups:
|
There are three special groups:
|
||||||
|
|
||||||
* ``.reseller_admin`` -- can do anything to any account for this auth
|
* ``.reseller_admin`` -- can do anything to any account for this auth
|
||||||
|
* ``.reseller_reader`` -- can GET/HEAD anything in any account for this auth
|
||||||
* ``.admin`` -- can do anything within the account
|
* ``.admin`` -- can do anything within the account
|
||||||
|
|
||||||
If neither of these groups are specified, the user can only access
|
If none of these groups are specified, the user can only access
|
||||||
containers that have been explicitly allowed for them by a ``.admin`` or
|
containers that have been explicitly allowed for them by a ``.admin`` or
|
||||||
``.reseller_admin``.
|
``.reseller_admin``.
|
||||||
|
|
||||||
@@ -124,8 +125,8 @@ and ``X-Service-Token`` is from the ``glance`` user::
|
|||||||
user_maryacct_mary = marypw .admin
|
user_maryacct_mary = marypw .admin
|
||||||
user_glance_glance = glancepw .service
|
user_glance_glance = glancepw .service
|
||||||
|
|
||||||
The name ``.service`` is an example. Unlike ``.admin`` and
|
The name ``.service`` is an example. Unlike ``.admin``, ``.reseller_admin``,
|
||||||
``.reseller_admin`` it is not a reserved name.
|
``.reseller_reader`` it is not a reserved name.
|
||||||
|
|
||||||
Please note that ACLs can be set on service accounts and are matched
|
Please note that ACLs can be set on service accounts and are matched
|
||||||
against the identity validated by ``X-Auth-Token``. As such ACLs can grant
|
against the identity validated by ``X-Auth-Token``. As such ACLs can grant
|
||||||
@@ -569,6 +570,14 @@ class TempAuth(object):
|
|||||||
% account_user)
|
% account_user)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if '.reseller_reader' in user_groups and \
|
||||||
|
account not in self.reseller_prefixes and \
|
||||||
|
not self._dot_account(account) and \
|
||||||
|
req.method in ('GET', 'HEAD'):
|
||||||
|
self.logger.debug("User %s has reseller reader authorizing."
|
||||||
|
% account_user)
|
||||||
|
return None
|
||||||
|
|
||||||
if wsgi_to_str(account) in user_groups and \
|
if wsgi_to_str(account) in user_groups and \
|
||||||
(req.method not in ('DELETE', 'PUT') or container):
|
(req.method not in ('DELETE', 'PUT') or container):
|
||||||
# The user is admin for the account and is not trying to do an
|
# The user is admin for the account and is not trying to do an
|
||||||
|
@@ -537,7 +537,7 @@ class TestAuth(unittest.TestCase):
|
|||||||
|
|
||||||
def test_account_put_permissions(self):
|
def test_account_put_permissions(self):
|
||||||
self.test_auth = auth.filter_factory({})(
|
self.test_auth = auth.filter_factory({})(
|
||||||
FakeApp(iter(NO_CONTENT_RESP * 4)))
|
FakeApp(iter(NO_CONTENT_RESP * 5)))
|
||||||
req = self._make_request('/v1/AUTH_new',
|
req = self._make_request('/v1/AUTH_new',
|
||||||
environ={'REQUEST_METHOD': 'PUT'})
|
environ={'REQUEST_METHOD': 'PUT'})
|
||||||
req.remote_user = 'act:usr,act'
|
req.remote_user = 'act:usr,act'
|
||||||
@@ -563,6 +563,12 @@ class TestAuth(unittest.TestCase):
|
|||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
self.assertIsNone(resp)
|
self.assertIsNone(resp)
|
||||||
|
|
||||||
|
req = self._make_request('/v1/AUTH_new',
|
||||||
|
environ={'REQUEST_METHOD': 'PUT'})
|
||||||
|
req.remote_user = 'act:usr,act,.reseller_reader'
|
||||||
|
resp = self.test_auth.authorize(req)
|
||||||
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
|
||||||
# .super_admin is not something the middleware should ever see or care
|
# .super_admin is not something the middleware should ever see or care
|
||||||
# about
|
# about
|
||||||
req = self._make_request('/v1/AUTH_new',
|
req = self._make_request('/v1/AUTH_new',
|
||||||
@@ -573,7 +579,7 @@ class TestAuth(unittest.TestCase):
|
|||||||
|
|
||||||
def test_account_delete_permissions(self):
|
def test_account_delete_permissions(self):
|
||||||
self.test_auth = auth.filter_factory({})(
|
self.test_auth = auth.filter_factory({})(
|
||||||
FakeApp(iter(NO_CONTENT_RESP * 4)))
|
FakeApp(iter(NO_CONTENT_RESP * 5)))
|
||||||
req = self._make_request('/v1/AUTH_new',
|
req = self._make_request('/v1/AUTH_new',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'})
|
environ={'REQUEST_METHOD': 'DELETE'})
|
||||||
req.remote_user = 'act:usr,act'
|
req.remote_user = 'act:usr,act'
|
||||||
@@ -599,6 +605,12 @@ class TestAuth(unittest.TestCase):
|
|||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
self.assertIsNone(resp)
|
self.assertIsNone(resp)
|
||||||
|
|
||||||
|
req = self._make_request('/v1/AUTH_new',
|
||||||
|
environ={'REQUEST_METHOD': 'DELETE'})
|
||||||
|
req.remote_user = 'act:usr,act,.reseller_reader'
|
||||||
|
resp = self.test_auth.authorize(req)
|
||||||
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
|
||||||
# .super_admin is not something the middleware should ever see or care
|
# .super_admin is not something the middleware should ever see or care
|
||||||
# about
|
# about
|
||||||
req = self._make_request('/v1/AUTH_new',
|
req = self._make_request('/v1/AUTH_new',
|
||||||
@@ -824,9 +836,18 @@ class TestAuth(unittest.TestCase):
|
|||||||
req = self._make_request('/v1/AUTH_cfa',
|
req = self._make_request('/v1/AUTH_cfa',
|
||||||
headers={'X-Auth-Token': 'AUTH_t'})
|
headers={'X-Auth-Token': 'AUTH_t'})
|
||||||
req.remote_user = '.reseller_admin'
|
req.remote_user = '.reseller_admin'
|
||||||
self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
|
self.assertIsNone(resp)
|
||||||
self.assertEqual(owner_values, [True])
|
self.assertEqual(owner_values, [True])
|
||||||
|
|
||||||
|
owner_values = []
|
||||||
|
req = self._make_request('/v1/AUTH_cfa',
|
||||||
|
headers={'X-Auth-Token': 'AUTH_t'})
|
||||||
|
req.remote_user = '.reseller_reader'
|
||||||
|
resp = self.test_auth.authorize(req)
|
||||||
|
self.assertIsNone(resp)
|
||||||
|
self.assertEqual(owner_values, [False])
|
||||||
|
|
||||||
def test_admin_is_owner(self):
|
def test_admin_is_owner(self):
|
||||||
orig_authorize = self.test_auth.authorize
|
orig_authorize = self.test_auth.authorize
|
||||||
owner_values = []
|
owner_values = []
|
||||||
@@ -1172,12 +1193,17 @@ class TestParseUserCreation(unittest.TestCase):
|
|||||||
'user_test_tester3': 'testing',
|
'user_test_tester3': 'testing',
|
||||||
'user_has_url': 'urlly .admin http://a.b/v1/DEF_has',
|
'user_has_url': 'urlly .admin http://a.b/v1/DEF_has',
|
||||||
'user_admin_admin': 'admin .admin .reseller_admin',
|
'user_admin_admin': 'admin .admin .reseller_admin',
|
||||||
|
'user_admin_auditor': 'admin_ro .reseller_reader',
|
||||||
})(FakeApp())
|
})(FakeApp())
|
||||||
self.assertEqual(auth_filter.users, {
|
self.assertEqual(auth_filter.users, {
|
||||||
'admin:admin': {
|
'admin:admin': {
|
||||||
'url': '$HOST/v1/ABC_admin',
|
'url': '$HOST/v1/ABC_admin',
|
||||||
'groups': ['.admin', '.reseller_admin'],
|
'groups': ['.admin', '.reseller_admin'],
|
||||||
'key': 'admin'
|
'key': 'admin'
|
||||||
|
}, 'admin:auditor': {
|
||||||
|
'url': '$HOST/v1/ABC_admin',
|
||||||
|
'groups': ['.reseller_reader'],
|
||||||
|
'key': 'admin_ro'
|
||||||
}, 'test:tester3': {
|
}, 'test:tester3': {
|
||||||
'url': '$HOST/v1/ABC_test',
|
'url': '$HOST/v1/ABC_test',
|
||||||
'groups': [],
|
'groups': [],
|
||||||
@@ -1612,6 +1638,16 @@ class ServiceTokenFunctionality(unittest.TestCase):
|
|||||||
{'reseller_prefix': 'AUTH'}, 'acct:joe,acct,AUTH_acct',
|
{'reseller_prefix': 'AUTH'}, 'acct:joe,acct,AUTH_acct',
|
||||||
'/v1/AUTH_acct/c', method='PUT')
|
'/v1/AUTH_acct/c', method='PUT')
|
||||||
self.assertEqual(resp.status_int, 200)
|
self.assertEqual(resp.status_int, 200)
|
||||||
|
resp = self._make_authed_request(
|
||||||
|
{'reseller_prefix': 'AUTH'},
|
||||||
|
'admin:mary,admin,AUTH_admin,.reseller_reader',
|
||||||
|
'/v1/AUTH_acct', method='GET')
|
||||||
|
self.assertEqual(resp.status_int, 200)
|
||||||
|
resp = self._make_authed_request(
|
||||||
|
{'reseller_prefix': 'AUTH'},
|
||||||
|
'admin:mary,admin,AUTH_admin,.reseller_reader',
|
||||||
|
'/v1/AUTH_acct/c', method='GET')
|
||||||
|
self.assertEqual(resp.status_int, 200)
|
||||||
resp = self._make_authed_request(
|
resp = self._make_authed_request(
|
||||||
{'reseller_prefix': 'AUTH'},
|
{'reseller_prefix': 'AUTH'},
|
||||||
'admin:mary,admin,AUTH_admin,.reseller_admin',
|
'admin:mary,admin,AUTH_admin,.reseller_admin',
|
||||||
@@ -1641,6 +1677,26 @@ class ServiceTokenFunctionality(unittest.TestCase):
|
|||||||
'/v1/AUTH_acct',
|
'/v1/AUTH_acct',
|
||||||
method='DELETE')
|
method='DELETE')
|
||||||
self.assertEqual(resp.status_int, 403)
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
resp = self._make_authed_request(
|
||||||
|
{'reseller_prefix': 'AUTH'},
|
||||||
|
'admin:mary,admin,.admin,.reseller_reader',
|
||||||
|
'/v1/AUTH_acct', method='PUT')
|
||||||
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
resp = self._make_authed_request(
|
||||||
|
{'reseller_prefix': 'AUTH'},
|
||||||
|
'admin:mary,admin,.admin,.reseller_reader',
|
||||||
|
'/v1/AUTH_acct', method='DELETE')
|
||||||
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
resp = self._make_authed_request(
|
||||||
|
{'reseller_prefix': 'AUTH'},
|
||||||
|
'admin:mary,admin,.admin,.reseller_reader',
|
||||||
|
'/v1/AUTH_acct/c', method='PUT')
|
||||||
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
resp = self._make_authed_request(
|
||||||
|
{'reseller_prefix': 'AUTH'},
|
||||||
|
'admin:mary,admin,.admin,.reseller_reader',
|
||||||
|
'/v1/AUTH_acct/c', method='DELETE')
|
||||||
|
self.assertEqual(resp.status_int, 403)
|
||||||
|
|
||||||
def test_authed_for_primary_path_multiple(self):
|
def test_authed_for_primary_path_multiple(self):
|
||||||
resp = self._make_authed_request(
|
resp = self._make_authed_request(
|
||||||
|
Reference in New Issue
Block a user