Auth: Check token validity + secure bansho/config

Change-Id: I417814a16df582ee636c197bcc7008978e084d3a
This commit is contained in:
aviau 2015-05-01 14:42:26 -04:00
parent 8480b4cc8e
commit 57025d4f4b
7 changed files with 73 additions and 24 deletions

View File

@ -1,6 +1,10 @@
{
"admin_required": "role:admin or is_admin:1",
"surveil_required": "role:surveil",
"surveil:admin": "rule:admin_required",
"surveil:authenticated": "rule:surveil_required",
"surveil:break": "!",
"surveil:pass": "@"
}
}

View File

@ -88,23 +88,23 @@ class AuthProtocol(object):
"""
self._remove_auth_headers(env)
# TODO(aviau): Get token and validate it, then build proper headers
if False:
self._reject_request(env, start_response)
token = self._get_header(env, 'X-Auth-Token', None)
user_headers = {
'X-Identity-Status': 'Confirmed',
'X-User-Id': 'surveil-default-user',
'X-Roles': 'admin',
'X-Service-Catalog': 'surveil'
}
self._add_headers(env, user_headers)
# TODO(aviau): Validate token, then build proper headers
if token == "aaaaa-bbbbb-ccccc-dddd":
user_headers = {
'X-Identity-Status': 'Confirmed',
'X-User-Id': 'surveil-default-user',
'X-Roles': 'admin,surveil',
'X-Service-Catalog': 'surveil'
}
self._add_headers(env, user_headers)
service_headers = {
'X-Service-Identity-Status': 'Confirmed',
'X-Service-Roles': 'surveil',
}
self._add_headers(env, service_headers)
service_headers = {
'X-Service-Identity-Status': 'Confirmed',
'X-Service-Roles': 'surveil',
}
self._add_headers(env, service_headers)
return self._call_app(env, start_response)
@ -142,6 +142,11 @@ class AuthProtocol(object):
"""
return 'HTTP_%s' % key.replace('-', '_').upper()
def _get_header(self, env, key, default=None):
"""Get http header from environment."""
env_key = self._header_to_env_var(key)
return env.get(env_key, default)
def _call_app(self, env, start_response):
# NOTE(jamielennox): We wrap the given start response so that if an
# application with a 'delay_auth_decision' setting fails, or otherwise

View File

@ -18,10 +18,12 @@ from pecan import rest
import wsmeext.pecan as wsme_pecan
from surveil.api.handlers.bansho import config_handler
from surveil.common import util
class ConfigController(rest.RestController):
@util.policy_enforce(['authenticated'])
@wsme_pecan.wsexpose(unicode)
def get(self):
"""Retrieve user config, empty dict if no config exists."""
@ -30,6 +32,7 @@ class ConfigController(rest.RestController):
config = handler.get(user_name)
return config
@util.policy_enforce(['authenticated'])
@wsme_pecan.wsexpose(body=unicode)
def post(self, config):
"""Save user config.

View File

@ -13,6 +13,8 @@
# under the License.
import functools
import pecan
from webob import exc
@ -22,7 +24,8 @@ from surveil.api import rbac
# TODO(aviau && Freddrickk): Properly document this decorator
def policy_enforce(actions):
def policy_enforce_inner(handler):
def handle_stack_method(controller, **kwargs):
@functools.wraps(handler)
def handle_stack_method(*args, **kwargs):
request = pecan.request
for action in actions:
allowed = rbac.enforce(action, request)
@ -30,6 +33,6 @@ def policy_enforce(actions):
if not allowed:
raise exc.HTTPForbidden()
return handler(controller, **kwargs)
return handler(*args, **kwargs)
return handle_stack_method
return policy_enforce_inner

View File

@ -34,15 +34,26 @@ class TestConfigController(functionalTest.FunctionalTest):
)
def test_get_post_get(self):
# At first, conf is empty
response = self.app.get('/v2/bansho/config')
self.assertIsNone(
self.mongoconnection.surveil.bansho.config.find_one(
{"user_name": "surveil-default-user"}
)
)
response = self.get('/v2/bansho/config')
self.assertEqual({}, json.loads(response.body.decode()))
# Now, post config
config = {"key": "val",
"morekey": "moreval"}
self.app.post_json('/v2/bansho/config', params=config)
self.post_json('/v2/bansho/config', params=config)
# Now config is what we gave to the API
response = self.app.get('/v2/bansho/config')
response = self.get('/v2/bansho/config')
self.assertEqual(config, json.loads(response.body.decode()))
self.assertIsNotNone(
self.mongoconnection.surveil.bansho.config.find_one(
{"user_name": "surveil-default-user"}
)
)

View File

@ -75,10 +75,27 @@ class FunctionalTest(base.BaseTestCase):
'app': {
'root': 'surveil.api.controllers.root.RootController',
'modules': ['surveil.api'],
'debug': False,
'debug': True,
'hooks': app_hooks
}
})
self.auth_headers = {
'X-Identity-Status': 'Confirmed',
'X-User-Id': 'surveil-default-user',
'X-Roles': 'admin,surveil',
'X-Service-Catalog': 'surveil',
'X-Service-Identity-Status': 'Confirmed',
'X-Service-Roles': 'surveil',
}
def tearDown(self):
pecan.set_config({}, overwrite=True)
def post_json(self, *args, **kwargs):
kwargs.setdefault('headers', self.auth_headers)
return self.app.post_json(*args, **kwargs)
def get(self, *args, **kwargs):
kwargs.setdefault('headers', self.auth_headers)
return self.app.get(*args, **kwargs)

View File

@ -1,4 +1,10 @@
{
"surveil:break":"!",
"surveil:pass":"@"
"admin_required": "role:admin or is_admin:1",
"surveil_required": "role:surveil",
"surveil:admin": "rule:admin_required",
"surveil:authenticated": "rule:surveil_required",
"surveil:break": "!",
"surveil:pass": "@"
}