Merge "Add public api support to basic auth"
This commit is contained in:
commit
9ecb6e33eb
@ -164,6 +164,14 @@ class TestBasicAuthApiIntrospect(TestApiIntrospect):
|
||||
headers=self.headers)
|
||||
self.assertEqual(401, res.status_code)
|
||||
|
||||
def test_unauthenticated_public_api(self):
|
||||
res = self.app.get('/')
|
||||
self.assertEqual(200, res.status_code)
|
||||
res = self.app.get('/v1')
|
||||
self.assertEqual(200, res.status_code)
|
||||
res = self.app.get('/v1/introspection')
|
||||
self.assertEqual(401, res.status_code)
|
||||
|
||||
|
||||
class TestApiContinue(BaseAPITest):
|
||||
def test_continue(self):
|
||||
|
@ -16,12 +16,14 @@ import logging as pylog
|
||||
|
||||
import futurist
|
||||
from ironic_lib import auth_basic
|
||||
from ironic_lib import exception
|
||||
from keystonemiddleware import auth_token
|
||||
from openstack.baremetal.v1 import node
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_middleware import cors as cors_middleware
|
||||
import pytz
|
||||
import webob
|
||||
|
||||
from ironic_inspector.common.i18n import _
|
||||
from ironic_inspector import policy
|
||||
@ -169,6 +171,42 @@ class NoAvailableConductor(Error):
|
||||
super(NoAvailableConductor, self).__init__(msg, code=503, **kwargs)
|
||||
|
||||
|
||||
class DeferredBasicAuthMiddleware(object):
|
||||
"""Middleware which sets X-Identity-Status header based on authentication
|
||||
|
||||
"""
|
||||
def __init__(self, app, auth_file):
|
||||
self.app = app
|
||||
self.auth_file = auth_file
|
||||
auth_basic.validate_auth_file(auth_file)
|
||||
|
||||
@webob.dec.wsgify()
|
||||
def __call__(self, req):
|
||||
|
||||
headers = req.headers
|
||||
try:
|
||||
if 'Authorization' not in headers:
|
||||
auth_basic.unauthorized()
|
||||
|
||||
token = auth_basic.parse_header({
|
||||
'HTTP_AUTHORIZATION': headers.get('Authorization')
|
||||
})
|
||||
username, password = auth_basic.parse_token(token)
|
||||
headers.update(
|
||||
auth_basic.authenticate(self.auth_file, username, password))
|
||||
headers['X-Identity-Status'] = 'Confirmed'
|
||||
|
||||
except exception.Unauthorized:
|
||||
headers['X-Identity-Status'] = 'Invalid'
|
||||
except exception.IronicException as e:
|
||||
status = '%s %s' % (int(e.code), str(e))
|
||||
resp = webob.Response(status=status)
|
||||
resp.headers.update(e.headers)
|
||||
return resp
|
||||
|
||||
return req.get_response(self.app)
|
||||
|
||||
|
||||
def executor():
|
||||
"""Return the current futures executor."""
|
||||
global _EXECUTOR
|
||||
@ -193,7 +231,7 @@ def add_basic_auth_middleware(app):
|
||||
|
||||
:param app: application.
|
||||
"""
|
||||
app.wsgi_app = auth_basic.BasicAuthMiddleware(
|
||||
app.wsgi_app = DeferredBasicAuthMiddleware(
|
||||
app.wsgi_app, CONF.http_basic_auth_user_file)
|
||||
|
||||
|
||||
@ -216,11 +254,13 @@ def check_auth(request, rule=None, target=None):
|
||||
:param target: dict-like structure to check rule against
|
||||
:raises: utils.Error if access is denied
|
||||
"""
|
||||
if CONF.auth_strategy != 'keystone':
|
||||
if CONF.auth_strategy not in ('keystone', 'http_basic'):
|
||||
return
|
||||
if not request.context.is_public_api:
|
||||
if request.headers.get('X-Identity-Status', '').lower() == 'invalid':
|
||||
raise Error(_('Authentication required'), code=401)
|
||||
if CONF.auth_strategy != 'keystone':
|
||||
return
|
||||
target = {} if target is None else target
|
||||
if not policy.authorize(rule, target, request.context.to_policy_values()):
|
||||
raise Error(_("Access denied by policy"), code=403)
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Using auth_strategy=http_basic incorrectly required authentication for
|
||||
public paths such as / and /v1. These paths are now public.
|
Loading…
Reference in New Issue
Block a user