barbican  12.0.0
About: OpenStack Barbican is the OpenStack Key Manager service. It provides secure storage, provisioning and management of secret data.
The "Wallaby" series (latest release).
  Fossies Dox: barbican-12.0.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

base.py
Go to the documentation of this file.
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 import abc
15 
16 from barbican.common import exception
17 from barbican import i18n as u
18 
19 
20 class CryptoPluginNotFound(exception.BarbicanException):
21  """Raised when no plugins are installed."""
22  message = u._("Crypto plugin not found.")
23 
24 
25 class CryptoKEKBindingException(exception.BarbicanException):
26  """Raised when the bind_kek_metadata method from a plugin returns None."""
27  def __init__(self, plugin_name=u._('Unknown')):
28  super(CryptoKEKBindingException, self).__init__(
29  u._('Failed to bind kek metadata for '
30  'plugin: {name}').format(name=plugin_name)
31  )
32  self.plugin_nameplugin_name = plugin_name
33 
34 
35 class CryptoPrivateKeyFailureException(exception.BarbicanException):
36  """Raised when could not generate private key."""
37  def __init__(self):
38  super(CryptoPrivateKeyFailureException, self).__init__(
39  u._('Could not generate private key')
40  )
41 
42 
43 class CryptoPluginUnsupportedOperation(exception.BarbicanException):
44  """Raised when no crypto plugins support the operation."""
45  def __init__(self, operation):
46  message = (
47  u._('Could not find an enabled crypto plugin backend '
48  'that supports the requested operation: {operation}')
49  .format(operation=operation))
50  super(CryptoPluginUnsupportedOperation, self).__init__(message)
51 
52 
53 # TODO(john-wood-w) Need to harmonize these lower-level constants with the
54 # higher level constants in secret_store.py.
55 class PluginSupportTypes(object):
56  """Class to hold the type enumeration that plugins may support."""
57  ENCRYPT_DECRYPT = "ENCRYPT_DECRYPT"
58  SYMMETRIC_KEY_GENERATION = "SYMMETRIC_KEY_GENERATION"
59  # A list of symmetric algorithms that are used to determine type of key gen
60  SYMMETRIC_ALGORITHMS = ['aes', 'des', '3des', 'hmacsha1',
61  'hmacsha256', 'hmacsha384', 'hmacsha512']
62  SYMMETRIC_KEY_LENGTHS = [64, 128, 192, 256]
63 
64  ASYMMETRIC_KEY_GENERATION = "ASYMMETRIC_KEY_GENERATION"
65  ASYMMETRIC_ALGORITHMS = ['rsa', 'dsa']
66  ASYMMETRIC_KEY_LENGTHS = [1024, 2048, 4096]
67 
68 
69 class KEKMetaDTO(object):
70  """Key Encryption Key Meta DTO
71 
72  Key Encryption Keys (KEKs) in Barbican are intended to represent a
73  distinct key that is used to perform encryption on secrets for a particular
74  project.
75 
76  ``KEKMetaDTO`` objects are provided to cryptographic backends by Barbican
77  to allow plugins to persist metadata related to the project's KEK.
78 
79  For example, a plugin that interfaces with a Hardware Security Module (HSM)
80  may want to use a different encryption key for each project. Such a plugin
81  could use the ``KEKMetaDTO`` object to save the key ID used for that
82  project. Barbican will persist the KEK metadata and ensure that it is
83  provided to the plugin every time a request from that same project is
84  processed.
85 
86  .. attribute:: plugin_name
87 
88  String attribute used by Barbican to identify the plugin that is bound
89  to the KEK metadata. Plugins should not change this attribute.
90 
91  .. attribute:: kek_label
92 
93  String attribute used to label the project's KEK by the plugin.
94  The value of this attribute should be meaningful to the plugin.
95  Barbican does not use this value.
96 
97  .. attribute:: algorithm
98 
99  String attribute used to identify the encryption algorithm used by the
100  plugin. e.g. "AES", "3DES", etc. This value should be meaningful to
101  the plugin. Barbican does not use this value.
102 
103  .. attribute:: mode
104 
105  String attribute used to identify the algorithm mode used by the
106  plugin. e.g. "CBC", "GCM", etc. This value should be meaningful to
107  the plugin. Barbican does not use this value.
108 
109  .. attribute:: bit_length
110 
111  Integer attribute used to identify the bit length of the KEK by the
112  plugin. This value should be meaningful to the plugin. Barbican does
113  not use this value.
114 
115  .. attribute:: plugin_meta
116 
117  String attribute used to persist any additional metadata that does not
118  fit in any other attribute. The value of this attribute is defined by
119  the plugin. It could be used to store external system references, such
120  as Key IDs in an HSM, URIs to an external service, or any other data
121  that the plugin deems necessary to persist. Because this is just a
122  plain text field, a plug in may even choose to persist data such as key
123  value pairs in a JSON object.
124  """
125 
126  def __init__(self, kek_datum):
127  """Plugins should not have to create their own instance of this class.
128 
129  kek_datum is typically a barbican.model.models.KEKDatum instance.
130  """
131  self.kek_labelkek_label = kek_datum.kek_label
132  self.plugin_nameplugin_name = kek_datum.plugin_name
133  self.algorithmalgorithm = kek_datum.algorithm
134  self.bit_lengthbit_length = kek_datum.bit_length
135  self.modemode = kek_datum.mode
136  self.plugin_metaplugin_meta = kek_datum.plugin_meta
137 
138 
139 class GenerateDTO(object):
140  """Secret Generation DTO
141 
142  Data Transfer Object used to pass all the necessary data for the plugin
143  to generate a secret on behalf of the user.
144 
145  .. attribute:: generation_type
146 
147  String attribute used to identify the type of secret that should be
148  generated. This will be either ``"symmetric"`` or ``"asymmetric"``.
149 
150  .. attribute:: algorithm
151 
152  String attribute used to specify what type of algorithm the secret will
153  be used for. e.g. ``"AES"`` for a ``"symmetric"`` type, or ``"RSA"``
154  for ``"asymmetric"``.
155 
156  .. attribute:: mode
157 
158  String attribute used to specify what algorithm mode the secret will be
159  used for. e.g. ``"CBC"`` for ``"AES"`` algorithm.
160 
161  .. attribute:: bit_length
162 
163  Integer attribute used to specify the bit length of the secret. For
164  example, this attribute could specify the key length for an encryption
165  key to be used in AES-CBC.
166  """
167 
168  def __init__(self, algorithm, bit_length, mode, passphrase=None):
169  self.algorithmalgorithm = algorithm
170  self.bit_lengthbit_length = bit_length
171  self.modemode = mode
172  self.passphrasepassphrase = passphrase
173 
174 
175 class ResponseDTO(object):
176  """Data transfer object for secret generation response.
177 
178  Barbican guarantees that both the ``cypher_text`` and
179  ``kek_metadata_extended`` will be persisted and then given back to
180  the plugin when requesting a decryption operation.
181 
182  ``kek_metadata_extended`` takes the idea of Key Encryption Key
183  (KEK) metadata further by giving plugins the option to store
184  secret-level KEK metadata. One example of using secret-level KEK
185  metadata would be plugins that want to use a unique KEK for every
186  secret that is encrypted. Such a plugin could use
187  ``kek_metadata_extended`` to store the Key ID for the KEK used to
188  encrypt this particular secret.
189 
190  :param cypher_text: Byte data resulting from the encryption of the
191  secret data.
192  :param kek_meta_extended: Optional String object to be persisted alongside
193  the cyphertext.
194  """
195  def __init__(self, cypher_text, kek_meta_extended=None):
196  self.cypher_textcypher_text = cypher_text
197  self.kek_meta_extendedkek_meta_extended = kek_meta_extended
198 
199 
200 class DecryptDTO(object):
201  """Secret Decryption DTO
202 
203  Data Transfer Object used to pass all the necessary data for the plugin
204  to perform decryption of a secret.
205 
206  Currently, this DTO only contains the data produced by the plugin during
207  encryption, but in the future this DTO will contain more information, such
208  as a transport key for secret wrapping back to the client.
209 
210  .. attribute:: encrypted
211 
212  The data that was produced by the plugin during encryption. For some
213  plugins this will be the actual bytes that need to be decrypted to
214  produce the secret. In other implementations, this may just be a
215  reference to some external system that can produce the unencrypted
216  secret.
217  """
218 
219  def __init__(self, encrypted):
220  self.encryptedencrypted = encrypted
221 
222 
223 class EncryptDTO(object):
224  """Secret Encryption DTO
225 
226  Data Transfer Object used to pass all the necessary data for the plugin
227  to perform encryption of a secret.
228 
229  Currently, this DTO only contains the raw bytes to be encrypted by the
230  plugin, but in the future this may contain more information.
231 
232  .. attribute:: unencrypted
233 
234  The secret data in Bytes to be encrypted by the plugin.
235  """
236 
237  def __init__(self, unencrypted):
238  self.unencryptedunencrypted = unencrypted
239 
240 
241 class CryptoPluginBase(object, metaclass=abc.ABCMeta):
242  """Base class for all Crypto plugins.
243 
244  Barbican requests operations by invoking the methods on an instance of the
245  implementing class. Barbican's plugin manager handles the life-cycle of
246  the Data Transfer Objects (DTOs) that are passed into these methods, and
247  persist the data that is assigned to these DTOs by the plugin.
248  """
249 
250  @abc.abstractmethod
251  def get_plugin_name(self):
252  """Gets user friendly plugin name.
253 
254  This plugin name is expected to be read from config file.
255  There will be a default defined for plugin name which can be customized
256  in specific deployment if needed.
257 
258  This name needs to be unique across a deployment.
259  """
260  raise NotImplementedError # pragma: no cover
261 
262  @abc.abstractmethod
263  def encrypt(self, encrypt_dto, kek_meta_dto, project_id):
264  """Encryption handler function
265 
266  This method will be called by Barbican when requesting an encryption
267  operation on a secret on behalf of a project.
268 
269  :param encrypt_dto: :class:`EncryptDTO` instance containing the raw
270  secret byte data to be encrypted.
271  :type encrypt_dto: :class:`EncryptDTO`
272  :param kek_meta_dto: :class:`KEKMetaDTO` instance containing
273  information about the project's Key Encryption Key (KEK) to be
274  used for encryption. Plugins may assume that binding via
275  :meth:`bind_kek_metadata` has already taken place before this
276  instance is passed in.
277  :type kek_meta_dto: :class:`KEKMetaDTO`
278  :param project_id: Project ID associated with the unencrypted data.
279  :return: A response DTO containing the cyphertext and KEK information.
280  :rtype: :class:`ResponseDTO`
281  """
282  raise NotImplementedError # pragma: no cover
283 
284  @abc.abstractmethod
285  def decrypt(self, decrypt_dto, kek_meta_dto, kek_meta_extended,
286  project_id):
287  """Decrypt encrypted_datum in the context of the provided project.
288 
289  :param decrypt_dto: data transfer object containing the cyphertext
290  to be decrypted.
291  :param kek_meta_dto: Key encryption key metadata to use for decryption
292  :param kek_meta_extended: Optional per-secret KEK metadata to use for
293  decryption.
294  :param project_id: Project ID associated with the encrypted datum.
295  :returns: str -- unencrypted byte data
296 
297  """
298  raise NotImplementedError # pragma: no cover
299 
300  @abc.abstractmethod
301  def bind_kek_metadata(self, kek_meta_dto):
302  """Key Encryption Key Metadata binding function
303 
304  Bind a key encryption key (KEK) metadata to the sub-system
305  handling encryption/decryption, updating information about the
306  key encryption key (KEK) metadata in the supplied 'kek_metadata'
307  data-transfer-object instance, and then returning this instance.
308 
309  This method is invoked prior to the encrypt() method above.
310  Implementors should fill out the supplied 'kek_meta_dto' instance
311  (an instance of KEKMetadata above) as needed to completely describe
312  the kek metadata and to complete the binding process. Barbican will
313  persist the contents of this instance once this method returns.
314 
315  :param kek_meta_dto: Key encryption key metadata to bind, with the
316  'kek_label' attribute guaranteed to be unique, and the
317  and 'plugin_name' attribute already configured.
318  :returns: kek_meta_dto: Returns the specified DTO, after
319  modifications.
320  """
321  raise NotImplementedError # pragma: no cover
322 
323  @abc.abstractmethod
324  def generate_symmetric(self, generate_dto, kek_meta_dto, project_id):
325  """Generate a new key.
326 
327  :param generate_dto: data transfer object for the record
328  associated with this generation request. Some relevant
329  parameters can be extracted from this object, including
330  bit_length, algorithm and mode
331  :param kek_meta_dto: Key encryption key metadata to use for decryption
332  :param project_id: Project ID associated with the data.
333  :returns: An object of type ResponseDTO containing encrypted data and
334  kek_meta_extended, the former the resultant cypher text, the latter
335  being optional per-secret metadata needed to decrypt (over and
336  above the per-project metadata managed outside of the plugins)
337  """
338  raise NotImplementedError # pragma: no cover
339 
340  @abc.abstractmethod
341  def generate_asymmetric(self, generate_dto, kek_meta_dto, project_id):
342  """Create a new asymmetric key.
343 
344  :param generate_dto: data transfer object for the record
345  associated with this generation request. Some relevant
346  parameters can be extracted from this object, including
347  bit_length, algorithm and passphrase
348  :param kek_meta_dto: Key encryption key metadata to use for decryption
349  :param project_id: Project ID associated with the data.
350  :returns: A tuple containing objects for private_key, public_key and
351  optionally one for passphrase. The objects will be of type
352  ResponseDTO.
353  Each object containing encrypted data and kek_meta_extended, the
354  former the resultant cypher text, the latter being optional
355  per-secret metadata needed to decrypt (over and above the
356  per-project metadata managed outside of the plugins)
357  """
358  raise NotImplementedError # pragma: no cover
359 
360  @abc.abstractmethod
361  def supports(self, type_enum, algorithm=None, bit_length=None, mode=None):
362  """Used to determine if the plugin supports the requested operation.
363 
364  :param type_enum: Enumeration from PluginSupportsType class
365  :param algorithm: String algorithm name if needed
366  """
367  raise NotImplementedError # pragma: no cover
def __init__(self, plugin_name=u._('Unknown'))
Definition: base.py:27
def bind_kek_metadata(self, kek_meta_dto)
Definition: base.py:301
def generate_symmetric(self, generate_dto, kek_meta_dto, project_id)
Definition: base.py:324
def supports(self, type_enum, algorithm=None, bit_length=None, mode=None)
Definition: base.py:361
def decrypt(self, decrypt_dto, kek_meta_dto, kek_meta_extended, project_id)
Definition: base.py:286
def generate_asymmetric(self, generate_dto, kek_meta_dto, project_id)
Definition: base.py:341
def encrypt(self, encrypt_dto, kek_meta_dto, project_id)
Definition: base.py:263
def __init__(self, encrypted)
Definition: base.py:219
def __init__(self, unencrypted)
Definition: base.py:237
def __init__(self, algorithm, bit_length, mode, passphrase=None)
Definition: base.py:168
def __init__(self, kek_datum)
Definition: base.py:126
def __init__(self, cypher_text, kek_meta_extended=None)
Definition: base.py:195