diff --git a/nova/tests/fixtures.py b/nova/tests/fixtures.py index 5e16c545b779..ce66ddb77411 100644 --- a/nova/tests/fixtures.py +++ b/nova/tests/fixtures.py @@ -874,7 +874,7 @@ class OSAPIFixture(fixtures.Fixture): def __init__(self, api_version='v2', project_id='6f70656e737461636b20342065766572', - use_project_id_in_urls=False): + use_project_id_in_urls=False, stub_keystone=True): """Constructor :param api_version: the API version that we're interested in @@ -883,11 +883,14 @@ class OSAPIFixture(fixtures.Fixture): :param project_id: the project id to use on the API. :param use_project_id_in_urls: If True, act like the "endpoint" in the "service catalog" has the legacy format including the project_id. + :param stub_keystone: If True, stub keystonemiddleware and + NovaKeystoneContext to simulate (but not perform) real auth. """ super(OSAPIFixture, self).__init__() self.api_version = api_version self.project_id = project_id self.use_project_id_in_urls = use_project_id_in_urls + self.stub_keystone = stub_keystone def setUp(self): super(OSAPIFixture, self).setUp() @@ -903,22 +906,8 @@ class OSAPIFixture(fixtures.Fixture): } self.useFixture(ConfPatcher(**conf_overrides)) - # Stub out authentication middleware - # TODO(efried): Use keystonemiddleware.fixtures.AuthTokenFixture - self.useFixture(fixtures.MockPatch( - 'keystonemiddleware.auth_token.filter_factory', - return_value=lambda _app: _app)) - - # Stub out context middleware - def fake_ctx(env, **kwargs): - user_id = env['HTTP_X_AUTH_USER'] - project_id = env['HTTP_X_AUTH_PROJECT_ID'] - is_admin = user_id == 'admin' - return context.RequestContext( - user_id, project_id, is_admin=is_admin, **kwargs) - - self.useFixture(fixtures.MonkeyPatch( - 'nova.api.auth.NovaKeystoneContext._create_context', fake_ctx)) + if self.stub_keystone: + self._stub_keystone() # Turn off manipulation of socket_options in TCPKeepAliveAdapter # to keep wsgi-intercept happy. Replace it with the method @@ -950,6 +939,24 @@ class OSAPIFixture(fixtures.Fixture): # the fixture. self.app = app + def _stub_keystone(self): + # Stub out authentication middleware + # TODO(efried): Use keystonemiddleware.fixtures.AuthTokenFixture + self.useFixture(fixtures.MockPatch( + 'keystonemiddleware.auth_token.filter_factory', + return_value=lambda _app: _app)) + + # Stub out context middleware + def fake_ctx(env, **kwargs): + user_id = env['HTTP_X_AUTH_USER'] + project_id = env['HTTP_X_AUTH_PROJECT_ID'] + is_admin = user_id == 'admin' + return context.RequestContext( + user_id, project_id, is_admin=is_admin, **kwargs) + + self.useFixture(fixtures.MonkeyPatch( + 'nova.api.auth.NovaKeystoneContext._create_context', fake_ctx)) + class OSMetadataServer(fixtures.Fixture): """Create an OS Metadata API server as a fixture. diff --git a/nova/tests/functional/api_sample_tests/test_versions.py b/nova/tests/functional/api_sample_tests/test_versions.py index 166195769f5a..373b87c002ea 100644 --- a/nova/tests/functional/api_sample_tests/test_versions.py +++ b/nova/tests/functional/api_sample_tests/test_versions.py @@ -12,33 +12,64 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +import ddt +import fixtures +import webob from nova.api.openstack import api_version_request as avr from nova.tests.functional.api_sample_tests import api_sample_base +@ddt.ddt class VersionsSampleJsonTest(api_sample_base.ApiSampleTestBaseV21): + """Validate that proper version documents can be fetched without auth.""" + + # Here we want to avoid stubbing keystone middleware. That will cause + # "real" keystone middleware to run (and fail) if it's in the pipeline. + # (The point of this test is to prove we do version discovery through + # pipelines that *don't* authenticate.) + STUB_KEYSTONE = False + sample_dir = 'versions' _use_project_id = False # NOTE(gmann): Setting empty scenario for 'version' API testing # as those does not send request on particular endpoint and running # its tests alone is enough. scenarios = [] - max_api_version = avr.max_api_version().get_string() + max_api_version = {'max_api_version': avr.max_api_version().get_string()} - def test_versions_get(self): - response = self._do_get('', strip_version=True) - self._verify_response('versions-get-resp', - {'max_api_version': self.max_api_version}, + def setUp(self): + super(VersionsSampleJsonTest, self).setUp() + # Version documents are supposed to be available without auth, so make + # the auth middleware "fail" authentication. + self.useFixture(fixtures.MockPatch( + # [api]auth_strategy is set to noauth2 by the ConfFixture + 'nova.api.openstack.auth.NoAuthMiddlewareBase.base_call', + return_value=webob.Response(status=401))) + + def _get(self, url): + return self._do_get( + url, + # Since we're explicitly getting discovery endpoints, strip the + # automatic /v2[.1] added by the fixture. + strip_version=True) + + @ddt.data('', '/') + def test_versions_get_base(self, url): + response = self._get(url) + self._verify_response('versions-get-resp', self.max_api_version, response, 200, update_links=False) - def test_versions_get_v2(self): - response = self._do_get('/v2', strip_version=True) - self._verify_response('v2-version-get-resp', {}, - response, 200, update_links=False) - - def test_versions_get_v21(self): - response = self._do_get('/v2.1', strip_version=True) - self._verify_response('v21-version-get-resp', - {'max_api_version': self.max_api_version}, - response, 200, update_links=False) + @ddt.data(('/v2', 'v2-version-get-resp', {}), + ('/v2/', 'v2-version-get-resp', {}), + ('/v2.1', 'v21-version-get-resp', max_api_version), + ('/v2.1/', 'v21-version-get-resp', max_api_version)) + @ddt.unpack + def test_versions_get_versioned(self, url, tplname, subs): + response = self._get(url) + # TODO(efried): This is bug 1845530 whereby we try to authenticate at + # the versioned discovery endpoint. + self.assertEqual(401, response.status_code) + # TODO(efried): Uncomment when bug 1845530 is resolved + # self._verify_response(tplname, subs, response, 200, + # update_links=False) diff --git a/nova/tests/functional/integrated_helpers.py b/nova/tests/functional/integrated_helpers.py index 4215e59df1c3..0c9a7df0010f 100644 --- a/nova/tests/functional/integrated_helpers.py +++ b/nova/tests/functional/integrated_helpers.py @@ -362,6 +362,10 @@ class _IntegratedTestBase(test.TestCase, InstanceHelperMixin): # This indicates whether to include the project ID in the URL for API # requests through OSAPIFixture. Overridden by subclasses. _use_project_id = False + # Override this in subclasses to avoid stubbing keystonemiddleware and + # NovaKeystoneContext, thus making those middlewares behave as they would + # in real life (i.e. try to do real authentication). + STUB_KEYSTONE = True def setUp(self): super(_IntegratedTestBase, self).setUp() @@ -398,7 +402,8 @@ class _IntegratedTestBase(test.TestCase, InstanceHelperMixin): self.api_fixture = self.useFixture( nova_fixtures.OSAPIFixture( api_version=self.api_major_version, - use_project_id_in_urls=self._use_project_id)) + use_project_id_in_urls=self._use_project_id, + stub_keystone=self.STUB_KEYSTONE)) # if the class needs to run as admin, make the api endpoint # the admin, otherwise it's safer to run as non admin user.