Split noauth context middleware into new class
Use UnauthenticatedContextMiddleware in the case that you want to deploy without an auth service. ContextMiddleware is now solely for authenticated requests. * Rewrite ownership tests for adding/updating images through the v1 API * Fixes bug 992859 Change-Id: I608671aac8300c9195769542708708afda991e04
This commit is contained in:
parent
64ab035f96
commit
eb4aaa97bd
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@
|
||||
AUTHORS
|
||||
build
|
||||
dist
|
||||
*.egg
|
||||
glance.egg-info
|
||||
glance/vcsversion.py
|
||||
tests.sqlite
|
||||
|
@ -40,12 +40,13 @@ Configuring the Glance servers to use Keystone
|
||||
|
||||
Keystone is integrated with Glance through the use of middleware. The
|
||||
default configuration files for both the Glance API and the Glance
|
||||
Registry use a single piece of middleware called ``context``, which
|
||||
generates a request context containing all the necesary authorization
|
||||
Registry use a single piece of middleware called ``unauthenticated-context``,
|
||||
which generates a request context containing blank authentication
|
||||
information. In order to configure Glance to use Keystone, the
|
||||
``authtoken`` middleware must also be deployed (which may be found in the
|
||||
Keystone distribution). The ``authtoken`` middleware performs the Keystone
|
||||
token validation, which is the heart of Keystone authentication.
|
||||
``authtoken`` and ``context`` middlewares must be deployed in place of the
|
||||
``unauthenticated-context`` middleware. The ``authtoken`` middleware performs
|
||||
the authentication token validation and retrieves actual user authentication
|
||||
information. It can be found in the Keystone distribution.
|
||||
|
||||
Configuring Glance API to use Keystone
|
||||
--------------------------------------
|
||||
@ -80,11 +81,11 @@ Finally, to actually enable using Keystone authentication, the
|
||||
application pipeline must be modified. By default, it looks like::
|
||||
|
||||
[pipeline:glance-api]
|
||||
pipeline = versionnegotiation context apiv1app
|
||||
pipeline = versionnegotiation unauthenticated-context apiv1app
|
||||
|
||||
(Your particular pipeline may vary depending on other options, such as
|
||||
the image cache.) This must be changed by inserting ``authtoken``
|
||||
before ``context``::
|
||||
Your particular pipeline may vary depending on other options, such as
|
||||
the image cache. This must be changed by replacing ``unauthenticated-context``
|
||||
with ``authtoken`` and ``context``::
|
||||
|
||||
[pipeline:glance-api]
|
||||
pipeline = versionnegotiation authtoken context apiv1app
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Default minimal pipeline
|
||||
[pipeline:glance-api]
|
||||
pipeline = versionnegotiation context rootapp
|
||||
pipeline = versionnegotiation unauthenticated-context rootapp
|
||||
|
||||
# Use the following pipeline for keystone auth
|
||||
# i.e. in glance-api.conf:
|
||||
@ -62,6 +62,10 @@ glance.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:ContextMiddleware
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:UnauthenticatedContextMiddleware
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystone.middleware.auth_token:filter_factory
|
||||
auth_host = 127.0.0.1
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Default minimal pipeline
|
||||
[pipeline:glance-registry]
|
||||
pipeline = context registryapp
|
||||
pipeline = unauthenticated-context registryapp
|
||||
|
||||
# Use the following pipeline for keystone auth
|
||||
# i.e. in glance-registry.conf:
|
||||
@ -18,6 +18,10 @@ glance.app_factory = glance.registry.api.v1:API
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:ContextMiddleware
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:UnauthenticatedContextMiddleware
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystone.middleware.auth_token:filter_factory
|
||||
auth_host = 127.0.0.1
|
||||
|
@ -15,6 +15,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import webob.exc
|
||||
|
||||
from glance.common import exception
|
||||
from glance.common import wsgi
|
||||
from glance.openstack.common import cfg
|
||||
@ -137,53 +139,53 @@ class ContextMiddleware(wsgi.Middleware):
|
||||
self.conf.register_opts(self.opts)
|
||||
super(ContextMiddleware, self).__init__(app)
|
||||
|
||||
def make_context(self, *args, **kwargs):
|
||||
"""
|
||||
Create a context with the given arguments.
|
||||
"""
|
||||
kwargs.setdefault('owner_is_tenant', self.conf.owner_is_tenant)
|
||||
def process_request(self, req):
|
||||
"""Convert authentication informtion into a request context
|
||||
|
||||
return RequestContext(*args, **kwargs)
|
||||
Generate a RequestContext object from the available
|
||||
authentication headers and store on the 'context' attribute
|
||||
of the req object.
|
||||
|
||||
:param req: wsgi request object that will be given the context object
|
||||
:raises webob.exc.HTTPUnauthorized: when value of the X-Identity-Status
|
||||
header is not 'Confirmed'
|
||||
"""
|
||||
if req.headers.get('X-Identity-Status') != 'Confirmed':
|
||||
raise webob.exc.HTTPUnauthorized()
|
||||
|
||||
#NOTE(bcwaldon): X-Roles is a csv string, but we need to parse
|
||||
# it into a list to be useful
|
||||
roles_header = req.headers.get('X-Roles', '')
|
||||
roles = [r.strip() for r in roles_header.split(',')]
|
||||
|
||||
#NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token
|
||||
deprecated_token = req.headers.get('X-Storage-Token')
|
||||
|
||||
kwargs = {
|
||||
'user': req.headers.get('X-User-Id'),
|
||||
'tenant': req.headers.get('X-Tenant-Id'),
|
||||
'roles': roles,
|
||||
'is_admin': self.conf.admin_role in roles,
|
||||
'auth_tok': req.headers.get('X-Auth-Token', deprecated_token),
|
||||
'owner_is_tenant': self.conf.owner_is_tenant,
|
||||
}
|
||||
|
||||
req.context = RequestContext(**kwargs)
|
||||
|
||||
|
||||
class UnauthenticatedContextMiddleware(wsgi.Middleware):
|
||||
|
||||
def __init__(self, app, conf, **local_conf):
|
||||
self.conf = conf
|
||||
super(UnauthenticatedContextMiddleware, self).__init__(app)
|
||||
|
||||
def process_request(self, req):
|
||||
"""
|
||||
Extract any authentication information in the request and
|
||||
construct an appropriate context from it.
|
||||
"""Create a context without an authorized user."""
|
||||
kwargs = {
|
||||
'user': None,
|
||||
'tenant': None,
|
||||
'roles': [],
|
||||
'is_admin': True,
|
||||
}
|
||||
|
||||
A few scenarios exist:
|
||||
|
||||
1. If X-Auth-Token is passed in, then consult TENANT and ROLE headers
|
||||
to determine permissions.
|
||||
|
||||
2. An X-Auth-Token was passed in, but the Identity-Status is not
|
||||
confirmed. For now, just raising a NotAuthenticated exception.
|
||||
|
||||
3. X-Auth-Token is omitted. If we were using Keystone, then the
|
||||
tokenauth middleware would have rejected the request, so we must be
|
||||
using NoAuth. In that case, assume that is_admin=True.
|
||||
"""
|
||||
auth_tok = req.headers.get('X-Auth-Token',
|
||||
req.headers.get('X-Storage-Token'))
|
||||
if auth_tok:
|
||||
if req.headers.get('X-Identity-Status') == 'Confirmed':
|
||||
# 1. Auth-token is passed, check other headers
|
||||
user = req.headers.get('X-User-Id')
|
||||
tenant = req.headers.get('X-Tenant-Id')
|
||||
roles = [r.strip()
|
||||
for r in req.headers.get('X-Roles', '').split(',')]
|
||||
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
|
||||
# is; just raising NotAuthenticated for now
|
||||
raise exception.NotAuthenticated()
|
||||
else:
|
||||
# 3. Auth-token is ommited, assume NoAuth
|
||||
user = None
|
||||
tenant = None
|
||||
roles = []
|
||||
is_admin = True
|
||||
|
||||
req.context = self.make_context(
|
||||
auth_tok=auth_tok, user=user, tenant=tenant, roles=roles,
|
||||
is_admin=is_admin)
|
||||
req.context = RequestContext(**kwargs)
|
||||
|
@ -252,13 +252,18 @@ policy_default_rule = %(policy_default_rule)s
|
||||
flavor = %(deployment_flavor)s
|
||||
"""
|
||||
self.paste_conf_base = """[pipeline:glance-api]
|
||||
pipeline = versionnegotiation context rootapp
|
||||
pipeline = versionnegotiation unauthenticated-context rootapp
|
||||
|
||||
[pipeline:glance-api-caching]
|
||||
pipeline = versionnegotiation context cache rootapp
|
||||
pipeline = versionnegotiation unauthenticated-context cache rootapp
|
||||
|
||||
[pipeline:glance-api-cachemanagement]
|
||||
pipeline = versionnegotiation context cache cache_manage rootapp
|
||||
pipeline =
|
||||
versionnegotiation
|
||||
unauthenticated-context
|
||||
cache
|
||||
cache_manage
|
||||
rootapp
|
||||
|
||||
[pipeline:glance-api-fakeauth]
|
||||
pipeline = versionnegotiation fakeauth context rootapp
|
||||
@ -297,6 +302,10 @@ glance.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:ContextMiddleware
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:UnauthenticatedContextMiddleware
|
||||
|
||||
[filter:fakeauth]
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.tests.utils:FakeAuthMiddleware
|
||||
@ -337,7 +346,7 @@ owner_is_tenant = %(owner_is_tenant)s
|
||||
flavor = %(deployment_flavor)s
|
||||
"""
|
||||
self.paste_conf_base = """[pipeline:glance-registry]
|
||||
pipeline = context registryapp
|
||||
pipeline = unauthenticated-context registryapp
|
||||
|
||||
[pipeline:glance-registry-fakeauth]
|
||||
pipeline = fakeauth context registryapp
|
||||
@ -350,6 +359,10 @@ glance.app_factory = glance.registry.api.v1:API
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:ContextMiddleware
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.common.context:UnauthenticatedContextMiddleware
|
||||
|
||||
[filter:fakeauth]
|
||||
paste.filter_factory = glance.common.wsgi:filter_factory
|
||||
glance.filter_factory = glance.tests.utils:FakeAuthMiddleware
|
||||
|
@ -31,36 +31,6 @@ from glance.tests.functional.store_utils import (setup_http,
|
||||
get_http_uri)
|
||||
|
||||
|
||||
class TestBinGlanceAuth(functional.FunctionalTest):
|
||||
"""Functional tests for bin/glance with some amount of auth"""
|
||||
|
||||
def assertIn(self, key, bag):
|
||||
msg = 'Expected to find substring "%s" in "%s"' % (key, bag)
|
||||
self.assertTrue(key in bag, msg)
|
||||
|
||||
def assertNotIn(self, key, bag):
|
||||
msg = 'Expected not to find substring "%s" in "%s"' % (key, bag)
|
||||
self.assertFalse(key in bag, msg)
|
||||
|
||||
def test_index_with_https_auth(self):
|
||||
self.cleanup()
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
api_port = self.api_port
|
||||
cmd = ("bin/glance --port=%d -N https://this.url.doesnt.matter/ "
|
||||
"-A aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa index") % api_port
|
||||
exitcode, out, err = execute(cmd, raise_error=False)
|
||||
|
||||
#NOTE(markwash): we should expect the command to fail because the
|
||||
# testing glance api server is not configured to authenticate, and the
|
||||
# token we provide is invalid. However, it should fail due to
|
||||
# NotAuthenticated, rather than because of an SSL error.
|
||||
|
||||
self.assertNotEqual(0, exitcode)
|
||||
self.assertNotIn('SSL23_GET_SERVER_HELLO', out)
|
||||
self.assertIn('NotAuthenticated: You are not authenticated.', out)
|
||||
|
||||
|
||||
class TestBinGlance(functional.FunctionalTest):
|
||||
"""Functional tests for the bin/glance CLI tool"""
|
||||
|
||||
@ -78,6 +48,20 @@ class TestBinGlance(functional.FunctionalTest):
|
||||
msg = 'expected "%s" to start with "%s"' % (str, prefix)
|
||||
self.assertTrue(str.startswith(prefix), msg)
|
||||
|
||||
def _assertNotIn(self, key, bag):
|
||||
msg = 'Expected not to find substring "%s" in "%s"' % (key, bag)
|
||||
self.assertFalse(key in bag, msg)
|
||||
|
||||
def test_index_with_https(self):
|
||||
self.cleanup()
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
cmd = ("bin/glance -N https://auth/ --port=%d index") % self.api_port
|
||||
exitcode, out, err = execute(cmd, raise_error=False)
|
||||
|
||||
self.assertNotEqual(0, exitcode)
|
||||
self._assertNotIn('SSL23_GET_SERVER_HELLO', out)
|
||||
|
||||
def test_add_with_location_and_id(self):
|
||||
self.cleanup()
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
@ -176,103 +160,6 @@ class TestBinGlance(functional.FunctionalTest):
|
||||
self.assertEqual('0', size, "Expected image to be 0 bytes in size, "
|
||||
"but got %s. " % size)
|
||||
|
||||
def _verify_owner(self, owner, image_id):
|
||||
cmd = "bin/glance --port=%d show %s" % (self.api_port, image_id)
|
||||
exitcode, out, err = execute(cmd)
|
||||
self.assertEqual(0, exitcode)
|
||||
|
||||
# verify expected owner as first class attribute
|
||||
self.assertTrue(('Owner: %s' % owner) in out)
|
||||
# ensure owner does not appear as a custom property
|
||||
self.assertFalse("Property 'owner':" in out)
|
||||
|
||||
def _create_by_admin(self, owner):
|
||||
# ownership set by admin user (defaults as such due to no-auth)
|
||||
cmd = minimal_add_command(self.api_port,
|
||||
'MyImage',
|
||||
'--silent-upload owner=%s' % owner)
|
||||
exitcode, out, err = execute(cmd)
|
||||
|
||||
self.assertEqual(0, exitcode)
|
||||
self.assertTrue(out.strip().startswith('Added new image with ID:'))
|
||||
|
||||
return out.strip().replace('Added new image with ID: ', '')
|
||||
|
||||
def test_add_with_owner_admin(self):
|
||||
"""Test setting ownership of new image by admin user"""
|
||||
self.cleanup()
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
image_id = self._create_by_admin('42')
|
||||
|
||||
self._verify_owner('42', image_id)
|
||||
|
||||
def test_add_with_owner_non_admin(self):
|
||||
"""Test setting ownership of new image by non-admin user"""
|
||||
self.cleanup()
|
||||
self.api_server.deployment_flavor = 'fakeauth'
|
||||
self.registry_server.deployment_flavor = 'fakeauth'
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
# ownership set by non-admin user (setup as such by fakeauth pipeline)
|
||||
headers = {'X-Image-Meta-Name': 'MyImage',
|
||||
'X-Image-Meta-disk_format': 'raw',
|
||||
'X-Image-Meta-container_format': 'ovf',
|
||||
'X-Image-Meta-Is-Public': 'True',
|
||||
'X-Image-Meta-Owner': '42',
|
||||
'X-Auth-Token': 'Confirmed:pattieblack:froggy:demo',
|
||||
}
|
||||
|
||||
path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'POST', headers=headers)
|
||||
self.assertEqual(response.status, 201)
|
||||
data = json.loads(content)
|
||||
image_id = data['image']['id']
|
||||
|
||||
self._verify_owner('froggy', image_id)
|
||||
|
||||
def test_update_with_owner_admin(self):
|
||||
"""Test updating ownership of existing image by admin user"""
|
||||
self.cleanup()
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
image_id = self._create_by_admin('user1')
|
||||
|
||||
self._verify_owner('user1', image_id)
|
||||
|
||||
# ownership updated by admin user (defaults as such due to no-auth)
|
||||
cmd = "bin/glance update %s owner=user2 -p %d" % (image_id,
|
||||
self.api_port)
|
||||
exitcode, out, err = execute(cmd, raise_error=False)
|
||||
|
||||
self.assertEqual(0, exitcode)
|
||||
self.assertTrue(out.strip().endswith('Updated image %s' % image_id))
|
||||
|
||||
self._verify_owner('user2', image_id)
|
||||
|
||||
def test_update_with_owner_non_admin(self):
|
||||
"""Test updating ownership of existing image by non-admin user"""
|
||||
self.cleanup()
|
||||
self.api_server.deployment_flavor = 'fakeauth'
|
||||
self.registry_server.deployment_flavor = 'fakeauth'
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
image_id = self._create_by_admin('user1')
|
||||
|
||||
# ownership update attempted by non-admin user
|
||||
# (setup as such by fakeauth pipeline)
|
||||
headers = {'X-Image-Meta-Owner': 'user2',
|
||||
'X-Auth-Token': 'Confirmed:pattieblack:froggy:demo',
|
||||
}
|
||||
|
||||
path = "http://%s:%d/v1/images/%s" % ("0.0.0.0",
|
||||
self.api_port,
|
||||
image_id)
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'PUT', headers=headers)
|
||||
self.assertEqual(response.status, 403)
|
||||
|
||||
def test_add_no_name(self):
|
||||
self.cleanup()
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
@ -1241,3 +1241,115 @@ class TestApi(functional.FunctionalTest):
|
||||
@skip_if_disabled
|
||||
def _do_test_put_image_content_missing_disk_format(self):
|
||||
self._do_test_put_image_content_missing_format('disk_format')
|
||||
|
||||
@skip_if_disabled
|
||||
def test_ownership(self):
|
||||
self.cleanup()
|
||||
self.api_server.deployment_flavor = 'fakeauth'
|
||||
self.registry_server.deployment_flavor = 'fakeauth'
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
# Add an image with admin privileges and ensure the owner
|
||||
# can be set to something other than what was used to authenticate
|
||||
auth_headers = {
|
||||
'X-Auth-Token': 'user1:tenant1:admin',
|
||||
}
|
||||
|
||||
create_headers = {
|
||||
'X-Image-Meta-Name': 'MyImage',
|
||||
'X-Image-Meta-disk_format': 'raw',
|
||||
'X-Image-Meta-container_format': 'ovf',
|
||||
'X-Image-Meta-Is-Public': 'True',
|
||||
'X-Image-Meta-Owner': 'tenant2',
|
||||
}
|
||||
create_headers.update(auth_headers)
|
||||
|
||||
path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'POST', headers=create_headers)
|
||||
self.assertEqual(response.status, 201)
|
||||
data = json.loads(content)
|
||||
image_id = data['image']['id']
|
||||
|
||||
path = ("http://%s:%d/v1/images/%s" %
|
||||
("0.0.0.0", self.api_port, image_id))
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'HEAD', headers=auth_headers)
|
||||
self.assertEqual(response.status, 200)
|
||||
self.assertEqual('tenant2', response['x-image-meta-owner'])
|
||||
|
||||
# Now add an image without admin privileges and ensure the owner
|
||||
# cannot be set to something other than what was used to authenticate
|
||||
auth_headers = {
|
||||
'X-Auth-Token': 'user1:tenant1:role1',
|
||||
}
|
||||
create_headers.update(auth_headers)
|
||||
|
||||
path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'POST', headers=create_headers)
|
||||
self.assertEqual(response.status, 201)
|
||||
data = json.loads(content)
|
||||
image_id = data['image']['id']
|
||||
|
||||
# We have to be admin to see the owner
|
||||
auth_headers = {
|
||||
'X-Auth-Token': 'user1:tenant1:admin',
|
||||
}
|
||||
create_headers.update(auth_headers)
|
||||
|
||||
path = ("http://%s:%d/v1/images/%s" %
|
||||
("0.0.0.0", self.api_port, image_id))
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'HEAD', headers=auth_headers)
|
||||
self.assertEqual(response.status, 200)
|
||||
self.assertEqual('tenant1', response['x-image-meta-owner'])
|
||||
|
||||
# Make sure the non-privileged user can't update their owner either
|
||||
update_headers = {
|
||||
'X-Image-Meta-Name': 'MyImage2',
|
||||
'X-Image-Meta-Owner': 'tenant2',
|
||||
'X-Auth-Token': 'user1:tenant1:role1',
|
||||
}
|
||||
|
||||
path = ("http://%s:%d/v1/images/%s" %
|
||||
("0.0.0.0", self.api_port, image_id))
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'PUT', headers=update_headers)
|
||||
self.assertEqual(response.status, 200)
|
||||
|
||||
# We have to be admin to see the owner
|
||||
auth_headers = {
|
||||
'X-Auth-Token': 'user1:tenant1:admin',
|
||||
}
|
||||
|
||||
path = ("http://%s:%d/v1/images/%s" %
|
||||
("0.0.0.0", self.api_port, image_id))
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'HEAD', headers=auth_headers)
|
||||
self.assertEqual(response.status, 200)
|
||||
self.assertEqual('tenant1', response['x-image-meta-owner'])
|
||||
|
||||
# An admin user should be able to update the owner
|
||||
auth_headers = {
|
||||
'X-Auth-Token': 'user1:tenant3:admin',
|
||||
}
|
||||
|
||||
update_headers = {
|
||||
'X-Image-Meta-Name': 'MyImage2',
|
||||
'X-Image-Meta-Owner': 'tenant2',
|
||||
}
|
||||
update_headers.update(auth_headers)
|
||||
|
||||
path = ("http://%s:%d/v1/images/%s" %
|
||||
("0.0.0.0", self.api_port, image_id))
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'PUT', headers=update_headers)
|
||||
self.assertEqual(response.status, 200)
|
||||
|
||||
path = ("http://%s:%d/v1/images/%s" %
|
||||
("0.0.0.0", self.api_port, image_id))
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'HEAD', headers=auth_headers)
|
||||
self.assertEqual(response.status, 200)
|
||||
self.assertEqual('tenant2', response['x-image-meta-owner'])
|
||||
|
@ -72,7 +72,8 @@ def stub_out_registry_and_store_server(stubs, base_dir):
|
||||
'verbose': VERBOSE,
|
||||
'debug': DEBUG
|
||||
})
|
||||
api = context.ContextMiddleware(rserver.API(conf), conf)
|
||||
api = context.UnauthenticatedContextMiddleware(
|
||||
rserver.API(conf), conf)
|
||||
res = self.req.get_response(api)
|
||||
|
||||
# httplib.Response has a read() method...fake it out
|
||||
@ -160,7 +161,8 @@ def stub_out_registry_and_store_server(stubs, base_dir):
|
||||
'filesystem_store_datadir': base_dir,
|
||||
'policy_file': os.path.join(base_dir, 'policy.json'),
|
||||
})
|
||||
api = context.ContextMiddleware(router.API(conf), conf)
|
||||
api = context.UnauthenticatedContextMiddleware(
|
||||
router.API(conf), conf)
|
||||
res = self.req.get_response(api)
|
||||
|
||||
# httplib.Response has a read() method...fake it out
|
||||
@ -240,7 +242,8 @@ def stub_out_registry_server(stubs, **kwargs):
|
||||
'verbose': VERBOSE,
|
||||
'debug': DEBUG
|
||||
})
|
||||
api = context.ContextMiddleware(rserver.API(conf), conf)
|
||||
api = context.UnauthenticatedContextMiddleware(
|
||||
rserver.API(conf), conf)
|
||||
res = self.req.get_response(api)
|
||||
|
||||
# httplib.Response has a read() method...fake it out
|
||||
|
@ -67,7 +67,7 @@ class TestPasteApp(unittest.TestCase):
|
||||
os.rmdir(os.path.dirname(conf.temp_file))
|
||||
|
||||
def test_load_paste_app(self):
|
||||
expected_middleware = context.ContextMiddleware
|
||||
expected_middleware = context.UnauthenticatedContextMiddleware
|
||||
self._do_test_load_paste_app(expected_middleware)
|
||||
|
||||
def test_load_paste_app_with_paste_flavor(self):
|
||||
@ -83,7 +83,7 @@ class TestPasteApp(unittest.TestCase):
|
||||
'etc/glance-registry-paste.ini')
|
||||
paste_group = {'paste_deploy': {'config_file': paste_config_file}}
|
||||
|
||||
expected_middleware = context.ContextMiddleware
|
||||
expected_middleware = context.UnauthenticatedContextMiddleware
|
||||
self._do_test_load_paste_app(expected_middleware,
|
||||
paste_group, paste_copy=False)
|
||||
|
||||
|
@ -93,7 +93,8 @@ class TestRegistryAPI(base.IsolatedUnitTest):
|
||||
def setUp(self):
|
||||
"""Establish a clean test environment"""
|
||||
super(TestRegistryAPI, self).setUp()
|
||||
self.api = context.ContextMiddleware(rserver.API(self.conf), self.conf)
|
||||
self.api = context.UnauthenticatedContextMiddleware(
|
||||
rserver.API(self.conf), self.conf)
|
||||
self.FIXTURES = [
|
||||
{'id': UUID1,
|
||||
'name': 'fake image #1',
|
||||
@ -1867,15 +1868,6 @@ class TestRegistryAPI(base.IsolatedUnitTest):
|
||||
self.assertEquals(res.status_int,
|
||||
webob.exc.HTTPNotFound.code)
|
||||
|
||||
def test_delete_image_public_not_owned(self):
|
||||
req = webob.Request.blank('/images/%s' % UUID2)
|
||||
req.method = 'DELETE'
|
||||
req.headers['x-auth-token'] = 'toke'
|
||||
req.headers['x-identity-status'] = 'Confirmed'
|
||||
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 403)
|
||||
|
||||
def test_get_image_members(self):
|
||||
"""
|
||||
Tests members listing for existing images
|
||||
@ -1955,7 +1947,8 @@ class TestGlanceAPI(base.IsolatedUnitTest):
|
||||
def setUp(self):
|
||||
"""Establish a clean test environment"""
|
||||
super(TestGlanceAPI, self).setUp()
|
||||
self.api = context.ContextMiddleware(router.API(self.conf), self.conf)
|
||||
self.api = context.UnauthenticatedContextMiddleware(
|
||||
router.API(self.conf), self.conf)
|
||||
self.FIXTURES = [
|
||||
{'id': UUID1,
|
||||
'name': 'fake image #1',
|
||||
|
@ -384,8 +384,8 @@ class FakeAuthMiddleware(wsgi.Middleware):
|
||||
def process_request(self, req):
|
||||
auth_tok = req.headers.get('X-Auth-Token')
|
||||
if auth_tok:
|
||||
status, user, tenant, role = auth_tok.split(':')
|
||||
req.headers['X-Identity-Status'] = status
|
||||
user, tenant, role = auth_tok.split(':')
|
||||
req.headers['X-User-Id'] = user
|
||||
req.headers['X-Tenant-Id'] = tenant
|
||||
req.headers['X-Role'] = role
|
||||
req.headers['X-Roles'] = role
|
||||
req.headers['X-Identity-Status'] = 'Confirmed'
|
||||
|
Loading…
Reference in New Issue
Block a user