Codebase list python-castellan / 3de8dad
Merge "Introduce Castellan Credential Factory" Jenkins authored 8 years ago Gerrit Code Review committed 8 years ago
4 changed file(s) with 366 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
6161
6262 class ManagedObjectNotFoundError(CastellanException):
6363 message = u._("Key not found, uuid: %(uuid)s")
64
65
66 class AuthTypeInvalidError(CastellanException):
67 message = u._("Invalid auth_type was specified, auth_type: %(type)s")
68
69
70 class InsufficientCredentialDataError(CastellanException):
71 message = u._("Insufficient credential data was provided, either "
72 "\"token\" must be set in the passed conf, or a context "
73 "with an \"auth_token\" property must be passed.")
0 # Copyright (c) 2016 IBM
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 # implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """
15 Common utilities for Castellan.
16 """
17
18 from castellan.common.credentials import keystone_password
19 from castellan.common.credentials import keystone_token
20 from castellan.common.credentials import password
21 from castellan.common.credentials import token
22 from castellan.common import exception
23
24 from oslo_config import cfg
25 from oslo_log import log as logging
26
27
28 LOG = logging.getLogger(__name__)
29
30 credential_opts = [
31 # auth_type opt
32 cfg.StrOpt('auth_type', default=None),
33
34 # token opt
35 cfg.StrOpt('token', default=None),
36
37 # password opts
38 cfg.StrOpt('username', default=None),
39 cfg.StrOpt('password', default=None),
40
41 # keystone credential opts
42 cfg.StrOpt('user_id', default=None),
43 cfg.StrOpt('user_domain_id', default=None),
44 cfg.StrOpt('user_domain_name', default=None),
45 cfg.StrOpt('trust_id', default=None),
46 cfg.StrOpt('domain_id', default=None),
47 cfg.StrOpt('domain_name', default=None),
48 cfg.StrOpt('project_id', default=None),
49 cfg.StrOpt('project_name', default=None),
50 cfg.StrOpt('project_domain_id', default=None),
51 cfg.StrOpt('project_domain_name', default=None),
52 cfg.BoolOpt('reauthenticate', default=True)
53 ]
54
55 OPT_GROUP = 'key_manager'
56
57
58 def credential_factory(conf=None, context=None):
59 """This function provides a factory for credentials.
60
61 It is used to create an appropriare credential object
62 from a passed configuration. This should be called before
63 making any calls to a key manager.
64
65 :param conf: Configuration file which this factory method uses
66 to generate a credential object. Note: In the future it will
67 become a required field.
68 :param context: Context used for authentication. It can be used
69 in conjunction with the configuration file. If no conf is passed,
70 then the context object will be converted to a KeystoneToken and
71 returned. If a conf is passed then only the 'token' is grabbed from
72 the context for the authentication types that require a token.
73 :returns: A credential object used for authenticating with the
74 Castellan key manager. Type of credential returned depends on
75 config and/or context passed.
76 """
77 if conf:
78 conf.register_opts(credential_opts, group=OPT_GROUP)
79
80 if conf.key_manager.auth_type == 'token':
81 if conf.key_manager.token:
82 auth_token = conf.key_manager.token
83 elif context:
84 auth_token = context.auth_token
85 else:
86 raise exception.InsufficientCredentialDataError()
87
88 return token.Token(auth_token)
89
90 elif conf.key_manager.auth_type == 'password':
91 return password.Password(
92 conf.key_manager.username,
93 conf.key_manager.password)
94
95 elif conf.key_manager.auth_type == 'keystone_password':
96 return keystone_password.KeystonePassword(
97 conf.key_manager.password,
98 username=conf.key_manager.username,
99 user_id=conf.key_manager.user_id,
100 user_domain_id=conf.key_manager.user_domain_id,
101 user_domain_name=conf.key_manager.user_domain_name,
102 trust_id=conf.key_manager.trust_id,
103 domain_id=conf.key_manager.domain_id,
104 domain_name=conf.key_manager.domain_name,
105 project_id=conf.key_manager.project_id,
106 project_name=conf.key_manager.project_name,
107 project_domain_id=conf.key_manager.domain_id,
108 project_domain_name=conf.key_manager.domain_name,
109 reauthenticate=conf.key_manager.reauthenticate)
110
111 elif conf.key_manager.auth_type == 'keystone_token':
112 if conf.key_manager.token:
113 auth_token = conf.key_manager.token
114 elif context:
115 auth_token = context.auth_token
116 else:
117 raise exception.InsufficientCredentialDataError()
118
119 return keystone_token.KeystoneToken(
120 auth_token,
121 trust_id=conf.key_manager.trust_id,
122 domain_id=conf.key_manager.domain_id,
123 domain_name=conf.key_manager.domain_name,
124 project_id=conf.key_manager.project_id,
125 project_name=conf.key_manager.project_name,
126 project_domain_id=conf.key_manager.domain_id,
127 project_domain_name=conf.key_manager.domain_name,
128 reauthenticate=conf.key_manager.reauthenticate)
129
130 else:
131 LOG.error("Invalid auth_type specified.")
132 raise exception.AuthTypeInvalidError(
133 type=conf.key_manager.auth_type)
134
135 # for compatibility between _TokenData and RequestContext
136 if hasattr(context, 'tenant') and context.tenant:
137 project_id = context.tenant
138 elif hasattr(context, 'project_id') and context.project_id:
139 project_id = context.project_id
140
141 return keystone_token.KeystoneToken(
142 context.auth_token,
143 project_id=project_id)
1919 from castellan.key_manager import barbican_key_manager as bkm
2020 except ImportError:
2121 bkm = None
22 from castellan.common import utils
2223
2324 _DEFAULT_LOG_LEVELS = ['castellan=WARN']
2425
9394
9495 :returns: a list of (group_name, opts) tuples
9596 """
96 opts = [('key_manager', km.key_manager_opts)]
97 key_manager_opts = []
98 key_manager_opts.extend(km.key_manager_opts)
99 key_manager_opts.extend(utils.credential_opts)
100 opts = [('key_manager', key_manager_opts)]
101
97102 if bkm is not None:
98103 opts.append((bkm.BARBICAN_OPT_GROUP, bkm.barbican_opts))
99104 return opts
0 # Copyright (c) 2016 IBM
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 # implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """
15 Test Common utilities for Castellan.
16 """
17
18 from castellan.common import exception
19 from castellan.common import utils
20 from castellan.tests import base
21
22 from oslo_config import cfg
23 from oslo_config import fixture as config_fixture
24 from oslo_context import context
25
26 CONF = cfg.CONF
27
28
29 class TestUtils(base.TestCase):
30
31 def setUp(self):
32 super(TestUtils, self).setUp()
33 self.config_fixture = self.useFixture(config_fixture.Config(CONF))
34 CONF.register_opts(utils.credential_opts, group=utils.OPT_GROUP)
35
36 def test_token_credential(self):
37 token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
38
39 self.config_fixture.config(
40 auth_type='token',
41 token=token_value,
42 group='key_manager'
43 )
44
45 token_context = utils.credential_factory(conf=CONF)
46 token_context_class = token_context.__class__.__name__
47
48 self.assertEqual('Token', token_context_class)
49 self.assertEqual(token_value, token_context.token)
50
51 def test_token_credential_with_context(self):
52 token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
53 ctxt = context.RequestContext(auth_token=token_value)
54
55 self.config_fixture.config(
56 auth_type='token',
57 group='key_manager'
58 )
59
60 token_context = utils.credential_factory(conf=CONF, context=ctxt)
61 token_context_class = token_context.__class__.__name__
62
63 self.assertEqual('Token', token_context_class)
64 self.assertEqual(token_value, token_context.token)
65
66 def test_token_credential_config_override_context(self):
67 ctxt_token_value = '00000000000000000000000000000000'
68 ctxt = context.RequestContext(auth_token=ctxt_token_value)
69
70 conf_token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
71
72 self.config_fixture.config(
73 auth_type='token',
74 token=conf_token_value,
75 group='key_manager'
76 )
77
78 token_context = utils.credential_factory(conf=CONF, context=ctxt)
79 token_context_class = token_context.__class__.__name__
80
81 self.assertEqual('Token', token_context_class)
82 self.assertEqual(conf_token_value, token_context.token)
83
84 def test_token_credential_exception(self):
85 self.config_fixture.config(
86 auth_type='token',
87 group='key_manager'
88 )
89
90 self.assertRaises(exception.InsufficientCredentialDataError,
91 utils.credential_factory,
92 CONF)
93
94 def test_password_credential(self):
95 password_value = 'p4ssw0rd'
96
97 self.config_fixture.config(
98 auth_type='password',
99 password=password_value,
100 group='key_manager'
101 )
102
103 password_context = utils.credential_factory(conf=CONF)
104 password_context_class = password_context.__class__.__name__
105
106 self.assertEqual('Password', password_context_class)
107 self.assertEqual(password_value, password_context.password)
108
109 def test_keystone_token_credential(self):
110 token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
111
112 self.config_fixture.config(
113 auth_type='keystone_token',
114 token=token_value,
115 group='key_manager'
116 )
117
118 ks_token_context = utils.credential_factory(conf=CONF)
119 ks_token_context_class = ks_token_context.__class__.__name__
120
121 self.assertEqual('KeystoneToken', ks_token_context_class)
122 self.assertEqual(token_value, ks_token_context.token)
123
124 def test_keystone_token_credential_with_context(self):
125 token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
126 ctxt = context.RequestContext(auth_token=token_value)
127
128 self.config_fixture.config(
129 auth_type='keystone_token',
130 group='key_manager'
131 )
132
133 ks_token_context = utils.credential_factory(conf=CONF, context=ctxt)
134 ks_token_context_class = ks_token_context.__class__.__name__
135
136 self.assertEqual('KeystoneToken', ks_token_context_class)
137 self.assertEqual(token_value, ks_token_context.token)
138
139 def test_keystone_token_credential_config_override_context(self):
140 ctxt_token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
141 ctxt = context.RequestContext(auth_token=ctxt_token_value)
142
143 conf_token_value = 'ec9799cd921e4e0a8ab6111c08ebf065'
144
145 self.config_fixture.config(
146 auth_type='keystone_token',
147 token=conf_token_value,
148 group='key_manager'
149 )
150
151 ks_token_context = utils.credential_factory(conf=CONF, context=ctxt)
152 ks_token_context_class = ks_token_context.__class__.__name__
153
154 self.assertEqual('KeystoneToken', ks_token_context_class)
155 self.assertEqual(conf_token_value, ks_token_context.token)
156
157 def test_keystone_token_credential_exception(self):
158 self.config_fixture.config(
159 auth_type='keystone_token',
160 group='key_manager'
161 )
162
163 self.assertRaises(exception.InsufficientCredentialDataError,
164 utils.credential_factory,
165 CONF)
166
167 def test_keystone_password_credential(self):
168 password_value = 'p4ssw0rd'
169
170 self.config_fixture.config(
171 auth_type='keystone_password',
172 password=password_value,
173 group='key_manager'
174 )
175
176 ks_password_context = utils.credential_factory(conf=CONF)
177 ks_password_context_class = ks_password_context.__class__.__name__
178
179 self.assertEqual('KeystonePassword', ks_password_context_class)
180 self.assertEqual(password_value, ks_password_context.password)
181
182 def test_oslo_context_to_keystone_token(self):
183 auth_token_value = '16bd612f28ec479b8ffe8e124fc37b43'
184 tenant_value = '00c6ef5ad2984af2acd7d42c299935c0'
185
186 ctxt = context.RequestContext(
187 auth_token=auth_token_value,
188 tenant=tenant_value)
189
190 ks_token_context = utils.credential_factory(context=ctxt)
191 ks_token_context_class = ks_token_context.__class__.__name__
192
193 self.assertEqual('KeystoneToken', ks_token_context_class)
194 self.assertEqual(auth_token_value, ks_token_context.token)
195 self.assertEqual(tenant_value, ks_token_context.project_id)
196
197 def test_invalid_auth_type(self):
198 self.config_fixture.config(
199 auth_type='hotdog',
200 group='key_manager'
201 )
202
203 self.assertRaises(exception.AuthTypeInvalidError,
204 utils.credential_factory,
205 conf=CONF)