Codebase list python-castellan / 147ccb9
Merge "Renames for consistent namespaces" Jenkins authored 9 years ago Gerrit Code Review committed 9 years ago
24 changed file(s) with 714 addition(s) and 714 deletion(s). Raw diff Collapse all Expand all
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 from oslo_config import cfg
16 from oslo_utils import importutils
17
18
19 key_manager_opts = [
20 cfg.StrOpt('api_class',
21 help='The full class name of the key manager API class'),
22 ]
23
24 CONF = cfg.CONF
25 CONF.register_opts(key_manager_opts, group='key_manager')
26
27
28 def API():
29 cls = importutils.import_class(CONF.key_manager.api_class)
30 return cls()
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Base Key and SymmetricKey Classes
17
18 This module defines the Key and SymmetricKey classes. The Key class is the base
19 class to represent all encryption keys. The basis for this class was copied
20 from Java.
21 """
22
23 import abc
24
25 import six
26
27
28 @six.add_metaclass(abc.ABCMeta)
29 class Key(object):
30 """Base class to represent all keys."""
31
32 @abc.abstractmethod
33 def get_algorithm(self):
34 """Returns the key's algorithm.
35
36 Returns the key's algorithm. For example, "DSA" indicates that this key
37 is a DSA key and "AES" indicates that this key is an AES key.
38 """
39 pass
40
41 @abc.abstractmethod
42 def get_format(self):
43 """Returns the encoding format.
44
45 Returns the key's encoding format or None if this key is not encoded.
46 """
47 pass
48
49 @abc.abstractmethod
50 def get_encoded(self):
51 """Returns the key in the format specified by its encoding."""
52 pass
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Key manager API
17 """
18
19 import abc
20
21 import six
22
23
24 @six.add_metaclass(abc.ABCMeta)
25 class KeyManager(object):
26 """Base Key Manager Interface
27
28 A Key Manager is responsible for managing encryption keys for volumes. A
29 Key Manager is responsible for creating, reading, and deleting keys.
30 """
31
32 @abc.abstractmethod
33 def create_key(self, context, algorithm='AES', length=256,
34 expiration=None, **kwargs):
35 """Creates a key.
36
37 This method creates a key and returns the key's UUID. If the specified
38 context does not permit the creation of keys, then a NotAuthorized
39 exception should be raised.
40 """
41 pass
42
43 @abc.abstractmethod
44 def store_key(self, context, key, expiration=None, **kwargs):
45 """Stores (i.e., registers) a key with the key manager.
46
47 This method stores the specified key and returns its UUID that
48 identifies it within the key manager. If the specified context does
49 not permit the creation of keys, then a NotAuthorized exception should
50 be raised.
51 """
52 pass
53
54 @abc.abstractmethod
55 def copy_key(self, context, key_id, **kwargs):
56 """Copies (i.e., clones) a key stored by the key manager.
57
58 This method copies the specified key and returns the copy's UUID. If
59 the specified context does not permit copying keys, then a
60 NotAuthorized error should be raised.
61
62 Implementation note: This method should behave identically to
63 store_key(context, get_key(context, <encryption key UUID>))
64 although it is preferable to perform this operation within the key
65 manager to avoid unnecessary handling of the key material.
66 """
67 pass
68
69 @abc.abstractmethod
70 def get_key(self, context, key_id, **kwargs):
71 """Retrieves the specified key.
72
73 Implementations should verify that the caller has permissions to
74 retrieve the key by checking the context object passed in as context.
75 If the user lacks permission then a NotAuthorized exception is raised.
76
77 If the specified key does not exist, then a KeyError should be raised.
78 Implementations should preclude users from discerning the UUIDs of
79 keys that belong to other users by repeatedly calling this method.
80 That is, keys that belong to other users should be considered "non-
81 existent" and completely invisible.
82 """
83 pass
84
85 @abc.abstractmethod
86 def delete_key(self, context, key_id, **kwargs):
87 """Deletes the specified key.
88
89 Implementations should verify that the caller has permission to delete
90 the key by checking the context object (context). A NotAuthorized
91 exception should be raised if the caller lacks permission.
92
93 If the specified key does not exist, then a KeyError should be raised.
94 Implementations should preclude users from discerning the UUIDs of
95 keys that belong to other users by repeatedly calling this method.
96 That is, keys that belong to other users should be considered "non-
97 existent" and completely invisible.
98 """
99 pass
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Key manager implementation that raises NotImplementedError
17 """
18
19 from castellan.key_manager import key_manager
20
21
22 class NotImplementedKeyManager(key_manager.KeyManager):
23 """Key Manager Interface that raises NotImplementedError for all operations
24
25 """
26
27 def create_key(self, context, algorithm='AES', length=256,
28 expiration=None, **kwargs):
29 raise NotImplementedError()
30
31 def store_key(self, context, key, expiration=None, **kwargs):
32 raise NotImplementedError()
33
34 def copy_key(self, context, key_id, **kwargs):
35 raise NotImplementedError()
36
37 def get_key(self, context, key_id, **kwargs):
38 raise NotImplementedError()
39
40 def delete_key(self, context, key_id, **kwargs):
41 raise NotImplementedError()
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Base SymmetricKey Class
17
18 This module defines the SymmetricKey class.
19 """
20
21 from castellan.key_manager import key
22
23
24 class SymmetricKey(key.Key):
25 """This class represents symmetric keys."""
26
27 def __init__(self, alg, key):
28 """Create a new SymmetricKey object.
29
30 The arguments specify the algorithm for the symmetric encryption and
31 the bytes for the key.
32 """
33 self.alg = alg
34 self.key = key
35
36 def get_algorithm(self):
37 """Returns the algorithm for symmetric encryption."""
38 return self.alg
39
40 def get_format(self):
41 """This method returns 'RAW'."""
42 return "RAW"
43
44 def get_encoded(self):
45 """Returns the key in its encoded format."""
46 return self.key
47
48 def __eq__(self, other):
49 if isinstance(other, SymmetricKey):
50 return (self.alg == other.alg and
51 self.key == other.key)
52 return NotImplemented
53
54 def __ne__(self, other):
55 result = self.__eq__(other)
56 if result is NotImplemented:
57 return result
58 return not result
+0
-31
castellan/keymgr/__init__.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 from oslo_config import cfg
16 from oslo_utils import importutils
17
18
19 keymgr_opts = [
20 cfg.StrOpt('api_class',
21 help='The full class name of the key manager API class'),
22 ]
23
24 CONF = cfg.CONF
25 CONF.register_opts(keymgr_opts, group='keymgr')
26
27
28 def API():
29 cls = importutils.import_class(CONF.keymgr.api_class)
30 return cls()
+0
-53
castellan/keymgr/key.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Base Key and SymmetricKey Classes
17
18 This module defines the Key and SymmetricKey classes. The Key class is the base
19 class to represent all encryption keys. The basis for this class was copied
20 from Java.
21 """
22
23 import abc
24
25 import six
26
27
28 @six.add_metaclass(abc.ABCMeta)
29 class Key(object):
30 """Base class to represent all keys."""
31
32 @abc.abstractmethod
33 def get_algorithm(self):
34 """Returns the key's algorithm.
35
36 Returns the key's algorithm. For example, "DSA" indicates that this key
37 is a DSA key and "AES" indicates that this key is an AES key.
38 """
39 pass
40
41 @abc.abstractmethod
42 def get_format(self):
43 """Returns the encoding format.
44
45 Returns the key's encoding format or None if this key is not encoded.
46 """
47 pass
48
49 @abc.abstractmethod
50 def get_encoded(self):
51 """Returns the key in the format specified by its encoding."""
52 pass
+0
-100
castellan/keymgr/key_mgr.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Key manager API
17 """
18
19 import abc
20
21 import six
22
23
24 @six.add_metaclass(abc.ABCMeta)
25 class KeyManager(object):
26 """Base Key Manager Interface
27
28 A Key Manager is responsible for managing encryption keys for volumes. A
29 Key Manager is responsible for creating, reading, and deleting keys.
30 """
31
32 @abc.abstractmethod
33 def create_key(self, context, algorithm='AES', length=256,
34 expiration=None, **kwargs):
35 """Creates a key.
36
37 This method creates a key and returns the key's UUID. If the specified
38 context does not permit the creation of keys, then a NotAuthorized
39 exception should be raised.
40 """
41 pass
42
43 @abc.abstractmethod
44 def store_key(self, context, key, expiration=None, **kwargs):
45 """Stores (i.e., registers) a key with the key manager.
46
47 This method stores the specified key and returns its UUID that
48 identifies it within the key manager. If the specified context does
49 not permit the creation of keys, then a NotAuthorized exception should
50 be raised.
51 """
52 pass
53
54 @abc.abstractmethod
55 def copy_key(self, context, key_id, **kwargs):
56 """Copies (i.e., clones) a key stored by the key manager.
57
58 This method copies the specified key and returns the copy's UUID. If
59 the specified context does not permit copying keys, then a
60 NotAuthorized error should be raised.
61
62 Implementation note: This method should behave identically to
63 store_key(context, get_key(context, <encryption key UUID>))
64 although it is preferable to perform this operation within the key
65 manager to avoid unnecessary handling of the key material.
66 """
67 pass
68
69 @abc.abstractmethod
70 def get_key(self, context, key_id, **kwargs):
71 """Retrieves the specified key.
72
73 Implementations should verify that the caller has permissions to
74 retrieve the key by checking the context object passed in as context.
75 If the user lacks permission then a NotAuthorized exception is raised.
76
77 If the specified key does not exist, then a KeyError should be raised.
78 Implementations should preclude users from discerning the UUIDs of
79 keys that belong to other users by repeatedly calling this method.
80 That is, keys that belong to other users should be considered "non-
81 existent" and completely invisible.
82 """
83 pass
84
85 @abc.abstractmethod
86 def delete_key(self, context, key_id, **kwargs):
87 """Deletes the specified key.
88
89 Implementations should verify that the caller has permission to delete
90 the key by checking the context object (context). A NotAuthorized
91 exception should be raised if the caller lacks permission.
92
93 If the specified key does not exist, then a KeyError should be raised.
94 Implementations should preclude users from discerning the UUIDs of
95 keys that belong to other users by repeatedly calling this method.
96 That is, keys that belong to other users should be considered "non-
97 existent" and completely invisible.
98 """
99 pass
+0
-42
castellan/keymgr/not_implemented_key_mgr.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Key manager implementation that raises NotImplementedError
17 """
18
19 from castellan.keymgr import key_mgr
20
21
22 class NotImplementedKeyManager(key_mgr.KeyManager):
23 """Key Manager Interface that raises NotImplementedError for all operations
24
25 """
26
27 def create_key(self, context, algorithm='AES', length=256,
28 expiration=None, **kwargs):
29 raise NotImplementedError()
30
31 def store_key(self, context, key, expiration=None, **kwargs):
32 raise NotImplementedError()
33
34 def copy_key(self, context, key_id, **kwargs):
35 raise NotImplementedError()
36
37 def get_key(self, context, key_id, **kwargs):
38 raise NotImplementedError()
39
40 def delete_key(self, context, key_id, **kwargs):
41 raise NotImplementedError()
+0
-59
castellan/keymgr/symmetric_key.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Base SymmetricKey Class
17
18 This module defines the SymmetricKey class.
19 """
20
21 from castellan.keymgr import key
22
23
24 class SymmetricKey(key.Key):
25 """This class represents symmetric keys."""
26
27 def __init__(self, alg, key):
28 """Create a new SymmetricKey object.
29
30 The arguments specify the algorithm for the symmetric encryption and
31 the bytes for the key.
32 """
33 self.alg = alg
34 self.key = key
35
36 def get_algorithm(self):
37 """Returns the algorithm for symmetric encryption."""
38 return self.alg
39
40 def get_format(self):
41 """This method returns 'RAW'."""
42 return "RAW"
43
44 def get_encoded(self):
45 """Returns the key in its encoded format."""
46 return self.key
47
48 def __eq__(self, other):
49 if isinstance(other, SymmetricKey):
50 return (self.alg == other.alg and
51 self.key == other.key)
52 return NotImplemented
53
54 def __ne__(self, other):
55 result = self.__eq__(other)
56 if result is NotImplemented:
57 return result
58 return not result
0 # Copyright 2011 Justin Santa Barbara
1 # Copyright 2012 OpenStack Foundation
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 """Implementation of a fake key manager."""
17
18
19 from castellan.tests.key_manager import mock_key_manager
20
21
22 def fake_api():
23 return mock_key_manager.MockKeyManager()
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 A mock implementation of a key manager that stores keys in a dictionary.
17
18 This key manager implementation is primarily intended for testing. In
19 particular, it does not store keys persistently. Lack of a centralized key
20 store also makes this implementation unsuitable for use among different
21 services.
22
23 Note: Instantiating this class multiple times will create separate key stores.
24 Keys created in one instance will not be accessible from other instances of
25 this class.
26 """
27
28 import array
29 import binascii
30 import random
31 import uuid
32
33 from castellan.common import exception
34 from castellan.key_manager import key_manager
35 from castellan.key_manager import symmetric_key as sym_key
36
37
38 class MockKeyManager(key_manager.KeyManager):
39
40 """Mocking manager for integration tests.
41
42 This mock key manager implementation supports all the methods specified
43 by the key manager interface. This implementation stores keys within a
44 dictionary, and as a result, it is not acceptable for use across different
45 services. Side effects (e.g., raising exceptions) for each method are
46 handled as specified by the key manager interface.
47
48 This key manager is not suitable for use in production deployments.
49 """
50
51 def __init__(self):
52 self.keys = {}
53
54 def _generate_hex_key(self, **kwargs):
55 key_length = kwargs.get('key_length', 256)
56 # hex digit => 4 bits
57 length = int(key_length / 4)
58 hex_encoded = self._generate_password(length=length,
59 symbolgroups='0123456789ABCDEF')
60 return hex_encoded
61
62 def _generate_key(self, **kwargs):
63 _hex = self._generate_hex_key(**kwargs)
64 return sym_key.SymmetricKey(
65 'AES',
66 array.array('B', binascii.unhexlify(_hex)).tolist())
67
68 def create_key(self, context, **kwargs):
69 """Creates a key.
70
71 This implementation returns a UUID for the created key. A
72 Forbidden exception is raised if the specified context is None.
73 """
74 if context is None:
75 raise exception.Forbidden()
76
77 key = self._generate_key(**kwargs)
78 return self.store_key(context, key)
79
80 def _generate_key_id(self):
81 key_id = str(uuid.uuid4())
82 while key_id in self.keys:
83 key_id = str(uuid.uuid4())
84
85 return key_id
86
87 def store_key(self, context, key, **kwargs):
88 """Stores (i.e., registers) a key with the key manager."""
89 if context is None:
90 raise exception.Forbidden()
91
92 key_id = self._generate_key_id()
93 self.keys[key_id] = key
94
95 return key_id
96
97 def copy_key(self, context, key_id, **kwargs):
98 if context is None:
99 raise exception.Forbidden()
100
101 copied_key_id = self._generate_key_id()
102 self.keys[copied_key_id] = self.keys[key_id]
103
104 return copied_key_id
105
106 def get_key(self, context, key_id, **kwargs):
107 """Retrieves the key identified by the specified id.
108
109 This implementation returns the key that is associated with the
110 specified UUID. A Forbidden exception is raised if the specified
111 context is None; a KeyError is raised if the UUID is invalid.
112 """
113 if context is None:
114 raise exception.Forbidden()
115
116 return self.keys[key_id]
117
118 def delete_key(self, context, key_id, **kwargs):
119 """Deletes the key identified by the specified id.
120
121 A Forbidden exception is raised if the context is None and a
122 KeyError is raised if the UUID is invalid.
123 """
124 if context is None:
125 raise exception.Forbidden()
126
127 del self.keys[key_id]
128
129 def _generate_password(self, length, symbolgroups):
130 """Generate a random password from the supplied symbol groups.
131
132 At least one symbol from each group will be included. Unpredictable
133 results if length is less than the number of symbol groups.
134
135 Believed to be reasonably secure (with a reasonable password length!)
136 """
137 # NOTE(jerdfelt): Some password policies require at least one character
138 # from each group of symbols, so start off with one random character
139 # from each symbol group
140 password = [random.choice(s) for s in symbolgroups]
141 # If length < len(symbolgroups), the leading characters will only
142 # be from the first length groups. Try our best to not be predictable
143 # by shuffling and then truncating.
144 random.shuffle(password)
145 password = password[:length]
146 length -= len(password)
147
148 # then fill with random characters from all symbol groups
149 symbols = ''.join(symbolgroups)
150 password.extend([random.choice(symbols) for _i in range(length)])
151
152 # finally shuffle to ensure first x characters aren't from a
153 # predictable group
154 random.shuffle(password)
155
156 return ''.join(password)
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the key classes.
17 """
18
19 import array
20 import binascii
21
22 from castellan.key_manager import symmetric_key as sym_key
23 from castellan.tests import base
24
25
26 class KeyTestCase(base.TestCase):
27
28 def _create_key(self):
29 raise NotImplementedError()
30
31 def setUp(self):
32 super(KeyTestCase, self).setUp()
33
34 self.key = self._create_key()
35
36
37 class SymmetricKeyTestCase(KeyTestCase):
38
39 def _create_key(self):
40 return sym_key.SymmetricKey(self.algorithm, self.encoded)
41
42 def setUp(self):
43 self.algorithm = 'AES'
44 self.encoded = array.array('B', binascii.unhexlify('0' * 64)).tolist()
45
46 super(SymmetricKeyTestCase, self).setUp()
47
48 def test_get_algorithm(self):
49 self.assertEqual(self.key.get_algorithm(), self.algorithm)
50
51 def test_get_format(self):
52 self.assertEqual(self.key.get_format(), 'RAW')
53
54 def test_get_encoded(self):
55 self.assertEqual(self.key.get_encoded(), self.encoded)
56
57 def test___eq__(self):
58 self.assertTrue(self.key == self.key)
59
60 self.assertFalse(self.key is None)
61 self.assertFalse(None == self.key)
62
63 def test___ne__(self):
64 self.assertFalse(self.key != self.key)
65
66 self.assertTrue(self.key is not None)
67 self.assertTrue(None != self.key)
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the key manager.
17 """
18
19 from castellan.tests import base
20
21
22 class KeyManagerTestCase(base.TestCase):
23
24 def _create_key_manager(self):
25 raise NotImplementedError()
26
27 def setUp(self):
28 super(KeyManagerTestCase, self).setUp()
29
30 self.key_mgr = self._create_key_manager()
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the mock key manager.
17 """
18
19 import array
20 import binascii
21
22 from castellan.common import exception
23 from castellan import context
24 from castellan.key_manager import symmetric_key as sym_key
25 from castellan.tests.key_manager import mock_key_manager as mock_key_mgr
26 from castellan.tests.key_manager import test_key_manager as test_key_mgr
27
28
29 class MockKeyManagerTestCase(test_key_mgr.KeyManagerTestCase):
30
31 def _create_key_manager(self):
32 return mock_key_mgr.MockKeyManager()
33
34 def setUp(self):
35 super(MockKeyManagerTestCase, self).setUp()
36
37 self.context = context.RequestContext('fake', 'fake')
38
39 def test_create_key(self):
40 key_id_1 = self.key_mgr.create_key(self.context)
41 key_id_2 = self.key_mgr.create_key(self.context)
42 # ensure that the UUIDs are unique
43 self.assertNotEqual(key_id_1, key_id_2)
44
45 def test_create_key_with_length(self):
46 for length in [64, 128, 256]:
47 key_id = self.key_mgr.create_key(self.context, key_length=length)
48 key = self.key_mgr.get_key(self.context, key_id)
49 self.assertEqual(length / 8, len(key.get_encoded()))
50
51 def test_create_null_context(self):
52 self.assertRaises(exception.Forbidden,
53 self.key_mgr.create_key, None)
54
55 def test_store_and_get_key(self):
56 secret_key = array.array('B', binascii.unhexlify('0' * 64)).tolist()
57 _key = sym_key.SymmetricKey('AES', secret_key)
58 key_id = self.key_mgr.store_key(self.context, _key)
59
60 actual_key = self.key_mgr.get_key(self.context, key_id)
61 self.assertEqual(_key, actual_key)
62
63 def test_store_null_context(self):
64 self.assertRaises(exception.Forbidden,
65 self.key_mgr.store_key, None, None)
66
67 def test_copy_key(self):
68 key_id = self.key_mgr.create_key(self.context)
69 key = self.key_mgr.get_key(self.context, key_id)
70
71 copied_key_id = self.key_mgr.copy_key(self.context, key_id)
72 copied_key = self.key_mgr.get_key(self.context, copied_key_id)
73
74 self.assertNotEqual(key_id, copied_key_id)
75 self.assertEqual(key, copied_key)
76
77 def test_copy_null_context(self):
78 self.assertRaises(exception.Forbidden,
79 self.key_mgr.copy_key, None, None)
80
81 def test_get_null_context(self):
82 self.assertRaises(exception.Forbidden,
83 self.key_mgr.get_key, None, None)
84
85 def test_get_unknown_key(self):
86 self.assertRaises(KeyError, self.key_mgr.get_key, self.context, None)
87
88 def test_delete_key(self):
89 key_id = self.key_mgr.create_key(self.context)
90 self.key_mgr.delete_key(self.context, key_id)
91
92 self.assertRaises(KeyError, self.key_mgr.get_key, self.context,
93 key_id)
94
95 def test_delete_null_context(self):
96 self.assertRaises(exception.Forbidden,
97 self.key_mgr.delete_key, None, None)
98
99 def test_delete_unknown_key(self):
100 self.assertRaises(KeyError, self.key_mgr.delete_key, self.context,
101 None)
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the not implemented key manager.
17 """
18
19 from castellan.key_manager import not_implemented_key_manager
20 from castellan.tests.key_manager import test_key_manager
21
22
23 class NotImplementedKeyManagerTestCase(test_key_manager.KeyManagerTestCase):
24
25 def _create_key_manager(self):
26 return not_implemented_key_manager.NotImplementedKeyManager()
27
28 def test_create_key(self):
29 self.assertRaises(NotImplementedError,
30 self.key_mgr.create_key, None)
31
32 def test_store_key(self):
33 self.assertRaises(NotImplementedError,
34 self.key_mgr.store_key, None, None)
35
36 def test_copy_key(self):
37 self.assertRaises(NotImplementedError,
38 self.key_mgr.copy_key, None, None)
39
40 def test_get_key(self):
41 self.assertRaises(NotImplementedError,
42 self.key_mgr.get_key, None, None)
43
44 def test_delete_key(self):
45 self.assertRaises(NotImplementedError,
46 self.key_mgr.delete_key, None, None)
+0
-0
castellan/tests/keymgr/__init__.py less more
(Empty file)
+0
-24
castellan/tests/keymgr/fake.py less more
0 # Copyright 2011 Justin Santa Barbara
1 # Copyright 2012 OpenStack Foundation
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 """Implementation of a fake key manager."""
17
18
19 from castellan.tests.keymgr import mock_key_mgr
20
21
22 def fake_api():
23 return mock_key_mgr.MockKeyManager()
+0
-157
castellan/tests/keymgr/mock_key_mgr.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 A mock implementation of a key manager that stores keys in a dictionary.
17
18 This key manager implementation is primarily intended for testing. In
19 particular, it does not store keys persistently. Lack of a centralized key
20 store also makes this implementation unsuitable for use among different
21 services.
22
23 Note: Instantiating this class multiple times will create separate key stores.
24 Keys created in one instance will not be accessible from other instances of
25 this class.
26 """
27
28 import array
29 import binascii
30 import random
31 import uuid
32
33 from castellan.common import exception
34 from castellan.keymgr import key_mgr
35 from castellan.keymgr import symmetric_key as sym_key
36
37
38 class MockKeyManager(key_mgr.KeyManager):
39
40 """Mocking manager for integration tests.
41
42 This mock key manager implementation supports all the methods specified
43 by the key manager interface. This implementation stores keys within a
44 dictionary, and as a result, it is not acceptable for use across different
45 services. Side effects (e.g., raising exceptions) for each method are
46 handled as specified by the key manager interface.
47
48 This key manager is not suitable for use in production deployments.
49 """
50
51 def __init__(self):
52 self.keys = {}
53
54 def _generate_hex_key(self, **kwargs):
55 key_length = kwargs.get('key_length', 256)
56 # hex digit => 4 bits
57 length = int(key_length / 4)
58 hex_encoded = self._generate_password(length=length,
59 symbolgroups='0123456789ABCDEF')
60 return hex_encoded
61
62 def _generate_key(self, **kwargs):
63 _hex = self._generate_hex_key(**kwargs)
64 return sym_key.SymmetricKey(
65 'AES',
66 array.array('B', binascii.unhexlify(_hex)).tolist())
67
68 def create_key(self, context, **kwargs):
69 """Creates a key.
70
71 This implementation returns a UUID for the created key. A
72 Forbidden exception is raised if the specified context is None.
73 """
74 if context is None:
75 raise exception.Forbidden()
76
77 key = self._generate_key(**kwargs)
78 return self.store_key(context, key)
79
80 def _generate_key_id(self):
81 key_id = str(uuid.uuid4())
82 while key_id in self.keys:
83 key_id = str(uuid.uuid4())
84
85 return key_id
86
87 def store_key(self, context, key, **kwargs):
88 """Stores (i.e., registers) a key with the key manager."""
89 if context is None:
90 raise exception.Forbidden()
91
92 key_id = self._generate_key_id()
93 self.keys[key_id] = key
94
95 return key_id
96
97 def copy_key(self, context, key_id, **kwargs):
98 if context is None:
99 raise exception.Forbidden()
100
101 copied_key_id = self._generate_key_id()
102 self.keys[copied_key_id] = self.keys[key_id]
103
104 return copied_key_id
105
106 def get_key(self, context, key_id, **kwargs):
107 """Retrieves the key identified by the specified id.
108
109 This implementation returns the key that is associated with the
110 specified UUID. A Forbidden exception is raised if the specified
111 context is None; a KeyError is raised if the UUID is invalid.
112 """
113 if context is None:
114 raise exception.Forbidden()
115
116 return self.keys[key_id]
117
118 def delete_key(self, context, key_id, **kwargs):
119 """Deletes the key identified by the specified id.
120
121 A Forbidden exception is raised if the context is None and a
122 KeyError is raised if the UUID is invalid.
123 """
124 if context is None:
125 raise exception.Forbidden()
126
127 del self.keys[key_id]
128
129 def _generate_password(self, length, symbolgroups):
130 """Generate a random password from the supplied symbol groups.
131
132 At least one symbol from each group will be included. Unpredictable
133 results if length is less than the number of symbol groups.
134
135 Believed to be reasonably secure (with a reasonable password length!)
136 """
137 # NOTE(jerdfelt): Some password policies require at least one character
138 # from each group of symbols, so start off with one random character
139 # from each symbol group
140 password = [random.choice(s) for s in symbolgroups]
141 # If length < len(symbolgroups), the leading characters will only
142 # be from the first length groups. Try our best to not be predictable
143 # by shuffling and then truncating.
144 random.shuffle(password)
145 password = password[:length]
146 length -= len(password)
147
148 # then fill with random characters from all symbol groups
149 symbols = ''.join(symbolgroups)
150 password.extend([random.choice(symbols) for _i in range(length)])
151
152 # finally shuffle to ensure first x characters aren't from a
153 # predictable group
154 random.shuffle(password)
155
156 return ''.join(password)
+0
-68
castellan/tests/keymgr/test_key.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the key classes.
17 """
18
19 import array
20 import binascii
21
22 from castellan.keymgr import symmetric_key as sym_key
23 from castellan.tests import base
24
25
26 class KeyTestCase(base.TestCase):
27
28 def _create_key(self):
29 raise NotImplementedError()
30
31 def setUp(self):
32 super(KeyTestCase, self).setUp()
33
34 self.key = self._create_key()
35
36
37 class SymmetricKeyTestCase(KeyTestCase):
38
39 def _create_key(self):
40 return sym_key.SymmetricKey(self.algorithm, self.encoded)
41
42 def setUp(self):
43 self.algorithm = 'AES'
44 self.encoded = array.array('B', binascii.unhexlify('0' * 64)).tolist()
45
46 super(SymmetricKeyTestCase, self).setUp()
47
48 def test_get_algorithm(self):
49 self.assertEqual(self.key.get_algorithm(), self.algorithm)
50
51 def test_get_format(self):
52 self.assertEqual(self.key.get_format(), 'RAW')
53
54 def test_get_encoded(self):
55 self.assertEqual(self.key.get_encoded(), self.encoded)
56
57 def test___eq__(self):
58 self.assertTrue(self.key == self.key)
59
60 self.assertFalse(self.key is None)
61 self.assertFalse(None == self.key)
62
63 def test___ne__(self):
64 self.assertFalse(self.key != self.key)
65
66 self.assertTrue(self.key is not None)
67 self.assertTrue(None != self.key)
+0
-31
castellan/tests/keymgr/test_key_mgr.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the key manager.
17 """
18
19 from castellan.tests import base
20
21
22 class KeyManagerTestCase(base.TestCase):
23
24 def _create_key_manager(self):
25 raise NotImplementedError()
26
27 def setUp(self):
28 super(KeyManagerTestCase, self).setUp()
29
30 self.key_mgr = self._create_key_manager()
+0
-102
castellan/tests/keymgr/test_mock_key_mgr.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the mock key manager.
17 """
18
19 import array
20 import binascii
21
22 from castellan.common import exception
23 from castellan import context
24 from castellan.keymgr import symmetric_key as sym_key
25 from castellan.tests.keymgr import mock_key_mgr
26 from castellan.tests.keymgr import test_key_mgr
27
28
29 class MockKeyManagerTestCase(test_key_mgr.KeyManagerTestCase):
30
31 def _create_key_manager(self):
32 return mock_key_mgr.MockKeyManager()
33
34 def setUp(self):
35 super(MockKeyManagerTestCase, self).setUp()
36
37 self.context = context.RequestContext('fake', 'fake')
38
39 def test_create_key(self):
40 key_id_1 = self.key_mgr.create_key(self.context)
41 key_id_2 = self.key_mgr.create_key(self.context)
42 # ensure that the UUIDs are unique
43 self.assertNotEqual(key_id_1, key_id_2)
44
45 def test_create_key_with_length(self):
46 for length in [64, 128, 256]:
47 key_id = self.key_mgr.create_key(self.context, key_length=length)
48 key = self.key_mgr.get_key(self.context, key_id)
49 self.assertEqual(length / 8, len(key.get_encoded()))
50
51 def test_create_null_context(self):
52 self.assertRaises(exception.Forbidden,
53 self.key_mgr.create_key, None)
54
55 def test_store_and_get_key(self):
56 secret_key = array.array('B', binascii.unhexlify('0' * 64)).tolist()
57 _key = sym_key.SymmetricKey('AES', secret_key)
58 key_id = self.key_mgr.store_key(self.context, _key)
59
60 actual_key = self.key_mgr.get_key(self.context, key_id)
61 self.assertEqual(_key, actual_key)
62
63 def test_store_null_context(self):
64 self.assertRaises(exception.Forbidden,
65 self.key_mgr.store_key, None, None)
66
67 def test_copy_key(self):
68 key_id = self.key_mgr.create_key(self.context)
69 key = self.key_mgr.get_key(self.context, key_id)
70
71 copied_key_id = self.key_mgr.copy_key(self.context, key_id)
72 copied_key = self.key_mgr.get_key(self.context, copied_key_id)
73
74 self.assertNotEqual(key_id, copied_key_id)
75 self.assertEqual(key, copied_key)
76
77 def test_copy_null_context(self):
78 self.assertRaises(exception.Forbidden,
79 self.key_mgr.copy_key, None, None)
80
81 def test_get_null_context(self):
82 self.assertRaises(exception.Forbidden,
83 self.key_mgr.get_key, None, None)
84
85 def test_get_unknown_key(self):
86 self.assertRaises(KeyError, self.key_mgr.get_key, self.context, None)
87
88 def test_delete_key(self):
89 key_id = self.key_mgr.create_key(self.context)
90 self.key_mgr.delete_key(self.context, key_id)
91
92 self.assertRaises(KeyError, self.key_mgr.get_key, self.context,
93 key_id)
94
95 def test_delete_null_context(self):
96 self.assertRaises(exception.Forbidden,
97 self.key_mgr.delete_key, None, None)
98
99 def test_delete_unknown_key(self):
100 self.assertRaises(KeyError, self.key_mgr.delete_key, self.context,
101 None)
+0
-47
castellan/tests/keymgr/test_not_implemented_key_mgr.py less more
0 # Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # 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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the not implemented key manager.
17 """
18
19 from castellan.keymgr import not_implemented_key_mgr
20 from castellan.tests.keymgr import test_key_mgr
21
22
23 class NotImplementedKeyManagerTestCase(test_key_mgr.KeyManagerTestCase):
24
25 def _create_key_manager(self):
26 return not_implemented_key_mgr.NotImplementedKeyManager()
27
28 def test_create_key(self):
29 self.assertRaises(NotImplementedError,
30 self.key_mgr.create_key, None)
31
32 def test_store_key(self):
33 self.assertRaises(NotImplementedError,
34 self.key_mgr.store_key, None, None)
35
36 def test_copy_key(self):
37 self.assertRaises(NotImplementedError,
38 self.key_mgr.copy_key, None, None)
39
40 def test_get_key(self):
41 self.assertRaises(NotImplementedError,
42 self.key_mgr.get_key, None, None)
43
44 def test_delete_key(self):
45 self.assertRaises(NotImplementedError,
46 self.key_mgr.delete_key, None, None)