Authentication allow now token and keystone together (#26)
This commit is contained in:
parent
3a458da2cb
commit
1728025721
@ -15,6 +15,7 @@
|
||||
import logging
|
||||
|
||||
from almanach import config
|
||||
from almanach.auth.mixed_auth import MixedAuthentication
|
||||
from almanach.auth.keystone_auth import KeystoneAuthentication, KeystoneTokenManagerFactory
|
||||
from almanach.auth.private_key_auth import PrivateKeyAuthentication
|
||||
|
||||
@ -31,6 +32,16 @@ class AuthenticationAdapter(object):
|
||||
auth_url=config.keystone_url(),
|
||||
tenant_name=config.keystone_tenant_name()
|
||||
))
|
||||
elif all(auth_method in config.auth_strategy() for auth_method in ['token', 'keystone']):
|
||||
logging.info("Loading Keystone authentication backend")
|
||||
auths = [PrivateKeyAuthentication(config.auth_private_key()),
|
||||
KeystoneAuthentication(KeystoneTokenManagerFactory(
|
||||
username=config.keystone_username(),
|
||||
password=config.keystone_password(),
|
||||
auth_url=config.keystone_url(),
|
||||
tenant_name=config.keystone_tenant_name()
|
||||
))]
|
||||
return MixedAuthentication(auths)
|
||||
else:
|
||||
logging.info("Loading PrivateKey authentication backend")
|
||||
return PrivateKeyAuthentication(config.auth_private_key())
|
||||
|
32
almanach/auth/mixed_auth.py
Normal file
32
almanach/auth/mixed_auth.py
Normal file
@ -0,0 +1,32 @@
|
||||
# Copyright 2016 Internap.
|
||||
#
|
||||
# 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.
|
||||
import logging
|
||||
from almanach.auth.base_auth import BaseAuth
|
||||
from almanach.common.exceptions.authentication_failure_exception import AuthenticationFailureException
|
||||
|
||||
|
||||
class MixedAuthentication(BaseAuth):
|
||||
def __init__(self, authentication_methods):
|
||||
self.authentication_methods = authentication_methods
|
||||
|
||||
def validate(self, token):
|
||||
for method in self.authentication_methods:
|
||||
try:
|
||||
valid = method.validate(token)
|
||||
if valid:
|
||||
logging.debug('Validated token with auth {0}'.format(method.__class__))
|
||||
return True
|
||||
except AuthenticationFailureException:
|
||||
logging.debug('Failed to validate with auth {0}'.format(method.__class__))
|
||||
raise AuthenticationFailureException('No valid auth method matching token')
|
@ -20,11 +20,11 @@ from hamcrest import instance_of, assert_that
|
||||
from almanach import config
|
||||
from almanach.adapters.auth_adapter import AuthenticationAdapter
|
||||
from almanach.auth.keystone_auth import KeystoneAuthentication
|
||||
from almanach.auth.mixed_auth import MixedAuthentication
|
||||
from almanach.auth.private_key_auth import PrivateKeyAuthentication
|
||||
|
||||
|
||||
class AuthenticationAdapterTest(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
flexmock_teardown()
|
||||
|
||||
@ -36,3 +36,8 @@ class AuthenticationAdapterTest(unittest.TestCase):
|
||||
flexmock(config).should_receive("auth_strategy").and_return("keystone")
|
||||
adapter = AuthenticationAdapter().factory()
|
||||
assert_that(adapter, instance_of(KeystoneAuthentication))
|
||||
|
||||
def test_get_mixed_auth_backend(self):
|
||||
flexmock(config).should_receive("auth_strategy").and_return("token,keystone")
|
||||
adapter = AuthenticationAdapter().factory()
|
||||
assert_that(adapter, instance_of(MixedAuthentication))
|
||||
|
48
tests/auth/test_mixed_auth.py
Normal file
48
tests/auth/test_mixed_auth.py
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright 2016 Internap.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import unittest
|
||||
|
||||
from flexmock import flexmock, flexmock_teardown
|
||||
from hamcrest import raises, assert_that, calling, equal_to
|
||||
|
||||
from almanach.auth.mixed_auth import MixedAuthentication
|
||||
from almanach.common.exceptions.authentication_failure_exception import AuthenticationFailureException
|
||||
|
||||
|
||||
class MixedAuthenticationTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.auth_one = flexmock()
|
||||
self.auth_two = flexmock()
|
||||
self.auth_backend = MixedAuthentication([self.auth_one, self.auth_two])
|
||||
|
||||
def tearDown(self):
|
||||
flexmock_teardown()
|
||||
|
||||
def test_with_token_valid_with_auth_one(self):
|
||||
token = "my token"
|
||||
self.auth_one.should_receive("validate").and_return(True)
|
||||
assert_that(self.auth_backend.validate(token), equal_to(True))
|
||||
|
||||
def test_with_token_valid_with_auth_two(self):
|
||||
token = "my token"
|
||||
self.auth_one.should_receive("validate").and_raise(AuthenticationFailureException)
|
||||
self.auth_two.should_receive("validate").and_return(True)
|
||||
assert_that(self.auth_backend.validate(token), equal_to(True))
|
||||
|
||||
def test_with_token_valid_with_auth_twos(self):
|
||||
token = "bad token"
|
||||
self.auth_one.should_receive("validate").and_raise(AuthenticationFailureException)
|
||||
self.auth_two.should_receive("validate").and_raise(AuthenticationFailureException)
|
||||
assert_that(calling(self.auth_backend.validate).with_args(token), raises(AuthenticationFailureException))
|
Loading…
x
Reference in New Issue
Block a user