Skip to content

Commit afb8a79

Browse files
committed
CLOUDSTACK-5921: S3 security key is stored in DB unencrypted
1 parent 28b5d0a commit afb8a79

4 files changed

Lines changed: 75 additions & 11 deletions

File tree

engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
import java.util.Map;
3030
import java.util.Set;
3131

32-
import com.cloud.hypervisor.Hypervisor;
3332
import org.apache.commons.lang.StringUtils;
3433
import org.apache.log4j.Logger;
3534

35+
import com.cloud.hypervisor.Hypervisor;
3636
import com.cloud.utils.crypt.DBEncryptionUtil;
3737
import com.cloud.utils.exception.CloudRuntimeException;
3838
import com.cloud.utils.script.Script;
@@ -68,6 +68,7 @@ public File[] getPrepareScripts() {
6868
@Override
6969
public void performDataMigration(Connection conn) {
7070
encryptLdapConfigParams(conn);
71+
encryptImageStoreDetails(conn);
7172
upgradeMemoryOfSsvmOffering(conn);
7273
updateSystemVmTemplates(conn);
7374
}
@@ -305,8 +306,44 @@ private void updateSystemVmTemplates(Connection conn) {
305306
}
306307
}
307308
s_logger.debug("Updating System Vm Template IDs Complete");
309+
} finally {
310+
try {
311+
if (rs != null) {
312+
rs.close();
313+
}
314+
315+
if (pstmt != null) {
316+
pstmt.close();
317+
}
318+
} catch (SQLException e) {
319+
}
308320
}
309-
finally {
321+
}
322+
323+
private void encryptImageStoreDetails(Connection conn) {
324+
s_logger.debug("Encrypting image store details");
325+
PreparedStatement pstmt = null;
326+
ResultSet rs = null;
327+
try {
328+
pstmt = conn.prepareStatement("select id, value from `cloud`.`image_store_details` where name = 'key' or name = 'secretkey'");
329+
rs = pstmt.executeQuery();
330+
while (rs.next()) {
331+
long id = rs.getLong(1);
332+
String value = rs.getString(2);
333+
if (value == null) {
334+
continue;
335+
}
336+
String encryptedValue = DBEncryptionUtil.encrypt(value);
337+
pstmt = conn.prepareStatement("update `cloud`.`image_store_details` set value=? where id=?");
338+
pstmt.setBytes(1, encryptedValue.getBytes("UTF-8"));
339+
pstmt.setLong(2, id);
340+
pstmt.executeUpdate();
341+
}
342+
} catch (SQLException e) {
343+
throw new CloudRuntimeException("Unable encrypt image_store_details values ", e);
344+
} catch (UnsupportedEncodingException e) {
345+
throw new CloudRuntimeException("Unable encrypt image_store_details values ", e);
346+
} finally {
310347
try {
311348
if (rs != null) {
312349
rs.close();
@@ -318,6 +355,7 @@ private void updateSystemVmTemplates(Connection conn) {
318355
} catch (SQLException e) {
319356
}
320357
}
358+
s_logger.debug("Done encrypting image_store_details");
321359
}
322360

323361
@Override

engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.springframework.stereotype.Component;
2828

29+
import org.apache.cloudstack.api.ApiConstants;
2930
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3031
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
3132
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO;
@@ -35,6 +36,7 @@
3536

3637
import com.cloud.storage.DataStoreRole;
3738
import com.cloud.storage.ScopeType;
39+
import com.cloud.utils.crypt.DBEncryptionUtil;
3840
import com.cloud.utils.exception.CloudRuntimeException;
3941

4042
@Component
@@ -104,7 +106,12 @@ public ImageStoreVO createImageStore(Map<String, Object> params, Map<String, Str
104106
ImageStoreDetailVO detail = new ImageStoreDetailVO();
105107
detail.setStoreId(store.getId());
106108
detail.setName(key);
107-
detail.setValue(details.get(key));
109+
String value = details.get(key);
110+
// encrypt swift key or s3 secret key
111+
if (key.equals(ApiConstants.KEY) || key.equals(ApiConstants.S3_SECRET_KEY)) {
112+
value = DBEncryptionUtil.encrypt(value);
113+
}
114+
detail.setValue(value);
108115
imageStoreDetailsDao.persist(detail);
109116
}
110117
}

engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222

2323
import javax.ejb.Local;
2424

25+
import org.springframework.stereotype.Component;
26+
27+
import org.apache.cloudstack.api.ApiConstants;
2528
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO;
2629
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
27-
import org.springframework.stereotype.Component;
2830

31+
import com.cloud.utils.crypt.DBEncryptionUtil;
2932
import com.cloud.utils.db.GenericDaoBase;
3033
import com.cloud.utils.db.SearchBuilder;
3134
import com.cloud.utils.db.SearchCriteria;
@@ -67,7 +70,12 @@ public Map<String, String> getDetails(long storeId) {
6770
List<ImageStoreDetailVO> details = listBy(sc);
6871
Map<String, String> detailsMap = new HashMap<String, String>();
6972
for (ImageStoreDetailVO detail : details) {
70-
detailsMap.put(detail.getName(), detail.getValue());
73+
String name = detail.getName();
74+
String value = detail.getValue();
75+
if (name.equals(ApiConstants.KEY) || name.equals(ApiConstants.S3_SECRET_KEY)) {
76+
value = DBEncryptionUtil.decrypt(value);
77+
}
78+
detailsMap.put(name, value);
7179
}
7280

7381
return detailsMap;

server/src/com/cloud/api/query/dao/ImageStoreJoinDaoImpl.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@
2222
import javax.ejb.Local;
2323
import javax.inject.Inject;
2424

25+
import org.apache.log4j.Logger;
26+
import org.springframework.stereotype.Component;
27+
28+
import org.apache.cloudstack.api.ApiConstants;
2529
import org.apache.cloudstack.api.response.ImageStoreDetailResponse;
2630
import org.apache.cloudstack.api.response.ImageStoreResponse;
2731
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
28-
import org.apache.log4j.Logger;
29-
import org.springframework.stereotype.Component;
3032

31-
import com.cloud.utils.StringUtils;
3233
import com.cloud.api.query.vo.ImageStoreJoinVO;
3334
import com.cloud.storage.ImageStore;
35+
import com.cloud.utils.StringUtils;
36+
import com.cloud.utils.crypt.DBEncryptionUtil;
3437
import com.cloud.utils.db.GenericDaoBase;
3538
import com.cloud.utils.db.SearchBuilder;
3639
import com.cloud.utils.db.SearchCriteria;
@@ -58,7 +61,7 @@ protected ImageStoreJoinDaoImpl() {
5861
dsIdSearch.and("id", dsIdSearch.entity().getId(), SearchCriteria.Op.EQ);
5962
dsIdSearch.done();
6063

61-
this._count = "select count(distinct id) from image_store_view WHERE ";
64+
_count = "select count(distinct id) from image_store_view WHERE ";
6265
}
6366

6467

@@ -84,7 +87,11 @@ public ImageStoreResponse newImageStoreResponse(ImageStoreJoinVO ids) {
8487

8588
String detailName = ids.getDetailName();
8689
if ( detailName != null && detailName.length() > 0 ){
87-
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, ids.getDetailValue());
90+
String detailValue = ids.getDetailValue();
91+
if (detailName.equals(ApiConstants.KEY) || detailName.equals(ApiConstants.S3_SECRET_KEY)) {
92+
detailValue = DBEncryptionUtil.decrypt(detailValue);
93+
}
94+
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, detailValue);
8895
osResponse.addDetail(osdResponse);
8996
}
9097
osResponse.setObjectName("imagestore");
@@ -99,7 +106,11 @@ public ImageStoreResponse newImageStoreResponse(ImageStoreJoinVO ids) {
99106
public ImageStoreResponse setImageStoreResponse(ImageStoreResponse response, ImageStoreJoinVO ids) {
100107
String detailName = ids.getDetailName();
101108
if ( detailName != null && detailName.length() > 0 ){
102-
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, ids.getDetailValue());
109+
String detailValue = ids.getDetailValue();
110+
if (detailName.equals(ApiConstants.KEY) || detailName.equals(ApiConstants.S3_SECRET_KEY)) {
111+
detailValue = DBEncryptionUtil.decrypt(detailValue);
112+
}
113+
ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, detailValue);
103114
response.addDetail(osdResponse);
104115
}
105116
return response;

0 commit comments

Comments
 (0)