Making / and /v2 URL allowed without auth

Closes-Bug: #1473963

Change-Id: I7170121a1216d9d72a43e552db1864a58e4c6237
(cherry-picked from commit e523f7537c)
This commit is contained in:
Nikolay Mahotkin 2015-07-13 18:36:52 +03:00
parent 5c0e8ca8e7
commit 9f5d338265
5 changed files with 80 additions and 7 deletions

View File

@ -15,7 +15,7 @@
# How many seconds to wait for the API to be responding before giving up
API_RESPONDING_TIMEOUT=20
if ! timeout ${API_RESPONDING_TIMEOUT} sh -c "while ! curl -s http://127.0.0.1:8989/v2/ 2>/dev/null | grep -q 'Authentication required' ; do sleep 1; done"; then
if ! timeout ${API_RESPONDING_TIMEOUT} sh -c "until curl --output /dev/null --silent --head --fail http://localhost:8989; do sleep 1; done"; then
echo "Mistral API failed to respond within ${API_RESPONDING_TIMEOUT} seconds"
exit 1
fi

View File

@ -25,7 +25,12 @@ _ENFORCER = None
def setup(app):
if cfg.CONF.pecan.auth_enable:
return auth_token.AuthProtocol(app, dict(cfg.CONF.keystone_authtoken))
conf = dict(cfg.CONF.keystone_authtoken)
# Change auth decisions of requests to the app itself.
conf.update({'delay_auth_decision': True})
return auth_token.AuthProtocol(app, conf)
else:
return app

View File

@ -51,7 +51,7 @@ def setup_app(config=None):
app = pecan.make_app(
app_conf.pop('root'),
hooks=lambda: [ctx.ContextHook()],
hooks=lambda: [ctx.ContextHook(), ctx.AuthHook()],
logging=getattr(config, 'logging', {}),
**app_conf
)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# Copyright 2013 - Mirantis, Inc.
#
@ -16,8 +15,9 @@
import eventlet
from keystoneclient.v3 import client as keystone_client
from oslo.config import cfg
from oslo import messaging
from oslo_config import cfg
import oslo_messaging as messaging
import pecan
from pecan import hooks
from mistral import exceptions as exc
@ -28,6 +28,7 @@ from mistral import utils
CONF = cfg.CONF
_CTX_THREAD_LOCAL_NAME = "MISTRAL_APP_CTX_THREAD_LOCAL"
ALLOWED_WITHOUT_AUTH = ['/', '/v2/']
class BaseContext(object):
@ -157,7 +158,6 @@ class JsonPayloadSerializer(messaging.NoOpSerializer):
class RpcContextSerializer(messaging.Serializer):
def __init__(self, base=None):
self._base = base or messaging.NoOpSerializer()
@ -183,6 +183,33 @@ class RpcContextSerializer(messaging.Serializer):
return ctx
class AuthHook(hooks.PecanHook):
def before(self, state):
if state.request.path in ALLOWED_WITHOUT_AUTH:
return
if CONF.pecan.auth_enable:
# Note(nmakhotkin): Since we have deferred authentication,
# need to check for auth manually (check for corresponding
# headers according to keystonemiddleware docs.
identity_status = state.request.headers.get('X-Identity-Status')
service_identity_status = state.request.headers.get(
'X-Service-Identity-Status'
)
if (identity_status == 'Confirmed'
or service_identity_status == 'Confirmed'):
return
if state.request.headers.get('X-Auth-Token'):
msg = ("Auth token is invalid: %s"
% state.request.headers['X-Auth-Token'])
else:
msg = 'Authentication required'
pecan.abort(status_code=401, detail=msg)
class ContextHook(hooks.PecanHook):
def before(self, state):
set_ctx(context_from_headers(state.request.headers))

View File

@ -16,6 +16,7 @@
from mistral.openstack.common import jsonutils
from mistral.tests.unit.api import base
from mistral.tests.unit.api import test_auth
class TestRootController(base.FunctionalTest):
@ -32,3 +33,43 @@ class TestRootController(base.FunctionalTest):
data[0]['link'],
{'href': 'http://localhost/v2', 'target': 'v2'}
)
def test_v2_root(self):
resp = self.app.get('/v2/', headers={'Accept': 'application/json'})
self.assertEqual(resp.status_int, 200)
data = jsonutils.loads(resp.body.decode())
self.assertEqual(
'http://localhost/v2',
data['uri']
)
class TestRootControllerWithAuth(test_auth.TestKeystoneMiddleware):
def test_index(self):
resp = self.app.get('/', headers={'Accept': 'application/json'})
self.assertEqual(resp.status_int, 200)
data = jsonutils.loads(resp.body.decode())
self.assertEqual(data[0]['id'], 'v2.0')
self.assertEqual(data[0]['status'], 'CURRENT')
self.assertEqual(
data[0]['link'],
{'href': 'http://localhost/v2', 'target': 'v2'}
)
def test_v2_root(self):
resp = self.app.get('/v2/', headers={'Accept': 'application/json'})
self.assertEqual(resp.status_int, 200)
data = jsonutils.loads(resp.body.decode())
self.assertEqual(
'http://localhost/v2',
data['uri']
)