Make placement base API return version without auth
Allow both GET '/placement' and '/placement/' to return version info without doing authentication. In many deployment placement is found on a prefix of '/placement' different servers will or will not append the '/'. To be most resilient, accept either as "root". A unit test is added which confirms that no auth is required for root but auth is still required elsewhere. Co-Authored-By: Chris Dent <cdent@anticdent.org> Related-Bug: #1838633 Change-Id: Iaa93ec943f4f4fbb6c1af3a809859813872e62d7
This commit is contained in:
parent
b12cba973d
commit
5466ec1833
@ -66,7 +66,7 @@ class PlacementKeystoneContext(Middleware):
|
|||||||
ctx = context.RequestContext.from_environ(
|
ctx = context.RequestContext.from_environ(
|
||||||
req.environ, request_id=req_id)
|
req.environ, request_id=req_id)
|
||||||
|
|
||||||
if ctx.user_id is None and req.environ['PATH_INFO'] != '/':
|
if ctx.user_id is None and req.environ['PATH_INFO'] not in ['/', '']:
|
||||||
LOG.debug("Neither X_USER_ID nor X_USER found in request")
|
LOG.debug("Neither X_USER_ID nor X_USER found in request")
|
||||||
return webob.exc.HTTPUnauthorized()
|
return webob.exc.HTTPUnauthorized()
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ class PlacementAuthProtocol(auth_token.AuthProtocol):
|
|||||||
super(PlacementAuthProtocol, self).__init__(app, conf)
|
super(PlacementAuthProtocol, self).__init__(app, conf)
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
if environ['PATH_INFO'] == '/':
|
if environ['PATH_INFO'] in ['/', '']:
|
||||||
return self._placement_app(environ, start_response)
|
return self._placement_app(environ, start_response)
|
||||||
|
|
||||||
return super(PlacementAuthProtocol, self).__call__(
|
return super(PlacementAuthProtocol, self).__call__(
|
||||||
|
75
placement/tests/unit/test_auth.py
Normal file
75
placement/tests/unit/test_auth.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
"""Unit tests for the auth middleware used by the Placement service.
|
||||||
|
|
||||||
|
Most of the functionality of the auth middleware is tested in functional
|
||||||
|
and integration tests but sometimes it is more convenient or accurate to
|
||||||
|
use unit tests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from keystonemiddleware import auth_token
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_config import fixture as config_fixture
|
||||||
|
from oslo_policy import opts as policy_opts
|
||||||
|
import testtools
|
||||||
|
import webob
|
||||||
|
|
||||||
|
from placement import conf
|
||||||
|
from placement import deploy
|
||||||
|
|
||||||
|
|
||||||
|
class RootNoAuth(testtools.TestCase):
|
||||||
|
"""Confirm that no auth is required for accessing root."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Establish config defaults for middlewares."""
|
||||||
|
super(RootNoAuth, self).setUp()
|
||||||
|
config = cfg.ConfigOpts()
|
||||||
|
conf_fixture = self.useFixture(config_fixture.Config(config))
|
||||||
|
conf.register_opts(conf_fixture.conf)
|
||||||
|
auth_token_opts = auth_token.AUTH_TOKEN_OPTS[0][1]
|
||||||
|
conf_fixture.register_opts(auth_token_opts, group='keystone_authtoken')
|
||||||
|
www_authenticate_uri = 'http://example.com/identity'
|
||||||
|
conf_fixture.config(
|
||||||
|
www_authenticate_uri=www_authenticate_uri,
|
||||||
|
group='keystone_authtoken')
|
||||||
|
# ensure that the auth_token middleware is chosen
|
||||||
|
conf_fixture.config(auth_strategy='keystone', group='api')
|
||||||
|
# register and default policy opts (referenced by deploy)
|
||||||
|
policy_opts.set_defaults(conf_fixture.conf)
|
||||||
|
self.conf = conf_fixture.conf
|
||||||
|
self.app = deploy.deploy(self.conf)
|
||||||
|
|
||||||
|
def _test_root_req(self, req):
|
||||||
|
# set no environ on req, thus no auth
|
||||||
|
req.environ['REMOTE_ADDR'] = '127.0.0.1'
|
||||||
|
|
||||||
|
response = req.get_response(self.app)
|
||||||
|
data = response.json_body
|
||||||
|
self.assertEqual('CURRENT', data['versions'][0]['status'])
|
||||||
|
|
||||||
|
def test_slash_no_auth(self):
|
||||||
|
"""Accessing / requires no auth."""
|
||||||
|
req = webob.Request.blank('/', method='GET')
|
||||||
|
self._test_root_req(req)
|
||||||
|
|
||||||
|
def test_no_slash_no_auth(self):
|
||||||
|
"""Accessing '' requires no auth."""
|
||||||
|
req = webob.Request.blank('', method='GET')
|
||||||
|
self._test_root_req(req)
|
||||||
|
|
||||||
|
def test_auth_elsewhere(self):
|
||||||
|
"""Make sure auth is happening."""
|
||||||
|
req = webob.Request.blank('/resource_providers', method='GET')
|
||||||
|
req.environ['REMOTE_ADDR'] = '127.0.0.1'
|
||||||
|
response = req.get_response(self.app)
|
||||||
|
self.assertEqual('401 Unauthorized', response.status)
|
Loading…
Reference in New Issue
Block a user