Permalink
Browse files

Add use_dynamic_reseller_names param to keystoneauth

If your using auth version 3 and want to have an account based of the
name of the project, then you can enable ``use_dynamic_reseller_name``
in conjuction with ``use_dynamic_reseller`` to do so. The form used
for the account would be::

    <reseller_prefix><project_domain_name>_<project_name>

Given a reseller_preix of 'AUTH_' as project_domain_name of 'Domain' and
a project name of 'Demo', this would generate::

    AUTH_Domain_Demo

NOTE: however, that if you ever change the domain or project name then
users accounts will change, loosing access to their old data, and
a large serverside copy would need to happen.
This feature however is really useful for federated environments however.

Change-Id: Ifad4526d09a4d29389594562fd7ca994125cdc37
  • Loading branch information...
matthewoliver committed May 2, 2018
1 parent 2d25fc4 commit f5f83c6a140cc15df0ba9020b636ac1b313ff56c
Showing with 69 additions and 3 deletions.
  1. +32 −3 swift/common/middleware/keystoneauth.py
  2. +37 −0 test/unit/common/middleware/test_keystoneauth.py
@@ -188,6 +188,23 @@ class KeystoneAuth(object):
use_dynamic_reseller = true
If your using auth version 3 and want to have an account based of the
name of the project, then you can enable ``use_dynamic_reseller_name``
in conjuction with ``use_dynamic_reseller`` to do so. The form used
for the account would be::
<reseller_prefix><project_domain_name>_<project_name>
Given a reseller_preix of 'AUTH_' as project_domain_name of 'Domain' and
a project name of 'Demo', this would generate::
AUTH_Domain_Demo
NOTE: however, that if you ever change the domain or project name then
users accounts will change, loosing access to their old data, and
a large serverside copy would need to happen.
This feature however is really useful for federated environments however.
:param app: The next WSGI app in the pipeline
:param conf: The dict of configuration values
"""
@@ -215,6 +232,8 @@ def __init__(self, app, conf):
conf.get('allow_names_in_acls', 'true'))
self.use_dynamic_reseller = swift_utils.config_true_value(
conf.get('use_dynamic_reseller', 'false'))
self.use_dynamic_reseller_names = swift_utils.config_true_value(
conf.get('use_dynamic_reseller_names', 'false'))
def __call__(self, environ, start_response):
env_identity = self._keystone_identity(environ)
@@ -292,16 +311,26 @@ def _keystone_identity(self, environ):
identity['auth_version'] = auth_version
return identity
def _set_dynamic_name(self, environ, env_identity):
def _set_dynamic_name(self, environ, identity):
try:
part = Request(environ).split_path(2, 4, True)
version, account, container, obj = part
except ValueError:
return
if account and account in self.reseller_prefixes:
path = "/%s/%s%s" % (version, account,
env_identity['tenant'][0])
if self.use_dynamic_reseller_names and \
identity['auth_version'] == 3:
account = "%s%s_%s" % (account, identity['project_domain'][1],
identity['tenant'][1])
elif self.use_dynamic_reseller_names:
self.logger.error('use_dynamic_reseller_names only available '
'when using auth v3.')
return
else:
account = "%s%s" % (account, identity['tenant'][0])
path = "/%s/%s" % (version, account)
if container:
path = "%s/%s" % (path, container)
if obj:
@@ -364,6 +364,43 @@ def test(path, expected_path):
for params in tests:
test(**params)
def test_use_dynamic_reseller_name(self):
reseller_prefix = self.test_auth.reseller_prefixes[0]
self.test_auth.use_dynamic_reseller = True
self.test_auth.use_dynamic_reseller_names = True
headers = get_identity_headers()
def test(path, expected_path, env):
self.test_auth.logger = FakeLogger()
req = self._make_request(path=path, headers=headers, environ=env)
resp = req.get_response(self.test_auth)
self.assertEqual(resp.request.path, expected_path)
if path == expected_path:
errors = self.test_auth.logger.get_lines_for_level('error')
self.assertIn(('use_dynamic_reseller_names only available '
'when using auth v3.'), errors)
# first run with auth_version 0 (ie no keystone.token_info)
test(path='/v1/%s/c/o' % reseller_prefix,
expected_path='/v1/%s/c/o' % reseller_prefix,
env=None)
# Next run with auth_version 2
environ = {'keystone.token_info': _fake_token_info(version='2')}
test(path='/v1/%s/c/o' % reseller_prefix,
expected_path='/v1/%s/c/o' % reseller_prefix,
env=environ)
# Next run with auth_version 3 - this should succeed
import pudb; pudb.set_trace()
environ = {'keystone.token_info': _fake_token_info(version='3')}
test(path='/v1/%s/c/o' % reseller_prefix,
expected_path='/v1/%s%s_%s/c/o' % (
reseller_prefix, headers['X_PROJECT_DOMAIN_NAME'],
headers['X_TENANT_NAME']),
env=environ)
class SwiftAuthMultiple(SwiftAuth):
"""Runs same tests as SwiftAuth with multiple reseller prefixes

0 comments on commit f5f83c6

Please sign in to comment.