CLOUDSTACK-5921:S3 security key is stored in DB unencrypted

This commit is contained in:
Min Chen 2014-01-21 14:34:32 -08:00
parent d4e069ecc8
commit c0da0a884a
4 changed files with 75 additions and 12 deletions

View File

@ -29,10 +29,10 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.cloud.hypervisor.Hypervisor;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
@ -68,6 +68,7 @@ public class Upgrade421to430 implements DbUpgrade {
@Override
public void performDataMigration(Connection conn) {
encryptLdapConfigParams(conn);
encryptImageStoreDetails(conn);
upgradeMemoryOfSsvmOffering(conn);
updateSystemVmTemplates(conn);
}
@ -305,8 +306,7 @@ public class Upgrade421to430 implements DbUpgrade {
}
}
s_logger.debug("Updating System Vm Template IDs Complete");
}
finally {
} finally {
try {
if (rs != null) {
rs.close();
@ -320,6 +320,44 @@ public class Upgrade421to430 implements DbUpgrade {
}
}
private void encryptImageStoreDetails(Connection conn) {
s_logger.debug("Encrypting image store details");
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement("select id, value from `cloud`.`image_store_details` where name = 'key' or name = 'secretkey'");
rs = pstmt.executeQuery();
while (rs.next()) {
long id = rs.getLong(1);
String value = rs.getString(2);
if (value == null) {
continue;
}
String encryptedValue = DBEncryptionUtil.encrypt(value);
pstmt = conn.prepareStatement("update `cloud`.`image_store_details` set value=? where id=?");
pstmt.setBytes(1, encryptedValue.getBytes("UTF-8"));
pstmt.setLong(2, id);
pstmt.executeUpdate();
}
} catch (SQLException e) {
throw new CloudRuntimeException("Unable encrypt image_store_details values ", e);
} catch (UnsupportedEncodingException e) {
throw new CloudRuntimeException("Unable encrypt image_store_details values ", e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
}
}
s_logger.debug("Done encrypting image_store_details");
}
@Override
public File[] getCleanupScripts() {
String script = Script.findScript("", "db/schema-421to430-cleanup.sql");

View File

@ -26,6 +26,7 @@ import javax.inject.Inject;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO;
@ -35,6 +36,7 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
@Component
@ -104,7 +106,12 @@ public class ImageStoreHelper {
ImageStoreDetailVO detail = new ImageStoreDetailVO();
detail.setStoreId(store.getId());
detail.setName(key);
detail.setValue(details.get(key));
String value = details.get(key);
// encrypt swift key or s3 secret key
if (key.equals(ApiConstants.KEY) || key.equals(ApiConstants.S3_SECRET_KEY)) {
value = DBEncryptionUtil.encrypt(value);
}
detail.setValue(value);
imageStoreDetailsDao.persist(detail);
}
}

View File

@ -24,9 +24,11 @@ import javax.ejb.Local;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@ -68,7 +70,12 @@ public class ImageStoreDetailsDaoImpl extends GenericDaoBase<ImageStoreDetailVO,
List<ImageStoreDetailVO> details = listBy(sc);
Map<String, String> detailsMap = new HashMap<String, String>();
for (ImageStoreDetailVO detail : details) {
detailsMap.put(detail.getName(), detail.getValue());
String name = detail.getName();
String value = detail.getValue();
if (name.equals(ApiConstants.KEY) || name.equals(ApiConstants.S3_SECRET_KEY)) {
value = DBEncryptionUtil.decrypt(value);
}
detailsMap.put(name, value);
}
return detailsMap;

View File

@ -23,17 +23,20 @@ import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.ImageStoreDetailResponse;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.springframework.stereotype.Component;
import com.cloud.api.query.vo.ImageStoreJoinVO;
import com.cloud.storage.ImageStore;
import com.cloud.utils.StringUtils;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.StringUtils;
@Component
@Local(value = {ImageStoreJoinDao.class})
@ -57,7 +60,7 @@ public class ImageStoreJoinDaoImpl extends GenericDaoBase<ImageStoreJoinVO, Long
dsIdSearch.and("id", dsIdSearch.entity().getId(), SearchCriteria.Op.EQ);
dsIdSearch.done();
this._count = "select count(distinct id) from image_store_view WHERE ";
_count = "select count(distinct id) from image_store_view WHERE ";
}
@Override
@ -78,8 +81,12 @@ public class ImageStoreJoinDaoImpl extends GenericDaoBase<ImageStoreJoinVO, Long
osResponse.setZoneName(ids.getZoneName());
String detailName = ids.getDetailName();
if (detailName != null && detailName.length() > 0) {
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, ids.getDetailValue());
if ( detailName != null && detailName.length() > 0 ){
String detailValue = ids.getDetailValue();
if (detailName.equals(ApiConstants.KEY) || detailName.equals(ApiConstants.S3_SECRET_KEY)) {
detailValue = DBEncryptionUtil.decrypt(detailValue);
}
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, detailValue);
osResponse.addDetail(osdResponse);
}
osResponse.setObjectName("imagestore");
@ -89,8 +96,12 @@ public class ImageStoreJoinDaoImpl extends GenericDaoBase<ImageStoreJoinVO, Long
@Override
public ImageStoreResponse setImageStoreResponse(ImageStoreResponse response, ImageStoreJoinVO ids) {
String detailName = ids.getDetailName();
if (detailName != null && detailName.length() > 0) {
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, ids.getDetailValue());
if ( detailName != null && detailName.length() > 0 ){
String detailValue = ids.getDetailValue();
if (detailName.equals(ApiConstants.KEY) || detailName.equals(ApiConstants.S3_SECRET_KEY)) {
detailValue = DBEncryptionUtil.decrypt(detailValue);
}
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, detailValue);
response.addDetail(osdResponse);
}
return response;