From: Ian Main Date: Thu, 26 Jul 2012 19:57:57 +0000 (-0700) Subject: Add encryption support for authentication information in db. X-Git-Tag: 2014.1~1558 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=58cd52624b50476ed5ed1c5c0ba7cb1b4d7ba66d;p=openstack-build%2Fheat-build.git Add encryption support for authentication information in db. This patch uses an encryption key generated in install.sh to perform symmetrical encryption on sensitive authentication information stored in the database for HA operations. Change-Id: Ifd09f3f566ba3ebd941a6f453953576011b518b9 Signed-off-by: Ian Main --- diff --git a/etc/heat-engine.conf b/etc/heat-engine.conf index f41b7129..0998d2e9 100644 --- a/etc/heat-engine.conf +++ b/etc/heat-engine.conf @@ -29,3 +29,5 @@ sql_connection = mysql://heat:heat@localhost/heat db_backend=heat.db.sqlalchemy.api rpc_backend=heat.openstack.common.rpc.impl_qpid + +auth_encryption_key=%ENCRYPTION_KEY% diff --git a/heat/db/sqlalchemy/api.py b/heat/db/sqlalchemy/api.py index 7365dfd5..09ab1cf5 100644 --- a/heat/db/sqlalchemy/api.py +++ b/heat/db/sqlalchemy/api.py @@ -19,6 +19,7 @@ from sqlalchemy.orm.session import Session from heat.common.exception import NotFound from heat.db.sqlalchemy import models from heat.db.sqlalchemy.session import get_session +from heat.engine import auth def model_query(context, *args, **kwargs): @@ -202,12 +203,18 @@ def stack_delete(context, stack_id): def user_creds_create(values): user_creds_ref = models.UserCreds() user_creds_ref.update(values) + user_creds_ref.password = auth.encrypt(values['password']) + user_creds_ref.service_password = auth.encrypt(values['service_password']) + user_creds_ref.aws_creds = auth.encrypt(values['aws_creds']) user_creds_ref.save() return user_creds_ref def user_creds_get(user_creds_id): result = model_query(None, models.UserCreds).get(user_creds_id) + result.password = auth.decrypt(result.password) + result.service_password = auth.decrypt(result.service_password) + result.aws_creds = auth.decrypt(result.aws_creds) return result diff --git a/heat/engine/auth.py b/heat/engine/auth.py index bd547b0c..a4be7ef0 100644 --- a/heat/engine/auth.py +++ b/heat/engine/auth.py @@ -16,6 +16,7 @@ import json import httplib import urlparse +import base64 from novaclient.v1_1 import client from novaclient.exceptions import BadRequest from novaclient.exceptions import NotFound @@ -23,9 +24,43 @@ from novaclient.exceptions import AuthorizationFailure from heat.common import context from heat.openstack.common import log as logging +from Crypto.Cipher import AES +from Crypto import Random + +from heat.openstack.common import cfg +from heat.openstack.common import importutils + + +auth_opts = [ + cfg.StrOpt('auth_encryption_key', + default='notgood', + help="Encryption key used for authentication info in database") +] + +cfg.CONF.register_opts(auth_opts) + logger = logging.getLogger('heat.engine.auth') +def encrypt(auth_info): + if auth_info is None: + return None + iv = Random.new().read(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 + + +def decrypt(auth_info): + if auth_info is None: + return None + auth = base64.b64decode(auth_info) + iv = auth[:AES.block_size] + cipher = AES.new(cfg.CONF.auth_encryption_key[:32], AES.MODE_CFB, iv) + res = cipher.decrypt(auth[AES.block_size:]) + return res + + def authenticate(con, service_type='heat', service_name='heat'): """ Authenticate a user context. This authenticates either an EC2 style key context or a keystone user/pass context. diff --git a/install.sh b/install.sh index b58f7153..946198b2 100755 --- a/install.sh +++ b/install.sh @@ -20,6 +20,8 @@ do elif [ -f $CONF_DIR/$f ]; then echo "not copying over $CONF_DIR/$f" diff -u $CONF_DIR/$f $f + elif [ $f = 'heat-engine.conf' ]; then + cat $f | sed s/%ENCRYPTION_KEY%/`/bin/uuidgen`/ > $CONF_DIR/$f else cp $f $CONF_DIR fi