diff --git a/doc/source/authentication.rst b/doc/source/authentication.rst index 02f2f4431e..d6f5c63992 100644 --- a/doc/source/authentication.rst +++ b/doc/source/authentication.rst @@ -157,6 +157,12 @@ configuration file, select the appropriate deployment flavor by adding a [paste_deploy] flavor = keystone +.. note:: + If your authentication service uses a role other than ``admin`` to identify + which users should be granted admin-level privileges, you must define it + in the ``admin_role`` config attribute in both ``glance-registry.conf`` and + ``glance-api.conf``. + Sharing Images With Others -------------------------- diff --git a/etc/glance-api.conf b/etc/glance-api.conf index f516788893..90803a7423 100644 --- a/etc/glance-api.conf +++ b/etc/glance-api.conf @@ -30,6 +30,9 @@ backlog = 4096 # this value to the number of CPUs present on your machine. workers = 0 +# Role used to identify an authenticated user as administrator +#admin_role = admin + # ================= Syslog Options ============================ # Send logs to syslog (/dev/log) instead of to file specified diff --git a/etc/glance-registry.conf b/etc/glance-registry.conf index ec4c5f0904..8597411d57 100644 --- a/etc/glance-registry.conf +++ b/etc/glance-registry.conf @@ -40,6 +40,9 @@ api_limit_max = 1000 # default to `limit_param_default` limit_param_default = 25 +# Role used to identify an authenticated user as administrator +#admin_role = admin + # ================= Syslog Options ============================ # Send logs to syslog (/dev/log) instead of to file specified diff --git a/glance/common/context.py b/glance/common/context.py index aaaf6a4afa..7382b30ed4 100644 --- a/glance/common/context.py +++ b/glance/common/context.py @@ -56,6 +56,7 @@ class ContextMiddleware(wsgi.Middleware): opts = [ cfg.BoolOpt('owner_is_tenant', default=True), + cfg.StrOpt('admin_role', default='admin'), ] def __init__(self, app, conf, **local_conf): @@ -106,7 +107,7 @@ class ContextMiddleware(wsgi.Middleware): tenant = req.headers.get('X-Tenant') roles = [r.strip() for r in req.headers.get('X-Role', '').split(',')] - is_admin = 'Admin' in roles + is_admin = self.conf.admin_role in roles else: # 2. Indentity-Status not confirmed # FIXME(sirp): not sure what the correct behavior in this case diff --git a/glance/tests/unit/test_api.py b/glance/tests/unit/test_api.py index 99c4f1f65a..cab717f90e 100644 --- a/glance/tests/unit/test_api.py +++ b/glance/tests/unit/test_api.py @@ -3055,3 +3055,44 @@ class TestImageSerializer(base.IsolatedUnitTest): self.serializer.image_send_notification(17, 19, image_meta, req) self.assertTrue(called['notified']) + + +class TestContextMiddleware(base.IsolatedUnitTest): + def _build_request(self, roles=None): + req = webob.Request.blank('/') + req.headers['x-auth-token'] = 'token1' + req.headers['x-identity-status'] = 'Confirmed' + req.headers['x-user'] = 'user1' + req.headers['x-tenant'] = 'tenant1' + _roles = roles or ['role1', 'role2'] + req.headers['x-role'] = ','.join(_roles) + return req + + def _build_middleware(self, **extra_config): + for k, v in extra_config.items(): + setattr(self.conf, k, v) + return context.ContextMiddleware(None, self.conf) + + def test_header_parsing(self): + req = self._build_request() + self._build_middleware().process_request(req) + self.assertEqual(req.context.auth_tok, 'token1') + self.assertEqual(req.context.user, 'user1') + self.assertEqual(req.context.tenant, 'tenant1') + self.assertEqual(req.context.roles, ['role1', 'role2']) + + def test_is_admin_flag(self): + # is_admin check should look for 'admin' role by default + req = self._build_request(roles=['admin', 'role2']) + self._build_middleware().process_request(req) + self.assertTrue(req.context.is_admin) + + # without the 'admin' role, is_admin shoud be False + req = self._build_request() + self._build_middleware().process_request(req) + self.assertFalse(req.context.is_admin) + + # if we change the admin_role attribute, we should be able to use it + req = self._build_request() + self._build_middleware(admin_role='role1').process_request(req) + self.assertTrue(req.context.is_admin)