Skip to content
This repository was archived by the owner on Jun 30, 2018. It is now read-only.

Commit 1728025

Browse files
Marx314maxc0c0s
authored andcommitted
Authentication allow now token and keystone together (#26)
1 parent 3a458da commit 1728025

File tree

4 files changed

+97
-1
lines changed

4 files changed

+97
-1
lines changed

almanach/adapters/auth_adapter.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import logging
1616

1717
from almanach import config
18+
from almanach.auth.mixed_auth import MixedAuthentication
1819
from almanach.auth.keystone_auth import KeystoneAuthentication, KeystoneTokenManagerFactory
1920
from almanach.auth.private_key_auth import PrivateKeyAuthentication
2021

@@ -31,6 +32,16 @@ def factory():
3132
auth_url=config.keystone_url(),
3233
tenant_name=config.keystone_tenant_name()
3334
))
35+
elif all(auth_method in config.auth_strategy() for auth_method in ['token', 'keystone']):
36+
logging.info("Loading Keystone authentication backend")
37+
auths = [PrivateKeyAuthentication(config.auth_private_key()),
38+
KeystoneAuthentication(KeystoneTokenManagerFactory(
39+
username=config.keystone_username(),
40+
password=config.keystone_password(),
41+
auth_url=config.keystone_url(),
42+
tenant_name=config.keystone_tenant_name()
43+
))]
44+
return MixedAuthentication(auths)
3445
else:
3546
logging.info("Loading PrivateKey authentication backend")
3647
return PrivateKeyAuthentication(config.auth_private_key())

almanach/auth/mixed_auth.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2016 Internap.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import logging
15+
from almanach.auth.base_auth import BaseAuth
16+
from almanach.common.exceptions.authentication_failure_exception import AuthenticationFailureException
17+
18+
19+
class MixedAuthentication(BaseAuth):
20+
def __init__(self, authentication_methods):
21+
self.authentication_methods = authentication_methods
22+
23+
def validate(self, token):
24+
for method in self.authentication_methods:
25+
try:
26+
valid = method.validate(token)
27+
if valid:
28+
logging.debug('Validated token with auth {0}'.format(method.__class__))
29+
return True
30+
except AuthenticationFailureException:
31+
logging.debug('Failed to validate with auth {0}'.format(method.__class__))
32+
raise AuthenticationFailureException('No valid auth method matching token')

tests/adapters/test_auth_adapter.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
from almanach import config
2121
from almanach.adapters.auth_adapter import AuthenticationAdapter
2222
from almanach.auth.keystone_auth import KeystoneAuthentication
23+
from almanach.auth.mixed_auth import MixedAuthentication
2324
from almanach.auth.private_key_auth import PrivateKeyAuthentication
2425

2526

2627
class AuthenticationAdapterTest(unittest.TestCase):
27-
2828
def tearDown(self):
2929
flexmock_teardown()
3030

@@ -36,3 +36,8 @@ def test_get_keystone_auth_backend(self):
3636
flexmock(config).should_receive("auth_strategy").and_return("keystone")
3737
adapter = AuthenticationAdapter().factory()
3838
assert_that(adapter, instance_of(KeystoneAuthentication))
39+
40+
def test_get_mixed_auth_backend(self):
41+
flexmock(config).should_receive("auth_strategy").and_return("token,keystone")
42+
adapter = AuthenticationAdapter().factory()
43+
assert_that(adapter, instance_of(MixedAuthentication))

tests/auth/test_mixed_auth.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2016 Internap.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import unittest
16+
17+
from flexmock import flexmock, flexmock_teardown
18+
from hamcrest import raises, assert_that, calling, equal_to
19+
20+
from almanach.auth.mixed_auth import MixedAuthentication
21+
from almanach.common.exceptions.authentication_failure_exception import AuthenticationFailureException
22+
23+
24+
class MixedAuthenticationTest(unittest.TestCase):
25+
def setUp(self):
26+
self.auth_one = flexmock()
27+
self.auth_two = flexmock()
28+
self.auth_backend = MixedAuthentication([self.auth_one, self.auth_two])
29+
30+
def tearDown(self):
31+
flexmock_teardown()
32+
33+
def test_with_token_valid_with_auth_one(self):
34+
token = "my token"
35+
self.auth_one.should_receive("validate").and_return(True)
36+
assert_that(self.auth_backend.validate(token), equal_to(True))
37+
38+
def test_with_token_valid_with_auth_two(self):
39+
token = "my token"
40+
self.auth_one.should_receive("validate").and_raise(AuthenticationFailureException)
41+
self.auth_two.should_receive("validate").and_return(True)
42+
assert_that(self.auth_backend.validate(token), equal_to(True))
43+
44+
def test_with_token_valid_with_auth_twos(self):
45+
token = "bad token"
46+
self.auth_one.should_receive("validate").and_raise(AuthenticationFailureException)
47+
self.auth_two.should_receive("validate").and_raise(AuthenticationFailureException)
48+
assert_that(calling(self.auth_backend.validate).with_args(token), raises(AuthenticationFailureException))

0 commit comments

Comments
 (0)