Revert "Add a new crypt method using cryptography"
This reverts commit d8f3ef910c
.
Change-Id: I76dc18baa0d71b1819b765c6ee5840bd7e2ef59d
Related-Bug: #1471150
This commit is contained in:
parent
d8f3ef910c
commit
9cba80c091
|
@ -12,19 +12,13 @@
|
|||
# under the License.
|
||||
|
||||
import base64
|
||||
import sys
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
from cryptography import fernet
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import encodeutils
|
||||
|
||||
from heat.common.i18n import _
|
||||
from heat.common.i18n import _LW
|
||||
from heat.openstack.common.crypto import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
auth_opts = [
|
||||
cfg.StrOpt('auth_encryption_key',
|
||||
|
@ -38,52 +32,36 @@ auth_opts = [
|
|||
cfg.CONF.register_opts(auth_opts)
|
||||
|
||||
|
||||
def encrypt(value, encryption_key=None):
|
||||
if value is None:
|
||||
def encrypt(auth_info, encryption_key=None):
|
||||
if auth_info is None:
|
||||
return None, None
|
||||
|
||||
encryption_key = get_valid_encryption_key(encryption_key)
|
||||
sym = fernet.Fernet(encryption_key.encode('base64'))
|
||||
res = sym.encrypt(encodeutils.safe_encode(value))
|
||||
return 'cryptography_decrypt_v1', res
|
||||
sym = utils.SymmetricCrypto()
|
||||
res = sym.encrypt(encryption_key,
|
||||
auth_info, b64encode=True)
|
||||
return 'oslo_decrypt_v1', res
|
||||
|
||||
|
||||
def decrypt(method, data, encryption_key=None):
|
||||
if method is None or data is None:
|
||||
def oslo_decrypt_v1(auth_info, encryption_key=None):
|
||||
if auth_info is None:
|
||||
return None
|
||||
decryptor = getattr(sys.modules[__name__], method)
|
||||
value = decryptor(data, encryption_key)
|
||||
if value is not None:
|
||||
try:
|
||||
return encodeutils.safe_decode(value, 'utf-8')
|
||||
except UnicodeDecodeError as ex:
|
||||
# if the incorrect encryption_key was used then we can get
|
||||
# total gibberish here and safe_decode() will freak out.
|
||||
LOG.warn(_LW("Couldn't decrypt parameters %s"), ex)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def cryptography_decrypt_v1(value, encryption_key=None):
|
||||
encryption_key = get_valid_encryption_key(encryption_key)
|
||||
sym = fernet.Fernet(encryption_key.encode('base64'))
|
||||
return sym.decrypt(encodeutils.safe_encode(value))
|
||||
auth_info, b64decode=True)
|
||||
|
||||
|
||||
def get_valid_encryption_key(encryption_key):
|
||||
if encryption_key is None:
|
||||
encryption_key = cfg.CONF.auth_encryption_key[:32]
|
||||
else:
|
||||
encryption_key = encryption_key[:32]
|
||||
encryption_key = encryption_key[0:32]
|
||||
return encryption_key
|
||||
|
||||
|
||||
def heat_decrypt(value, encryption_key=None):
|
||||
def heat_decrypt(auth_info, encryption_key=None):
|
||||
"""Decrypt function for data that has been encrypted using an older
|
||||
version of Heat.
|
||||
Note: the encrypt function returns the function that is needed to
|
||||
|
@ -92,8 +70,11 @@ def heat_decrypt(value, encryption_key=None):
|
|||
function must still exist. So whilst it may seem that this function
|
||||
is not referenced, it will be referenced from the database.
|
||||
"""
|
||||
if auth_info is None:
|
||||
return None
|
||||
|
||||
encryption_key = get_valid_encryption_key(encryption_key)
|
||||
auth = base64.b64decode(value)
|
||||
auth = base64.b64decode(auth_info)
|
||||
iv = auth[:AES.block_size]
|
||||
cipher = AES.new(encryption_key, AES.MODE_CFB, iv)
|
||||
res = cipher.decrypt(auth[AES.block_size:])
|
||||
|
|
|
@ -18,6 +18,8 @@ import sys
|
|||
from oslo_config import cfg
|
||||
from oslo_db.sqlalchemy import session as db_session
|
||||
from oslo_db.sqlalchemy import utils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import timeutils
|
||||
import osprofiler.sqlalchemy
|
||||
import six
|
||||
|
@ -29,6 +31,7 @@ from sqlalchemy.orm import session as orm_session
|
|||
from heat.common import crypt
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.common.i18n import _LW
|
||||
from heat.db.sqlalchemy import filters as db_filters
|
||||
from heat.db.sqlalchemy import migration
|
||||
from heat.db.sqlalchemy import models
|
||||
|
@ -39,6 +42,8 @@ CONF.import_opt('hidden_stack_tags', 'heat.common.config')
|
|||
CONF.import_opt('max_events_per_stack', 'heat.common.config')
|
||||
CONF.import_group('profiler', 'heat.common.config')
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
_facade = None
|
||||
|
||||
|
||||
|
@ -192,7 +197,7 @@ def resource_data_get_all(resource, data=None):
|
|||
|
||||
for res in data:
|
||||
if res.redact:
|
||||
ret[res.key] = crypt.decrypt(res.decrypt_method, res.value)
|
||||
ret[res.key] = _decrypt(res.value, res.decrypt_method)
|
||||
else:
|
||||
ret[res.key] = res.value
|
||||
return ret
|
||||
|
@ -206,7 +211,7 @@ def resource_data_get(resource, key):
|
|||
resource.id,
|
||||
key)
|
||||
if result.redact:
|
||||
return crypt.decrypt(result.decrypt_method, result.value)
|
||||
return _decrypt(result.value, result.decrypt_method)
|
||||
return result.value
|
||||
|
||||
|
||||
|
@ -240,6 +245,22 @@ def stack_tags_get(context, stack_id):
|
|||
return result or None
|
||||
|
||||
|
||||
def _encrypt(value):
|
||||
if value is not None:
|
||||
return crypt.encrypt(value.encode('utf-8'))
|
||||
else:
|
||||
return None, None
|
||||
|
||||
|
||||
def _decrypt(enc_value, method):
|
||||
if method is None:
|
||||
return None
|
||||
decryptor = getattr(crypt, method)
|
||||
value = decryptor(enc_value)
|
||||
if value is not None:
|
||||
return six.text_type(value, 'utf-8')
|
||||
|
||||
|
||||
def resource_data_get_by_key(context, resource_id, key):
|
||||
"""Looks up resource_data by resource_id and key. Does not unencrypt
|
||||
resource_data.
|
||||
|
@ -256,7 +277,7 @@ def resource_data_get_by_key(context, resource_id, key):
|
|||
def resource_data_set(resource, key, value, redact=False):
|
||||
"""Save resource's key/value pair to database."""
|
||||
if redact:
|
||||
method, value = crypt.encrypt(value)
|
||||
method, value = _encrypt(value)
|
||||
else:
|
||||
method = ''
|
||||
try:
|
||||
|
@ -602,7 +623,7 @@ def user_creds_create(context):
|
|||
values = context.to_dict()
|
||||
user_creds_ref = models.UserCreds()
|
||||
if values.get('trust_id'):
|
||||
method, trust_id = crypt.encrypt(values.get('trust_id'))
|
||||
method, trust_id = _encrypt(values.get('trust_id'))
|
||||
user_creds_ref.trust_id = trust_id
|
||||
user_creds_ref.decrypt_method = method
|
||||
user_creds_ref.trustor_user_id = values.get('trustor_user_id')
|
||||
|
@ -614,7 +635,7 @@ def user_creds_create(context):
|
|||
user_creds_ref.region_name = values.get('region_name')
|
||||
else:
|
||||
user_creds_ref.update(values)
|
||||
method, password = crypt.encrypt(values['password'])
|
||||
method, password = _encrypt(values['password'])
|
||||
if len(six.text_type(password)) > 255:
|
||||
raise exception.Error(_("Length of OS_PASSWORD after encryption"
|
||||
" exceeds Heat limit (255 chars)"))
|
||||
|
@ -632,10 +653,8 @@ def user_creds_get(user_creds_id):
|
|||
# or it can be committed back to the DB in decrypted form
|
||||
result = dict(db_result)
|
||||
del result['decrypt_method']
|
||||
result['password'] = crypt.decrypt(
|
||||
db_result.decrypt_method, result['password'])
|
||||
result['trust_id'] = crypt.decrypt(
|
||||
db_result.decrypt_method, result['trust_id'])
|
||||
result['password'] = _decrypt(result['password'], db_result.decrypt_method)
|
||||
result['trust_id'] = _decrypt(result['trust_id'], db_result.decrypt_method)
|
||||
return result
|
||||
|
||||
|
||||
|
@ -1140,7 +1159,8 @@ def db_encrypt_parameters_and_properties(ctxt, encryption_key):
|
|||
except KeyError:
|
||||
param_val = param.default
|
||||
|
||||
encrypted_val = crypt.encrypt(param_val, encryption_key)
|
||||
encoded_val = encodeutils.safe_encode(param_val)
|
||||
encrypted_val = crypt.encrypt(encoded_val, encryption_key)
|
||||
raw_template.environment['parameters'][param_name] = \
|
||||
encrypted_val
|
||||
encrypted_params.append(param_name)
|
||||
|
@ -1163,10 +1183,18 @@ def db_decrypt_parameters_and_properties(ctxt, encryption_key):
|
|||
encrypted_params = raw_template.environment[
|
||||
'encrypted_param_names']
|
||||
for param_name in encrypted_params:
|
||||
method, value = parameters[param_name]
|
||||
decrypted_val = crypt.decrypt(method, value, encryption_key)
|
||||
parameters[param_name] = decrypted_val
|
||||
|
||||
decrypt_function_name = parameters[param_name][0]
|
||||
decrypt_function = getattr(crypt, decrypt_function_name)
|
||||
decrypted_val = decrypt_function(parameters[param_name][1],
|
||||
encryption_key)
|
||||
try:
|
||||
parameters[param_name] = encodeutils.safe_decode(
|
||||
decrypted_val)
|
||||
except UnicodeDecodeError as ex:
|
||||
# if the incorrect encryption_key was used then we can get
|
||||
# total gibberish here and safe_decode() will freak out.
|
||||
LOG.warn(_LW("Couldn't decrypt parameters %s"), ex)
|
||||
parameters[param_name] = ""
|
||||
environment = raw_template.environment.copy()
|
||||
environment['encrypted_param_names'] = []
|
||||
raw_template_update(ctxt, raw_template.id,
|
||||
|
|
|
@ -20,6 +20,7 @@ RawTemplate object
|
|||
import copy
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
|
@ -55,9 +56,10 @@ class RawTemplate(
|
|||
env_fmt.ENCRYPTED_PARAM_NAMES]
|
||||
|
||||
for param_name in encrypted_param_names:
|
||||
method, value = parameters[param_name]
|
||||
decrypted_val = crypt.decrypt(method, value)
|
||||
parameters[param_name] = decrypted_val
|
||||
decrypt_function_name = parameters[param_name][0]
|
||||
decrypt_function = getattr(crypt, decrypt_function_name)
|
||||
decrypted_val = decrypt_function(parameters[param_name][1])
|
||||
parameters[param_name] = encodeutils.safe_decode(decrypted_val)
|
||||
tpl.environment[env_fmt.PARAMETERS] = parameters
|
||||
|
||||
tpl._context = context
|
||||
|
@ -76,7 +78,8 @@ class RawTemplate(
|
|||
if not tmpl.param_schemata()[param_name].hidden:
|
||||
continue
|
||||
clear_text_val = tmpl.env.params.get(param_name)
|
||||
tmpl.env.params[param_name] = crypt.encrypt(clear_text_val)
|
||||
encoded_val = encodeutils.safe_encode(clear_text_val)
|
||||
tmpl.env.params[param_name] = crypt.encrypt(encoded_val)
|
||||
tmpl.env.encrypted_param_names.append(param_name)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -20,6 +20,7 @@ Resource object
|
|||
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import fields
|
||||
import six
|
||||
|
@ -84,8 +85,9 @@ class Resource(
|
|||
if resource.properties_data_encrypted and resource.properties_data:
|
||||
properties_data = {}
|
||||
for prop_name, prop_value in resource.properties_data.items():
|
||||
method, value = prop_value
|
||||
decrypted_value = crypt.decrypt(method, value)
|
||||
decrypt_function_name = prop_value[0]
|
||||
decrypt_function = getattr(crypt, decrypt_function_name, None)
|
||||
decrypted_value = decrypt_function(prop_value[1])
|
||||
prop_string = jsonutils.loads(decrypted_value)
|
||||
properties_data[prop_name] = prop_string
|
||||
resource.properties_data = properties_data
|
||||
|
@ -183,7 +185,8 @@ class Resource(
|
|||
result = {}
|
||||
for prop_name, prop_value in data.items():
|
||||
prop_string = jsonutils.dumps(prop_value)
|
||||
encrypted_value = crypt.encrypt(prop_string)
|
||||
encoded_value = encodeutils.safe_encode(prop_string)
|
||||
encrypted_value = crypt.encrypt(encoded_value)
|
||||
result[prop_name] = encrypted_value
|
||||
return (True, result)
|
||||
return (False, data)
|
||||
|
|
|
@ -22,7 +22,6 @@ from oslo_utils import timeutils
|
|||
import six
|
||||
|
||||
from heat.common import context
|
||||
from heat.common import crypt
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.db.sqlalchemy import api as db_api
|
||||
|
@ -1501,8 +1500,8 @@ class DBAPIUserCredsTest(common.HeatTestCase):
|
|||
trustor_user_id='trustor_id')
|
||||
self.assertIsNotNone(user_creds.id)
|
||||
self.assertEqual('test_trust_id',
|
||||
crypt.decrypt(user_creds.decrypt_method,
|
||||
user_creds.trust_id))
|
||||
db_api._decrypt(user_creds.trust_id,
|
||||
user_creds.decrypt_method))
|
||||
self.assertEqual('trustor_id', user_creds.trustor_user_id)
|
||||
self.assertIsNone(user_creds.username)
|
||||
self.assertIsNone(user_creds.password)
|
||||
|
@ -1513,14 +1512,14 @@ class DBAPIUserCredsTest(common.HeatTestCase):
|
|||
user_creds = create_user_creds(self.ctx)
|
||||
self.assertIsNotNone(user_creds.id)
|
||||
self.assertEqual(self.ctx.password,
|
||||
crypt.decrypt(user_creds.decrypt_method,
|
||||
user_creds.password))
|
||||
db_api._decrypt(user_creds.password,
|
||||
user_creds.decrypt_method))
|
||||
|
||||
def test_user_creds_get(self):
|
||||
user_creds = create_user_creds(self.ctx)
|
||||
ret_user_creds = db_api.user_creds_get(user_creds.id)
|
||||
self.assertEqual(crypt.decrypt(user_creds.decrypt_method,
|
||||
user_creds.password),
|
||||
self.assertEqual(db_api._decrypt(user_creds.password,
|
||||
user_creds.decrypt_method),
|
||||
ret_user_creds['password'])
|
||||
|
||||
def test_user_creds_get_noexist(self):
|
||||
|
@ -2732,9 +2731,8 @@ class DBAPICryptParamsPropsTest(common.HeatTestCase):
|
|||
self.ctx, cfg.CONF.auth_encryption_key)
|
||||
|
||||
env = session.query(models.RawTemplate).all()[0].environment
|
||||
self.assertEqual('cryptography_decrypt_v1',
|
||||
self.assertEqual('oslo_decrypt_v1',
|
||||
env['parameters']['param2'][0])
|
||||
encrypt_value = env['parameters']['param2'][1]
|
||||
|
||||
db_api.db_decrypt_parameters_and_properties(
|
||||
self.ctx, cfg.CONF.auth_encryption_key)
|
||||
|
@ -2744,13 +2742,9 @@ class DBAPICryptParamsPropsTest(common.HeatTestCase):
|
|||
|
||||
# Use a different encryption key to decrypt
|
||||
db_api.db_encrypt_parameters_and_properties(
|
||||
self.ctx, '774c15be099ea74123a9b9592ff12680')
|
||||
env = session.query(models.RawTemplate).all()[0].environment
|
||||
self.assertNotEqual(encrypt_value,
|
||||
env['parameters']['param2'][1])
|
||||
|
||||
self.ctx, cfg.CONF.auth_encryption_key)
|
||||
db_api.db_decrypt_parameters_and_properties(
|
||||
self.ctx, '774c15be099ea74123a9b9592ff12680')
|
||||
|
||||
env = session.query(models.RawTemplate).all()[0].environment
|
||||
self.assertEqual('bar', env['parameters']['param2'])
|
||||
self.assertNotEqual('bar', env['parameters']['param2'])
|
||||
|
|
|
@ -1987,7 +1987,7 @@ class StackTest(common.HeatTestCase):
|
|||
db_tpl = db_api.raw_template_get(self.ctx, self.stack.t.id)
|
||||
db_params = db_tpl.environment['parameters']
|
||||
self.assertEqual('foo', db_params['param1'])
|
||||
self.assertEqual('cryptography_decrypt_v1', db_params['param2'][0])
|
||||
self.assertEqual('oslo_decrypt_v1', db_params['param2'][0])
|
||||
self.assertIsNotNone(db_params['param2'][1])
|
||||
|
||||
# Verify that loaded stack has decrypted paramters
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
pbr<2.0,>=0.11
|
||||
Babel>=1.3
|
||||
cryptography>=0.8.2 # Apache-2.0
|
||||
dogpile.cache>=0.5.3
|
||||
eventlet>=0.17.4
|
||||
greenlet>=0.3.2
|
||||
|
|
Loading…
Reference in New Issue