diff --git a/heat/common/crypt.py b/heat/common/crypt.py index 369be6cb7a..a4b7a9b53a 100644 --- a/heat/common/crypt.py +++ b/heat/common/crypt.py @@ -18,9 +18,9 @@ from Crypto.Cipher import AES from cryptography import fernet from oslo_config import cfg from oslo_utils import encodeutils +from oslo_utils import importutils from heat.common.i18n import _ -from heat.openstack.common.crypto import utils auth_opts = [ cfg.StrOpt('auth_encryption_key', @@ -33,6 +33,46 @@ auth_opts = [ cfg.CONF.register_opts(auth_opts) +class SymmetricCrypto(object): + """Symmetric Key Crypto object. + + This class creates a Symmetric Key Crypto object that can be used + to decrypt arbitrary data. + + Note: This is moved here from oslo-incubator for backward + compatibility. Once we've db migration script available to + re-rencrypt using new encryption method as part of upgrade, + this can be removed. + + :param enctype: Encryption Cipher name (default: AES) + """ + + def __init__(self, enctype='AES'): + self.cipher = importutils.import_module('Crypto.Cipher.' + enctype) + + def decrypt(self, key, msg, b64decode=True): + """Decrypts the provided ciphertext. + + The ciphertext can be optionally base64 encoded. + + Uses AES-128-CBC with an IV by default. + + :param key: The Encryption key. + :param msg: the ciphetext, the first block is the IV + + :returns plain: the plaintext message, after padding is removed. + """ + if b64decode: + msg = base64.b64decode(msg) + iv = msg[:self.cipher.block_size] + cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv) + + padded = cipher.decrypt(msg[self.cipher.block_size:]) + l = ord(padded[-1:]) + 1 + plain = padded[:-l] + return plain + + def encrypt(value, encryption_key=None): if value is None: return None, None @@ -54,9 +94,8 @@ def decrypt(method, data, encryption_key=None): def oslo_decrypt_v1(value, encryption_key=None): encryption_key = get_valid_encryption_key(encryption_key) - sym = utils.SymmetricCrypto() - return sym.decrypt(encryption_key, - value, b64decode=True) + sym = SymmetricCrypto() + return sym.decrypt(encryption_key, value, b64decode=True) def cryptography_decrypt_v1(value, encryption_key=None): diff --git a/heat/openstack/__init__.py b/heat/openstack/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/heat/openstack/common/README b/heat/openstack/common/README deleted file mode 100644 index 00505509d1..0000000000 --- a/heat/openstack/common/README +++ /dev/null @@ -1,16 +0,0 @@ -oslo-incubator --------------- - -A number of modules from oslo-incubator are imported into this project. -You can clone the oslo-incubator repository using the following url: - - https://git.openstack.org/openstack/oslo-incubator - -These modules are "incubating" in oslo-incubator and are kept in sync -with the help of oslo-incubator's update.py script. See: - - https://wiki.openstack.org/wiki/Oslo#Syncing_Code_from_Incubator - -The copy of the code should never be directly modified here. Please -always update oslo-incubator first and then run the script to copy -the changes across. diff --git a/heat/openstack/common/__init__.py b/heat/openstack/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/heat/openstack/common/_i18n.py b/heat/openstack/common/_i18n.py deleted file mode 100644 index a272fc66df..0000000000 --- a/heat/openstack/common/_i18n.py +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -try: - import oslo_i18n - - # NOTE(dhellmann): This reference to o-s-l-o will be replaced by the - # application name when this module is synced into the separate - # repository. It is OK to have more than one translation function - # using the same domain, since there will still only be one message - # catalog. - _translators = oslo_i18n.TranslatorFactory(domain='heat') - - # The primary translation function using the well-known name "_" - _ = _translators.primary - - # Translators for log levels. - # - # The abbreviated names are meant to reflect the usual use of a short - # name like '_'. The "L" is for "log" and the other letter comes from - # the level. - _LI = _translators.log_info - _LW = _translators.log_warning - _LE = _translators.log_error - _LC = _translators.log_critical -except ImportError: - # NOTE(dims): Support for cases where a project wants to use - # code from oslo-incubator, but is not ready to be internationalized - # (like tempest) - _ = _LI = _LW = _LE = _LC = lambda x: x diff --git a/heat/openstack/common/crypto/__init__.py b/heat/openstack/common/crypto/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/heat/openstack/common/crypto/utils.py b/heat/openstack/common/crypto/utils.py deleted file mode 100644 index 98c76e2be0..0000000000 --- a/heat/openstack/common/crypto/utils.py +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -######################################################################## -# -# THIS MODULE IS DEPRECATED -# -# Please refer to -# https://etherpad.openstack.org/p/kilo-heat-library-proposals for -# the discussion leading to this deprecation. -# -# We recommend checking out Barbican or the cryptography.py project -# (https://pypi.python.org/pypi/cryptography) instead of this module. -# -######################################################################## - -import base64 - -from Crypto import Hash -from Crypto import Random -from oslo_utils import importutils -import six - -from heat.openstack.common._i18n import _ - -bchr = six.int2byte - - -class CryptoutilsException(Exception): - """Generic Exception for Crypto utilities.""" - - message = _("An unknown error occurred in crypto utils.") - - -class CipherBlockLengthTooBig(CryptoutilsException): - """The block size is too big.""" - - def __init__(self, requested, permitted): - msg = _("Block size of %(given)d is too big, max = %(maximum)d") - message = msg % {'given': requested, 'maximum': permitted} - super(CryptoutilsException, self).__init__(message) - - -class HKDFOutputLengthTooLong(CryptoutilsException): - """The amount of Key Material asked is too much.""" - - def __init__(self, requested, permitted): - msg = _("Length of %(given)d is too long, max = %(maximum)d") - message = msg % {'given': requested, 'maximum': permitted} - super(CryptoutilsException, self).__init__(message) - - -class HKDF(object): - """An HMAC-based Key Derivation Function implementation (RFC5869) - - This class creates an object that allows to use HKDF to derive keys. - """ - - def __init__(self, hashtype='SHA256'): - self.hashfn = importutils.import_module('Crypto.Hash.' + hashtype) - self.max_okm_length = 255 * self.hashfn.digest_size - - def extract(self, ikm, salt=None): - """An extract function that can be used to derive a robust key given - weak Input Key Material (IKM) which could be a password. - Returns a pseudorandom key (of HashLen octets) - - :param ikm: input keying material (ex a password) - :param salt: optional salt value (a non-secret random value) - """ - if salt is None: - salt = b'\x00' * self.hashfn.digest_size - - return Hash.HMAC.new(salt, ikm, self.hashfn).digest() - - def expand(self, prk, info, length): - """An expand function that will return arbitrary length output that can - be used as keys. - Returns a buffer usable as key material. - - :param prk: a pseudorandom key of at least HashLen octets - :param info: optional string (can be a zero-length string) - :param length: length of output keying material (<= 255 * HashLen) - """ - if length > self.max_okm_length: - raise HKDFOutputLengthTooLong(length, self.max_okm_length) - - N = (length + self.hashfn.digest_size - 1) // self.hashfn.digest_size - - okm = b"" - tmp = b"" - for block in range(1, N + 1): - tmp = Hash.HMAC.new( - prk, tmp + info + bchr(block), self.hashfn).digest() - okm += tmp - - return okm[:length] - - -MAX_CB_SIZE = 256 - - -class SymmetricCrypto(object): - """Symmetric Key Crypto object. - - This class creates a Symmetric Key Crypto object that can be used - to encrypt, decrypt, or sign arbitrary data. - - :param enctype: Encryption Cipher name (default: AES) - :param hashtype: Hash/HMAC type name (default: SHA256) - """ - - def __init__(self, enctype='AES', hashtype='SHA256'): - self.cipher = importutils.import_module('Crypto.Cipher.' + enctype) - self.hashfn = importutils.import_module('Crypto.Hash.' + hashtype) - - def new_key(self, size): - return Random.new().read(size) - - def encrypt(self, key, msg, b64encode=True): - """Encrypt the provided msg and returns the cyphertext optionally - base64 encoded. - - Uses AES-128-CBC with a Random IV by default. - - The plaintext is padded to reach blocksize length. - The last byte of the block is the length of the padding. - The length of the padding does not include the length byte itself. - - :param key: The Encryption key. - :param msg: the plain text. - - :returns enc: a block of encrypted data. - """ - iv = Random.new().read(self.cipher.block_size) - cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv) - - # CBC mode requires a fixed block size. Append padding and length of - # padding. - if self.cipher.block_size > MAX_CB_SIZE: - raise CipherBlockLengthTooBig(self.cipher.block_size, MAX_CB_SIZE) - r = len(msg) % self.cipher.block_size - padlen = self.cipher.block_size - r - 1 - msg += b'\x00' * padlen - msg += bchr(padlen) - - enc = iv + cipher.encrypt(msg) - if b64encode: - enc = base64.b64encode(enc) - return enc - - def decrypt(self, key, msg, b64decode=True): - """Decrypts the provided ciphertext, optionally base64 encoded, and - returns the plaintext message, after padding is removed. - - Uses AES-128-CBC with an IV by default. - - :param key: The Encryption key. - :param msg: the ciphetext, the first block is the IV - - :returns plain: the plaintext message. - """ - if b64decode: - msg = base64.b64decode(msg) - iv = msg[:self.cipher.block_size] - cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv) - - padded = cipher.decrypt(msg[self.cipher.block_size:]) - l = ord(padded[-1:]) + 1 - plain = padded[:-l] - return plain - - def sign(self, key, msg, b64encode=True): - """Signs a message string and returns a base64 encoded signature. - - Uses HMAC-SHA-256 by default. - - :param key: The Signing key. - :param msg: the message to sign. - - :returns out: a base64 encoded signature. - """ - h = Hash.HMAC.new(key, msg, self.hashfn) - out = h.digest() - if b64encode: - out = base64.b64encode(out) - return out diff --git a/openstack-common.conf b/openstack-common.conf deleted file mode 100644 index cb59d436b1..0000000000 --- a/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from oslo-incubator -module=crypto - -# The base module to hold the copy of openstack.common -base=heat diff --git a/setup.cfg b/setup.cfg index 73645930d4..d6684d2cf6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -51,7 +51,6 @@ oslo.config.opts = heat.engine.clients = heat.engine.clients:list_opts heat.engine.notification = heat.engine.notification:list_opts heat.engine.resources = heat.engine.resources:list_opts - heat.openstack.common.policy = heat.openstack.common.policy:list_opts heat.api.middleware.ssl = heat.api.middleware.ssl:list_opts heat.api.aws.ec2token = heat.api.aws.ec2token:list_opts heat_integrationtests.common.config = heat_integrationtests.common.config:list_opts @@ -192,7 +191,6 @@ autodoc_exclude_modules = heat.db.* heat.engine.resources.* heat.locale.* - heat.openstack.* *.tests.* *.resources.*