Merge "Add support for multiple encryption methods"
This commit is contained in:
commit
37e74a3c06
@ -35,14 +35,14 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
def encrypt(auth_info):
|
||||
if auth_info is None:
|
||||
return None
|
||||
return None, None
|
||||
iv = urandom(AES.block_size)
|
||||
cipher = AES.new(cfg.CONF.auth_encryption_key[:32], AES.MODE_CFB, iv)
|
||||
res = base64.b64encode(iv + cipher.encrypt(auth_info))
|
||||
return res
|
||||
return 'heat_decrypt', res
|
||||
|
||||
|
||||
def decrypt(auth_info):
|
||||
def heat_decrypt(auth_info):
|
||||
if auth_info is None:
|
||||
return None
|
||||
auth = base64.b64decode(auth_info)
|
||||
|
@ -142,7 +142,7 @@ def resource_data_get_all(resource):
|
||||
|
||||
for res in result:
|
||||
if res.redact:
|
||||
ret[res.key] = _decrypt(res.value)
|
||||
ret[res.key] = _decrypt(res.value, res.decrypt_method)
|
||||
else:
|
||||
ret[res.key] = res.value
|
||||
|
||||
@ -157,17 +157,22 @@ def resource_data_get(resource, key):
|
||||
resource.id,
|
||||
key)
|
||||
if result.redact:
|
||||
return _decrypt(result.value)
|
||||
return _decrypt(result.value, result.decrypt_method)
|
||||
return result.value
|
||||
|
||||
|
||||
def _encrypt(value):
|
||||
if value is not None:
|
||||
return crypt.encrypt(value.encode('utf-8'))
|
||||
else:
|
||||
return None, None
|
||||
|
||||
|
||||
def _decrypt(enc_value):
|
||||
value = crypt.decrypt(enc_value)
|
||||
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 unicode(value, 'utf-8')
|
||||
|
||||
@ -188,7 +193,9 @@ 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:
|
||||
value = _encrypt(value)
|
||||
method, value = _encrypt(value)
|
||||
else:
|
||||
method = ''
|
||||
try:
|
||||
current = resource_data_get_by_key(resource.context, resource.id, key)
|
||||
except exception.NotFound:
|
||||
@ -197,6 +204,7 @@ def resource_data_set(resource, key, value, redact=False):
|
||||
current.resource_id = resource.id
|
||||
current.redact = redact
|
||||
current.value = value
|
||||
current.decrypt_method = method
|
||||
current.save(session=resource.context.session)
|
||||
return current
|
||||
|
||||
@ -425,7 +433,9 @@ def user_creds_create(context):
|
||||
values = context.to_dict()
|
||||
user_creds_ref = models.UserCreds()
|
||||
if values.get('trust_id'):
|
||||
user_creds_ref.trust_id = _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')
|
||||
user_creds_ref.username = None
|
||||
user_creds_ref.password = None
|
||||
@ -433,7 +443,9 @@ def user_creds_create(context):
|
||||
user_creds_ref.tenant_id = values.get('tenant_id')
|
||||
else:
|
||||
user_creds_ref.update(values)
|
||||
user_creds_ref.password = _encrypt(values['password'])
|
||||
method, password = _encrypt(values['password'])
|
||||
user_creds_ref.password = password
|
||||
user_creds_ref.decrypt_method = method
|
||||
user_creds_ref.save(_session(context))
|
||||
return user_creds_ref
|
||||
|
||||
@ -443,8 +455,9 @@ def user_creds_get(user_creds_id):
|
||||
# Return a dict copy of db results, do not decrypt details into db_result
|
||||
# or it can be committed back to the DB in decrypted form
|
||||
result = dict(db_result)
|
||||
result['password'] = _decrypt(result['password'])
|
||||
result['trust_id'] = _decrypt(result['trust_id'])
|
||||
del result['decrypt_method']
|
||||
result['password'] = _decrypt(result['password'], db_result.decrypt_method)
|
||||
result['trust_id'] = _decrypt(result['trust_id'], db_result.decrypt_method)
|
||||
return result
|
||||
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
# 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.
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
for table in ('user_creds', 'resource_data'):
|
||||
table = sqlalchemy.Table(table, meta, autoload=True)
|
||||
method = sqlalchemy.Column('decrypt_method',
|
||||
sqlalchemy.String(length=64),
|
||||
default='heat_decrypt')
|
||||
method.create(table)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = sqlalchemy.MetaData(bind=migrate_engine)
|
||||
|
||||
for table in ('user_creds', 'resource_data'):
|
||||
table = sqlalchemy.Table(table, meta, autoload=True)
|
||||
table.c.decrypt_method.drop()
|
@ -166,6 +166,7 @@ class UserCreds(BASE, HeatBase):
|
||||
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
|
||||
username = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
password = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
decrypt_method = sqlalchemy.Column(sqlalchemy.String(64))
|
||||
tenant = sqlalchemy.Column(sqlalchemy.String(1024))
|
||||
auth_url = sqlalchemy.Column(sqlalchemy.String)
|
||||
tenant_id = sqlalchemy.Column(sqlalchemy.String(256))
|
||||
@ -207,6 +208,7 @@ class ResourceData(BASE, HeatBase):
|
||||
key = sqlalchemy.Column('key', sqlalchemy.String(255))
|
||||
value = sqlalchemy.Column('value', sqlalchemy.String)
|
||||
redact = sqlalchemy.Column('redact', sqlalchemy.Boolean)
|
||||
decrypt_method = sqlalchemy.Column(sqlalchemy.String(64))
|
||||
resource_id = sqlalchemy.Column('resource_id',
|
||||
sqlalchemy.String(36),
|
||||
sqlalchemy.ForeignKey('resource.id'),
|
||||
|
@ -637,7 +637,9 @@ class DBAPIUserCredsTest(HeatTestCase):
|
||||
user_creds = create_user_creds(self.ctx, trust_id='test_trust_id',
|
||||
trustor_user_id='trustor_id')
|
||||
self.assertIsNotNone(user_creds.id)
|
||||
self.assertEqual('test_trust_id', db_api._decrypt(user_creds.trust_id))
|
||||
self.assertEqual('test_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)
|
||||
@ -648,12 +650,14 @@ class DBAPIUserCredsTest(HeatTestCase):
|
||||
user_creds = create_user_creds(self.ctx)
|
||||
self.assertIsNotNone(user_creds.id)
|
||||
self.assertEqual(self.ctx.password,
|
||||
db_api._decrypt(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(db_api._decrypt(user_creds.password),
|
||||
self.assertEqual(db_api._decrypt(user_creds.password,
|
||||
user_creds.decrypt_method),
|
||||
ret_user_creds['password'])
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user