Codebase list python-castellan / 986bae0
Merge tag '3.5.0' into debian/victoria castellan 3.5.0 release meta:version: 3.5.0 meta:diff-start: - meta:series: victoria meta:release-type: release meta:pypi: no meta:first: no meta:release:Author: Hervé Beraud <hberaud@redhat.com> meta:release:Commit: Hervé Beraud <hberaud@redhat.com> meta:release:Change-Id: I634e7d331d55fbbd83b1bb7e5059d4be6ec86aaf meta:release:Code-Review+1: Ghanshyam Mann <gmann@ghanshyammann.com> meta:release:Code-Review+2: Sean McGinnis <sean.mcginnis@gmail.com> meta:release:Workflow+1: Sean McGinnis <sean.mcginnis@gmail.com> Thomas Goirand 3 years ago
42 changed file(s) with 372 addition(s) and 149 deletion(s). Raw diff Collapse all Expand all
00 - job:
11 name: castellan-functional-vault
2 parent: openstack-tox-py27
2 parent: openstack-tox-py36
33 description: |
44 Run tox functional-vault target
55 required-projects:
5050 jobs:
5151 - castellan-functional-vault
5252 - castellan-functional-devstack
53 - barbican-simple-crypto-devstack-tempest-castellan-from-git
53 - barbican-tempest-plugin-simple-crypto-castellan-src
5454 gate:
5555 jobs:
5656 - castellan-functional-vault
5757 - castellan-functional-devstack
58 - barbican-simple-crypto-devstack-tempest-castellan-from-git
58 - barbican-tempest-plugin-simple-crypto-castellan-src
5959 templates:
6060 - check-requirements
6161 - openstack-lower-constraints-jobs
62 - openstack-python3-ussuri-jobs
62 - openstack-python3-victoria-jobs
6363 - periodic-stable-jobs
6464 - publish-openstack-docs-pti
6565 - release-notes-jobs-python3
+0
-2
babel.cfg less more
0 [python: **.py]
1
6363 message = _("Key not found, uuid: %(uuid)s")
6464
6565
66 class InvalidManagedObjectDictError(CastellanException):
67 message = _("Dict has no field '%(field)s'.")
68
69
70 class UnknownManagedObjectTypeError(CastellanException):
71 message = _("Type not found, type: %(type)s")
72
73
6674 class AuthTypeInvalidError(CastellanException):
6775 message = _("Invalid auth_type was specified, auth_type: %(type)s")
6876
0 # Licensed under the Apache License, Version 2.0 (the "License"); you may
1 # not use this file except in compliance with the License. You may obtain
2 # a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
9 # License for the specific language governing permissions and limitations
10 # under the License.
11
12 from castellan.common import exception
13 from castellan.common.objects import opaque_data
14 from castellan.common.objects import passphrase
15 from castellan.common.objects import private_key
16 from castellan.common.objects import public_key
17 from castellan.common.objects import symmetric_key
18 from castellan.common.objects import x_509
19
20 _managed_objects_by_type = {
21 cls.managed_type(): cls for cls in [
22 opaque_data.OpaqueData,
23 passphrase.Passphrase,
24 private_key.PrivateKey,
25 public_key.PublicKey,
26 symmetric_key.SymmetricKey,
27 x_509.X509,
28 ]
29 }
30
31
32 def from_dict(obj, id=None):
33 try:
34 managed_object_type = obj["type"]
35 except KeyError:
36 raise exception.InvalidManagedObjectDictError(field="type")
37
38 try:
39 cls = _managed_objects_by_type[managed_object_type]
40 except KeyError:
41 raise exception.UnknownManagedObjectTypeError(type=managed_object_type)
42
43 try:
44 managed_object = cls.from_dict(obj, id)
45 except KeyError as e:
46 raise exception.InvalidManagedObjectDictError(field=str(e))
47
48 return managed_object
2121 """
2222
2323 import abc
24 import binascii
2425
26 from castellan.common.objects import exception
2527 from castellan.common.objects import managed_object
2628
2729
2830 class Key(managed_object.ManagedObject):
2931 """Base class to represent all keys."""
3032
31 @abc.abstractproperty
33 @property
34 @abc.abstractmethod
3235 def algorithm(self):
3336 """Returns the key's algorithm.
3437
3740 """
3841 pass
3942
40 @abc.abstractproperty
43 @property
44 @abc.abstractmethod
4145 def bit_length(self):
4246 """Returns the key's bit length.
4347
4650 the length of the modulus.
4751 """
4852 pass
53
54 def to_dict(self):
55 dict_fields = super().to_dict()
56
57 dict_fields["algorithm"] = self.algorithm
58 dict_fields["bit_length"] = self.bit_length
59
60 return dict_fields
61
62 @classmethod
63 def from_dict(cls, dict_fields, id=None, metadata_only=False):
64 try:
65 value = None
66
67 # NOTE(moguimar): the managed object's value is exported as
68 # a hex string. For now, this is a compatibility thing with
69 # the already existent vault_key_manager backend.
70 if not metadata_only and dict_fields["value"] is not None:
71 value = binascii.unhexlify(dict_fields["value"])
72
73 return cls(
74 algorithm=dict_fields["algorithm"],
75 bit_length=dict_fields["bit_length"],
76 key=value,
77 name=dict_fields["name"],
78 created=dict_fields["created"],
79 id=id,
80 )
81 except KeyError as e:
82 raise exception.InvalidManagedObjectDictError(field=str(e))
1818 This module defines the ManagedObject class. The ManagedObject class
1919 is the base class to represent all objects managed by the key manager.
2020 """
21
2122 import abc
23 import binascii
24
25 from castellan.common import exception
2226
2327
2428 class ManagedObject(object, metaclass=abc.ABCMeta):
6872 """
6973 return self._created
7074
71 @abc.abstractproperty
75 @property
76 @abc.abstractmethod
7277 def format(self):
7378 """Returns the encoding format.
7479
7681 encoded.
7782 """
7883 pass
84
85 @property
86 def value(self):
87 """Returns the managed object value."""
88 return self.get_encoded()
7989
8090 @abc.abstractmethod
8191 def get_encoded(self):
8999 def is_metadata_only(self):
90100 """Returns if the associated object is only metadata or not."""
91101 return self.get_encoded() is None
102
103 @classmethod
104 @abc.abstractmethod
105 def managed_type(cls):
106 """Returns the managed object type identifier.
107
108 Returns the object's type identifier for serialization purpose.
109 """
110 pass
111
112 @classmethod
113 def from_dict(cls, dict_fields, id=None, metadata_only=False):
114 """Returns an instance of this class based on a dict object.
115
116 :param dict_fields: The dictionary containing all necessary params
117 to create one instance.
118 :param id: The optional param 'id' to be passed to the constructor.
119 :param metadata_only: A switch to create an instance with metadata
120 only, without the secret itself.
121 """
122 try:
123 value = None
124
125 # NOTE(moguimar): the managed object's value is exported as
126 # a hex string. For now, this is a compatibility thing with
127 # the already existent vault_key_manager backend.
128 if not metadata_only and dict_fields["value"] is not None:
129 value = binascii.unhexlify(dict_fields["value"])
130
131 return cls(
132 value,
133 name=dict_fields["name"],
134 created=dict_fields["created"],
135 id=id,
136 )
137 except KeyError as e:
138 raise exception.InvalidManagedObjectDictError(field=str(e))
139
140 def to_dict(self, metadata_only=False):
141 """Returns a dict that can be used with the from_dict() method.
142
143 :param metadata_only: A switch to create an dictionary with metadata
144 only, without the secret itself.
145
146 :rtype: dict
147 """
148 value = None
149
150 # NOTE(moguimar): the managed object's value is exported as
151 # a hex string. For now, this is a compatibility thing with
152 # the already existent vault_key_manager backend.
153 if not metadata_only and self.value is not None:
154 value = binascii.hexlify(self.value).decode("utf-8")
155
156 return {
157 "type": self.managed_type(),
158 "name": self.name,
159 "created": self.created,
160 "value": value,
161 }
3030 Expected type for data is a bytestring.
3131 """
3232 self._data = data
33 super(OpaqueData, self).__init__(name=name, created=created, id=id)
33 super().__init__(name=name, created=created, id=id)
34
35 @classmethod
36 def managed_type(cls):
37 return "opaque"
3438
3539 @property
3640 def format(self):
37 """This method returns 'Opaque'."""
3841 return "Opaque"
3942
4043 def get_encoded(self):
41 """Returns the data in its original format."""
4244 return self._data
4345
4446 def __eq__(self, other):
3030 The expected type for the passphrase is a bytestring.
3131 """
3232 self._passphrase = passphrase
33 super(Passphrase, self).__init__(name=name, created=created, id=id)
33 super().__init__(name=name, created=created, id=id)
34
35 @classmethod
36 def managed_type(cls):
37 return "passphrase"
3438
3539 @property
3640 def format(self):
37 """This method returns 'RAW'."""
3841 return "RAW"
3942
4043 def get_encoded(self):
41 """Returns the data in a bytestring."""
4244 return self._passphrase
4345
4446 def __eq__(self, other):
3434 self._alg = algorithm
3535 self._bit_length = bit_length
3636 self._key = key
37 super(PrivateKey, self).__init__(name=name, created=created, id=id)
37 super().__init__(name=name, created=created, id=id)
38
39 @classmethod
40 def managed_type(cls):
41 return "private"
3842
3943 @property
4044 def algorithm(self):
41 """Returns the algorithm for asymmetric encryption."""
4245 return self._alg
4346
4447 @property
4548 def format(self):
46 """This method returns 'PKCS8'."""
4749 return "PKCS8"
4850
4951 @property
5052 def bit_length(self):
51 """Returns the key length."""
5253 return self._bit_length
5354
5455 def get_encoded(self):
55 """Returns the key in DER encoded format."""
5656 return self._key
5757
5858 def __eq__(self, other):
3535 self._alg = algorithm
3636 self._bit_length = bit_length
3737 self._key = key
38 super(PublicKey, self).__init__(name=name, created=created, id=id)
38 super().__init__(name=name, created=created, id=id)
39
40 @classmethod
41 def managed_type(cls):
42 return "public"
3943
4044 @property
4145 def algorithm(self):
42 """Returns the algorithm for asymmetric encryption."""
4346 return self._alg
4447
4548 @property
4649 def format(self):
47 """This method returns 'SubjectPublicKeyInfo'."""
4850 return "SubjectPublicKeyInfo"
4951
5052 def get_encoded(self):
51 """Returns the key in its encoded format."""
5253 return self._key
5354
5455 @property
5556 def bit_length(self):
56 """Returns the key length."""
5757 return self._bit_length
5858
5959 def __eq__(self, other):
3434 self._alg = algorithm
3535 self._bit_length = bit_length
3636 self._key = key
37 super(SymmetricKey, self).__init__(name=name, created=created, id=id)
37 super().__init__(name=name, created=created, id=id)
38
39 @classmethod
40 def managed_type(cls):
41 return "symmetric"
3842
3943 @property
4044 def algorithm(self):
41 """Returns the algorithm for symmetric encryption."""
4245 return self._alg
4346
4447 @property
4548 def format(self):
46 """This method returns 'RAW'."""
4749 return "RAW"
4850
4951 def get_encoded(self):
50 """Returns the key in its encoded format."""
5152 return self._key
5253
5354 @property
5455 def bit_length(self):
55 """Returns the key length."""
5656 return self._bit_length
5757
5858 def __eq__(self, other):
3030 The data should be in a bytestring.
3131 """
3232 self._data = data
33 super(X509, self).__init__(name=name, created=created, id=id)
33 super().__init__(name=name, created=created, id=id)
34
35 @classmethod
36 def managed_type(cls):
37 return "certificate"
3438
3539 @property
3640 def format(self):
37 """This method returns 'X.509'."""
3841 return "X.509"
3942
4043 def get_encoded(self):
41 """Returns the data in its encoded format."""
4244 return self._data
4345
4446 def __eq__(self, other):
192192 return barbican.barbican_endpoint
193193 elif getattr(auth, 'service_catalog', None):
194194 endpoint_data = auth.service_catalog.endpoint_data_for(
195 service_type='key-manager')
195 service_type='key-manager',
196 interface=barbican.barbican_endpoint_type)
196197 return endpoint_data.url
197198 else:
198199 service_parameters = {'service_type': 'key-manager',
4040
4141 _DEFAULT_VAULT_URL = "http://127.0.0.1:8200"
4242 _DEFAULT_MOUNTPOINT = "secret"
43 _DEFAULT_VERSION = 2
4344
4445 _vault_opts = [
4546 cfg.StrOpt('root_token_id',
5253 default=_DEFAULT_MOUNTPOINT,
5354 help='Mountpoint of KV store in Vault to use, for example: '
5455 '{}'.format(_DEFAULT_MOUNTPOINT)),
56 cfg.IntOpt('kv_version',
57 default=_DEFAULT_VERSION,
58 help='Version of KV store in Vault to use, for example: '
59 '{}'.format(_DEFAULT_VERSION)),
5560 cfg.StrOpt('vault_url',
5661 default=_DEFAULT_VAULT_URL,
5762 help='Use this endpoint to connect to Vault, for example: '
9196 self._approle_token_ttl = None
9297 self._approle_token_issue = None
9398 self._kv_mountpoint = self._conf.vault.kv_mountpoint
99 self._kv_version = self._conf.vault.kv_version
94100 self._vault_url = self._conf.vault.vault_url
95101 if self._vault_url.startswith("https://"):
96102 self._verify_server = self._conf.vault.ssl_ca_crt_file or True
97103 else:
98104 self._verify_server = False
99 self._vault_kv_version = None
100105
101106 def _get_url(self):
102107 if not self._vault_url.endswith('/'):
103108 self._vault_url += '/'
104109 return self._vault_url
105110
106 def _get_api_version(self):
107 if self._vault_kv_version:
108 return self._vault_kv_version
109
110 resource_url = '{}v1/sys/internal/ui/mounts/{}'.format(
111 self._get_url(),
112 self._kv_mountpoint
113 )
114 resp = self._do_http_request(self._session.get, resource_url)
115
116 if resp.status_code == requests.codes['not_found']:
117 self._vault_kv_version = '1'
118 else:
119 self._vault_kv_version = resp.json()['data']['options']['version']
120
121 return self._vault_kv_version
122
123111 def _get_resource_url(self, key_id=None):
124112 return '{}v1/{}/{}{}'.format(
125113 self._get_url(),
126114 self._kv_mountpoint,
127115
128 '' if self._get_api_version() == '1' else
116 '' if self._kv_version == 1 else
129117 'data/' if key_id else
130118 'metadata/', # no key_id is for listing and 'data/' doesn't works
131119
172160 if resp.status_code == requests.codes['forbidden']:
173161 raise exception.Forbidden()
174162
175 resp = resp.json()
176 self._cached_approle_token_id = resp['auth']['client_token']
163 resp_data = resp.json()
164
165 if resp.status_code == requests.codes['bad_request']:
166 raise exception.KeyManagerError(', '.join(resp_data['errors']))
167
168 self._cached_approle_token_id = resp_data['auth']['client_token']
177169 self._approle_token_issue = token_issue_utc
178 self._approle_token_ttl = resp['auth']['lease_duration']
170 self._approle_token_ttl = resp_data['auth']['lease_duration']
179171 return {'X-Vault-Token': self._approle_token_id}
180172
181173 return {}
263255 'name': value.name,
264256 'created': value.created
265257 }
266 if self._get_api_version() != '1':
258 if self._kv_version > 1:
267259 record = {'data': record}
268260
269261 self._do_http_request(self._session.post,
308300 raise exception.ManagedObjectNotFoundError(uuid=key_id)
309301
310302 record = resp.json()['data']
311 if self._get_api_version() != '1':
303 if self._kv_version > 1:
312304 record = record['data']
313305
314306 key = None if metadata_only else binascii.unhexlify(record['value'])
116116 self.ks_password_credential)
117117
118118 self.assertFalse(self.ks_password_credential is None)
119 self.assertFalse(None == self.ks_password_credential)
119 self.assertFalse(None == self.ks_password_credential) # noqa: E711
120120
121121 other_ks_password_credential = keystone_password.KeystonePassword(
122122 self.password,
139139
140140 def test___ne___none(self):
141141 self.assertTrue(self.ks_password_credential is not None)
142 self.assertTrue(None != self.ks_password_credential)
142 self.assertTrue(None != self.ks_password_credential) # noqa: E711
143143
144144 def test___ne___password(self):
145145 other_password = "wheresmyCat??"
9292 self.ks_token_credential)
9393
9494 self.assertFalse(self.ks_token_credential is None)
95 self.assertFalse(None == self.ks_token_credential)
95 self.assertFalse(None == self.ks_token_credential) # noqa: E711
9696
9797 other_ks_token_credential = keystone_token.KeystoneToken(
9898 self.token,
111111
112112 def test___ne___none(self):
113113 self.assertTrue(self.ks_token_credential is not None)
114 self.assertTrue(None != self.ks_token_credential)
114 self.assertTrue(None != self.ks_token_credential) # noqa: E711
115115
116116 def test___ne___token(self):
117117 other_token = "5c59e3217d3d4dd297589b297aee2a6f"
4545 self.assertTrue(self.password_credential is self.password_credential)
4646
4747 self.assertFalse(self.password_credential is None)
48 self.assertFalse(None == self.password_credential)
48 self.assertFalse(None == self.password_credential) # noqa: E711
4949
5050 other_password_credential = password.Password(self.username,
5151 self.password)
5454
5555 def test___ne___none(self):
5656 self.assertTrue(self.password_credential is not None)
57 self.assertTrue(None != self.password_credential)
57 self.assertTrue(None != self.password_credential) # noqa: E711
5858
5959 def test___ne___username(self):
6060 other_username = "service"
3838 self.assertTrue(self.token_credential is self.token_credential)
3939
4040 self.assertFalse(self.token_credential is None)
41 self.assertFalse(None == self.token_credential)
41 self.assertFalse(None == self.token_credential) # noqa: E711
4242
4343 other_token_credential = token.Token(self.token)
4444 self.assertTrue(self.token_credential == other_token_credential)
4646
4747 def test___ne___none(self):
4848 self.assertTrue(self.token_credential is not None)
49 self.assertTrue(None != self.token_credential)
49 self.assertTrue(None != self.token_credential) # noqa: E711
5050
5151 def test___ne___token(self):
5252 other_token = "fe32af1fe47e4744a48254e60ae80012"
1616 Test cases for the barbican key manager.
1717 """
1818 import calendar
19 from unittest import mock
1920
2021 from barbicanclient import exceptions as barbican_exceptions
21 import mock
2222 from oslo_utils import timeutils
2323
2424 from castellan.common import exception
1717 """
1818
1919 import binascii
20 import mock
20 from unittest import mock
2121
2222 from oslo_config import cfg
2323
0 # Copyright 2020 Red Hat, Inc.
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 Managed Objects.
17 """
18 from castellan.common import exception
19 from castellan.common import objects
20 from castellan.tests import base
21
22
23 class ManagedObjectFromDictTestCase(base.TestCase):
24 def test_invalid_dict(self):
25 self.assertRaises(
26 exception.InvalidManagedObjectDictError,
27 objects.from_dict,
28 {},
29 )
30
31 def test_unknown_type(self):
32 self.assertRaises(
33 exception.UnknownManagedObjectTypeError,
34 objects.from_dict,
35 {"type": "non-existing-managed-object-type"},
36 )
1515 """
1616 Test cases for the opaque data class.
1717 """
18 from castellan.common import objects
1819 from castellan.common.objects import opaque_data
1920 from castellan.tests import base
2021
6667 self.assertTrue(self.opaque_data is self.opaque_data)
6768
6869 self.assertFalse(self.opaque_data is None)
69 self.assertFalse(None == self.opaque_data)
70 self.assertFalse(None == self.opaque_data) # noqa: E711
7071
7172 other_opaque_data = opaque_data.OpaqueData(self.data)
7273 self.assertTrue(self.opaque_data == other_opaque_data)
7475
7576 def test___ne___none(self):
7677 self.assertTrue(self.opaque_data is not None)
77 self.assertTrue(None != self.opaque_data)
78 self.assertTrue(None != self.opaque_data) # noqa: E711
7879
7980 def test___ne___data(self):
8081 other_opaque = opaque_data.OpaqueData(b'other data', self.name)
8182 self.assertTrue(self.opaque_data != other_opaque)
83
84 def test_to_and_from_dict(self):
85 other = objects.from_dict(self.opaque_data.to_dict())
86 self.assertEqual(self.opaque_data, other)
1515 """
1616 Test cases for the passphrase class.
1717 """
18 from castellan.common import objects
1819 from castellan.common.objects import passphrase
1920 from castellan.tests import base
2021
6667 self.assertTrue(self.passphrase is self.passphrase)
6768
6869 self.assertFalse(self.passphrase is None)
69 self.assertFalse(None == self.passphrase)
70 self.assertFalse(None == self.passphrase) # noqa: E711
7071
7172 other_passphrase = passphrase.Passphrase(self.passphrase_data)
7273 self.assertTrue(self.passphrase == other_passphrase)
7475
7576 def test___ne___none(self):
7677 self.assertTrue(self.passphrase is not None)
77 self.assertTrue(None != self.passphrase)
78 self.assertTrue(None != self.passphrase) # noqa: E711
7879
7980 def test___ne___data(self):
8081 other_phrase = passphrase.Passphrase(b"other passphrase", self.name)
8182 self.assertTrue(self.passphrase != other_phrase)
83
84 def test_to_and_from_dict(self):
85 other = objects.from_dict(self.passphrase.to_dict())
86 self.assertEqual(self.passphrase, other)
1515 """
1616 Test cases for the private key class.
1717 """
18 from castellan.common import objects
1819 from castellan.common.objects import private_key
1920 from castellan.tests import base
2021 from castellan.tests import utils
8283 self.assertTrue(self.key is self.key)
8384
8485 self.assertFalse(self.key is None)
85 self.assertFalse(None == self.key)
86 self.assertFalse(None == self.key) # noqa: E711
8687
8788 other_key = private_key.PrivateKey(self.algorithm,
8889 self.bit_length,
9293
9394 def test___ne___none(self):
9495 self.assertTrue(self.key is not None)
95 self.assertTrue(None != self.key)
96 self.assertTrue(None != self.key) # noqa: E711
9697
9798 def test___ne___algorithm(self):
9899 other_key = private_key.PrivateKey('DSA',
115116 different_encoded,
116117 self.name)
117118 self.assertTrue(self.key != other_key)
119
120 def test_to_and_from_dict(self):
121 other = objects.from_dict(self.key.to_dict())
122 self.assertEqual(self.key, other)
1515 """
1616 Test cases for the public key class.
1717 """
18 from castellan.common import objects
1819 from castellan.common.objects import public_key
1920 from castellan.tests import base
2021 from castellan.tests import utils
8283 self.assertTrue(self.key is self.key)
8384
8485 self.assertFalse(self.key is None)
85 self.assertFalse(None == self.key)
86 self.assertFalse(None == self.key) # noqa: E711
8687
8788 other_key = public_key.PublicKey(self.algorithm,
8889 self.bit_length,
9293
9394 def test___ne___none(self):
9495 self.assertTrue(self.key is not None)
95 self.assertTrue(None != self.key)
96 self.assertTrue(None != self.key) # noqa: E711
9697
9798 def test___ne___algorithm(self):
9899 other_key = public_key.PublicKey('DSA',
115116 different_encoded,
116117 self.name)
117118 self.assertTrue(self.key != other_key)
119
120 def test_to_and_from_dict(self):
121 other = objects.from_dict(self.key.to_dict())
122 self.assertEqual(self.key, other)
1515 """
1616 Test cases for the symmetric key class.
1717 """
18 from castellan.common import objects
1819 from castellan.common.objects import symmetric_key as sym_key
1920 from castellan.tests import base
2021
8182 self.assertTrue(self.key is self.key)
8283
8384 self.assertFalse(self.key is None)
84 self.assertFalse(None == self.key)
85 self.assertFalse(None == self.key) # noqa: E711
8586
8687 other_key = sym_key.SymmetricKey(self.algorithm,
8788 self.bit_length,
9192
9293 def test___ne___none(self):
9394 self.assertTrue(self.key is not None)
94 self.assertTrue(None != self.key)
95 self.assertTrue(None != self.key) # noqa: E711
9596
9697 def test___ne___algorithm(self):
9798 other_key = sym_key.SymmetricKey('DES',
114115 different_encoded,
115116 self.name)
116117 self.assertTrue(self.key != other_key)
118
119 def test_to_and_from_dict(self):
120 other = objects.from_dict(self.key.to_dict())
121 self.assertEqual(self.key, other)
1515 """
1616 Test cases for the X.509 certificate class.
1717 """
18 from castellan.common import objects
1819 from castellan.common.objects import x_509
1920 from castellan.tests import base
2021 from castellan.tests import utils
6667 self.assertTrue(self.cert is self.cert)
6768
6869 self.assertFalse(self.cert is None)
69 self.assertFalse(None == self.cert)
70 self.assertFalse(None == self.cert) # noqa: E711
7071
7172 other_x_509 = x_509.X509(self.data)
7273 self.assertTrue(self.cert == other_x_509)
7475
7576 def test___ne___none(self):
7677 self.assertTrue(self.cert is not None)
77 self.assertTrue(None != self.cert)
78 self.assertTrue(None != self.cert) # noqa: E711
7879
7980 def test___ne___data(self):
8081 other_x509 = x_509.X509(b'\x00\x00\x00', self.name)
8182 self.assertTrue(self.cert != other_x509)
83
84 def test_to_and_from_dict(self):
85 other = objects.from_dict(self.cert.to_dict())
86 self.assertEqual(self.cert, other)
0 sphinx>=1.8.0,!=2.1.0 # BSD
0 sphinx>=2.0.0,!=2.1.0 # BSD
11 sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
2 reno>=2.5.0 # Apache-2.0
3 openstackdocstheme>=1.18.1 # Apache-2.0
2 reno>=3.1.0 # Apache-2.0
3 openstackdocstheme>=2.2.1 # Apache-2.0
4747 add_module_names = True
4848
4949 # The name of the Pygments (syntax highlighting) style to use.
50 pygments_style = 'sphinx'
50 pygments_style = 'native'
5151
5252 # -- Options for HTML output --------------------------------------------------
5353
5858
5959 # Output file base name for HTML help builder.
6060 htmlhelp_basename = '%sdoc' % project
61
62 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
63 # using the given strftime format.
64 # html_last_updated_fmt = '%b %d, %Y'
65 html_last_updated_fmt = '%Y-%m-%d %H:%M'
6661
6762 # Add any paths that contain "extra" files, such as .htaccess or
6863 # robots.txt.
8984 #intersphinx_mapping = {'https://docs.python.org/3/': None}
9085
9186 # -- Options for openstackdocstheme -------------------------------------------
92 repository_name = 'openstack/castellan'
93 bug_project = 'castellan'
94 bug_tag = ''
87 openstackdocs_repo_name = 'openstack/castellan'
88 openstackdocs_pdf_link = True
89 openstackdocs_auto_name = False
90 openstackdocs_bug_project = 'castellan'
91 openstackdocs_bug_tag = ''
0 alabaster==0.7.10
10 appdirs==1.3.0
21 asn1crypto==0.23.0
3 Babel==2.3.4
4 bandit==1.1.0
5 cffi==1.7.0
2 certifi==2020.4.5.2
3 cffi==1.13.2
4 chardet==3.0.4
65 cliff==2.8.0
76 cmd2==0.8.0
87 coverage==4.0
98 cryptography==2.1
109 debtcollector==1.2.0
11 docutils==0.11
12 dulwich==0.15.0
10 entrypoints==0.3
1311 extras==1.0.0
1412 fixtures==3.0.0
15 flake8==2.5.5
13 future==0.18.2
1614 gitdb==0.6.4
1715 GitPython==1.0.1
18 hacking==0.12.0
1916 idna==2.5
20 imagesize==0.7.1
2117 iso8601==0.1.11
22 Jinja2==2.10
2318 keystoneauth1==3.4.0
2419 linecache2==1.0.0
25 MarkupSafe==1.0
26 mccabe==0.2.1
27 mock==2.0.0
2820 monotonic==0.6
2921 mox3==0.20.0
3022 msgpack-python==0.4.0
3931 oslo.utils==3.33.0
4032 oslotest==3.2.0
4133 pbr==2.0.0
42 pep8==1.5.7
4334 pifpaf==0.10.0
4435 prettytable==0.7.2
4536 pycparser==2.18
46 pyflakes==0.8.1
47 Pygments==2.2.0
4837 pyinotify==0.9.6
4938 pyparsing==2.1.0
5039 pyperclip==1.5.27
5746 requests==2.18.0
5847 requestsexceptions==1.2.0
5948 rfc3986==0.3.1
49 six==1.15.0
6050 smmap==0.9.0
61 snowballstemmer==1.2.1
51 stestr==2.0.0
6252 stevedore==1.20.0
63 stestr==2.0.0
53 testrepository==0.0.20
6454 testscenarios==0.4
6555 testtools==2.2.0
6656 traceback2==1.4.0
6757 unittest2==1.1.0
58 urllib3==1.21.1
59 voluptuous==0.11.7
6860 wrapt==1.7.0
6961 xattr==0.9.2
0 ---
1 features:
2 - |
3 Historically, the vault key manager backend converts its managed objects
4 to dictionaries in order to send them as a json object. To promote
5 cross-backend compatibility, suck feature should be migrated to managed
6 objects. Methods from_dict() and to_dict() added to class ManagedObject.
7 The Method from_dict() is a class method to create instances based on a
8 dictionary while the method to_dict() is an instance method to translate
9 an instance to a dictionary.
0 ---
1 fixes:
2 - |
3 In some situations, vault will not provide KV API version in the options
4 structure. Vault documentation [1] doesn't cover cases when KV API version
5 is not provided. A new configuration option, with default value equivalent
6 to the latest KV API version available (kv_version=2) was added to allow
7 precise configuration of the KV API being used.
8
9 [1] https://learn.hashicorp.com/vault/secrets-management/sm-versioned-kv
0 ---
1 fixes:
2 - |
3 ``barbican_endpoint_type`` is now used to retrieve Barbican endpoint URL
4 from service catalog. This config option is set to 'public' by default so
5 it will not change the current behaviour.
5151 master_doc = 'index'
5252
5353 # General information about the project.
54 repository_name = 'openstack/castellan'
55 bug_project = 'castellan'
56 bug_tag = 'doc'
54 openstackdocs_repo_name = 'openstack/castellan'
55 openstackdocs_auto_name = False
56 openstackdocs_bug_project = 'castellan'
57 openstackdocs_bug_tag = 'doc'
5758 project = u'Castellan Release Notes'
5859 copyright = u'2017, Castellan Developers'
5960
9495 # show_authors = False
9596
9697 # The name of the Pygments (syntax highlighting) style to use.
97 pygments_style = 'sphinx'
98 pygments_style = 'native'
9899
99100 # A list of ignored prefixes for module index sorting.
100101 # modindex_common_prefix = []
142143 # .htaccess) here, relative to this directory. These files are copied
143144 # directly to the root of the documentation.
144145 # html_extra_path = []
145
146 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
147 # using the given strftime format.
148 html_last_updated_fmt = '%Y-%m-%d %H:%M'
149146
150147 # If true, SmartyPants will be used to convert quotes and dashes to
151148 # typographically correct entities.
55 :maxdepth: 1
66
77 unreleased
8 ussuri
89 train
910 stein
1011 rocky
0 ===========================
1 Ussuri Series Release Notes
2 ===========================
3
4 .. release-notes::
5 :branch: stable/ussuri
22 # process, which may cause wedges in the gate later.
33
44 pbr!=2.1.0,>=2.0.0 # Apache-2.0
5 Babel!=2.4.0,>=2.3.4 # BSD
65 cryptography>=2.1 # BSD/Apache-2.0
76 python-barbicanclient>=4.5.2 # Apache-2.0
87 oslo.config>=6.4.0 # Apache-2.0
1616 Programming Language :: Python :: 3
1717 Programming Language :: Python :: 3.6
1818 Programming Language :: Python :: 3.7
19 Programming Language :: Python :: 3.8
1920 Programming Language :: Python :: 3 :: Only
2021 Programming Language :: Python :: Implementation :: CPython
2122
3435 castellan.drivers =
3536 barbican = castellan.key_manager.barbican_key_manager:BarbicanKeyManager
3637 vault = castellan.key_manager.vault_key_manager:VaultKeyManager
37
38 [compile_catalog]
39 directory = castellan/locale
40 domain = castellan
41
42 [update_catalog]
43 domain = castellan
44 output_dir = castellan/locale
45 input_file = castellan/locale/castellan.pot
46
47 [extract_messages]
48 keywords = _ gettext ngettext l_ lazy_gettext
49 mapping_file = babel.cfg
50 output_file = castellan/locale/castellan.pot
1212 # See the License for the specific language governing permissions and
1313 # limitations under the License.
1414
15 # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
1615 import setuptools
17
18 # In python < 2.7.4, a lazy loading of package `pbr` will break
19 # setuptools if some other modules registered functions in `atexit`.
20 # solution from: http://bugs.python.org/issue15881#msg170215
21 try:
22 import multiprocessing # noqa
23 except ImportError:
24 pass
2516
2617 setuptools.setup(
2718 setup_requires=['pbr>=2.0.0'],
00 # The order of packages is significant, because pip processes them in the order
11 # of appearance. Changing the order has an impact on the overall integration
22 # process, which may cause wedges in the gate later.
3 hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
3 hacking>=3.0.1,<3.1.0 # Apache-2.0
4 # remove this pyflakes from here once you bump the
5 # hacking to 3.2.0 or above. hacking 3.2.0 takes
6 # care of pyflakes version compatibilty.
7 pyflakes>=2.1.1
48
59 coverage!=4.4,>=4.0 # Apache-2.0
610 python-barbicanclient>=4.5.2 # Apache-2.0
1014 fixtures>=3.0.0 # Apache-2.0/BSD
1115 testscenarios>=0.4 # Apache-2.0/BSD
1216 testtools>=2.2.0 # MIT
13 bandit>=1.1.0,<1.6.0 # Apache-2.0
17 bandit>=1.6.0,<1.7.0 # Apache-2.0
1418 pifpaf>=0.10.0 # Apache-2.0
00 #!/bin/bash
11 set -eux
22 if [ -z "$(which vault)" ]; then
3 VAULT_VERSION=0.10.4
3 VAULT_VERSION=1.4.2
44 SUFFIX=zip
55 case `uname -s` in
66 Darwin)
00 [tox]
11 minversion = 3.1.1
2 envlist = py37,pep8
2 envlist = py38,pep8
33 ignore_basepython_conflict = True
44 skipsdist = True
55
1010 VIRTUAL_ENV={envdir}
1111 OS_TEST_PATH=./castellan/tests/unit
1212 deps =
13 -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/ussuri}
13 -c{env:TOX_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
1414 -r{toxinidir}/requirements.txt
1515 -r{toxinidir}/test-requirements.txt
1616 commands = stestr run --slowest {posargs}
7777
7878 [testenv:functional]
7979 usedevelop = True
80 install_command = pip install -U {opts} {packages}
8180 setenv =
8281 VIRTUAL_ENV={envdir}
8382 OS_TEST_PATH=./castellan/tests/functional
8685 [testenv:functional-vault]
8786 passenv = HOME
8887 usedevelop = True
89 install_command = pip install -U {opts} {packages}
9088 setenv =
9189 VIRTUAL_ENV={envdir}
9290 OS_TEST_PATH=./castellan/tests/functional