Centralize loading of db.properties to one place

There is now a method DbProperites.getDbProperties() that will load the
db.properties in one place and do the proper decryption of values if needed
This commit is contained in:
Darren Shepherd 2013-10-30 17:03:13 -07:00
parent 27294a3827
commit 1460196496
15 changed files with 241 additions and 417 deletions

View File

@ -16,18 +16,11 @@
// under the License.
package com.cloud.bridge.persist.dao;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.properties.EncryptableProperties;
import com.cloud.bridge.util.ConfigurationHelper;
import com.cloud.bridge.util.EncryptionSecretKeyCheckerUtil;
import com.cloud.utils.db.DbProperties;
@ -43,24 +36,9 @@ public class BaseDao {
static{
logger.info("Initializing DB props");
File propertiesFile = ConfigurationHelper.findConfigurationFile("db.properties");
Properties EC2Prop = null;
if (null != propertiesFile) {
if(EncryptionSecretKeyCheckerUtil.useEncryption()){
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyCheckerUtil.getEncryptor();
EC2Prop = new EncryptableProperties(encryptor);
} else {
EC2Prop = new Properties();
}
Properties EC2Prop = DbProperties.getDbProperties();
try {
EC2Prop.load( new FileInputStream( propertiesFile ));
} catch (FileNotFoundException e) {
logger.warn("Unable to open properties file: " + propertiesFile.getAbsolutePath(), e);
} catch (IOException e) {
logger.warn("Unable to read properties file: " + propertiesFile.getAbsolutePath(), e);
}
if (EC2Prop.size() > 0) {
dbHost = EC2Prop.getProperty( "db.cloud.host" );
awsapi_dbName = EC2Prop.getProperty( "db.awsapi.name" );
cloud_dbName = EC2Prop.getProperty( "db.cloud.name" );

View File

@ -1,138 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
package com.cloud.bridge.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
public class EncryptionSecretKeyCheckerUtil {
private static final Logger s_logger = Logger.getLogger(EncryptionSecretKeyCheckerUtil.class);
private static final String s_keyFile = "/etc/cloudstack/management/key";
private static final String s_envKey = "CLOUD_SECRET_KEY";
private static StandardPBEStringEncryptor s_encryptor = new StandardPBEStringEncryptor();
private static boolean s_useEncryption = false;
static{
//Get encryption type from db.properties
final File dbPropsFile = ConfigurationHelper.findConfigurationFile("db.properties");
final Properties dbProps = new Properties();
try {
dbProps.load(new FileInputStream(dbPropsFile));
final String encryptionType = dbProps.getProperty("db.cloud.encryption.type");
s_logger.debug("Encryption Type: "+ encryptionType);
if(encryptionType != null && !encryptionType.equals("none")){
s_encryptor.setAlgorithm("PBEWithMD5AndDES");
String secretKey = null;
SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig();
if(encryptionType.equals("file")){
try {
BufferedReader in = new BufferedReader(new FileReader(s_keyFile));
secretKey = in.readLine();
//Check for null or empty secret key
} catch (FileNotFoundException e) {
throw new RuntimeException("File containing secret key not found: "+s_keyFile, e);
} catch (IOException e) {
throw new RuntimeException("Error while reading secret key from: "+s_keyFile, e);
}
if(secretKey == null || secretKey.isEmpty()){
throw new RuntimeException("Secret key is null or empty in file "+s_keyFile);
}
} else if(encryptionType.equals("env")){
secretKey = System.getenv(s_envKey);
if(secretKey == null || secretKey.isEmpty()){
throw new RuntimeException("Environment variable "+s_envKey+" is not set or empty");
}
} else if(encryptionType.equals("web")){
ServerSocket serverSocket = null;
int port = 8097;
try {
serverSocket = new ServerSocket(port);
} catch (IOException ioex) {
throw new RuntimeException("Error initializing secret key reciever", ioex);
}
s_logger.info("Waiting for admin to send secret key on port "+port);
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
throw new RuntimeException("Accept failed on "+port);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;
if ((inputLine = in.readLine()) != null) {
secretKey = inputLine;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
} else {
throw new RuntimeException("Invalid encryption type: "+encryptionType);
}
stringConfig.setPassword(secretKey);
s_encryptor.setConfig(stringConfig);
s_useEncryption = true;
}
} catch (FileNotFoundException e) {
throw new RuntimeException("File db.properties not found", e);
} catch (IOException e) {
throw new RuntimeException("Error while reading db.properties", e);
}
}
public static StandardPBEStringEncryptor getEncryptor() {
return s_encryptor;
}
public static boolean useEncryption(){
return s_useEncryption;
}
//Initialize encryptor for migration during secret key change
public static void initEncryptorForMigration(String secretKey){
s_encryptor.setAlgorithm("PBEWithMD5AndDES");
SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig();
stringConfig.setPassword(secretKey);
s_encryptor.setConfig(stringConfig);
s_useEncryption = true;
}
}

View File

@ -25,8 +25,9 @@
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
>
<bean class="org.apache.cloudstack.spring.lifecycle.CloudStackLog4jSetup" />
<bean class="com.cloud.utils.crypt.EncryptionSecretKeyChecker" />
</beans>

View File

@ -18,7 +18,12 @@
*/
package com.cloud.upgrade;
import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
@ -33,7 +38,6 @@ import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.SystemIntegrityChecker;
import com.cloud.utils.db.ScriptRunner;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionLegacy;
// Creates the CloudStack Database by using the 4.0 schema and apply
@ -171,10 +175,6 @@ public class DatabaseCreator {
System.exit(1);
}
try {
TransactionLegacy.initDataSource(dbPropsFile);
} catch (NullPointerException e) {
}
initDB(dbPropsFile, rootPassword, databases, dryRun);
// Process sql files

View File

@ -18,21 +18,16 @@
package com.cloud.upgrade.dao;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.crypt.EncryptionSecretKeyChecker;
import org.apache.log4j.Logger;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.properties.EncryptableProperties;
public class Upgrade307to410 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade307to410.class);
@ -68,23 +63,7 @@ public class Upgrade307to410 implements DbUpgrade {
}
private void updateRegionEntries(Connection conn) {
File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
final Properties dbProps;
if (EncryptionSecretKeyChecker.useEncryption()) {
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
dbProps = new EncryptableProperties(encryptor);
} else {
dbProps = new Properties();
}
try {
dbProps.load(new FileInputStream(dbPropsFile));
} catch (IOException e) {
s_logger.fatal("Unable to load db properties file, pl. check the classpath and file path configuration", e);
return;
} catch (NullPointerException e) {
s_logger.fatal("Unable to locate db properties file within classpath or absolute path: db.properties");
return;
}
final Properties dbProps = DbProperties.getDbProperties();
int region_id = 1;
String regionId = dbProps.getProperty("region.id");
if(regionId != null){

View File

@ -19,9 +19,11 @@ package com.cloud.upgrade.dao;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.crypt.EncryptionSecretKeyChecker;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import org.apache.log4j.Logger;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.properties.EncryptableProperties;
@ -81,23 +83,7 @@ public class Upgrade40to41 implements DbUpgrade {
}
private void updateRegionEntries(Connection conn) {
File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
final Properties dbProps;
if (EncryptionSecretKeyChecker.useEncryption()) {
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
dbProps = new EncryptableProperties(encryptor);
} else {
dbProps = new Properties();
}
try {
dbProps.load(new FileInputStream(dbPropsFile));
} catch (IOException e) {
s_logger.fatal("Unable to load db properties file, pl. check the classpath and file path configuration", e);
return;
} catch (NullPointerException e) {
s_logger.fatal("Unable to locate db properties file within classpath or absolute path: db.properties");
return;
}
final Properties dbProps = DbProperties.getDbProperties();
int region_id = 1;
String regionId = dbProps.getProperty("region.id");
if(regionId != null){

View File

@ -59,6 +59,7 @@ import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.ConnectionConcierge;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionLegacy;
@ -1029,15 +1030,7 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
s_logger.info("Start configuring cluster manager : " + name);
}
File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
Properties dbProps = new Properties();
try {
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
} catch (FileNotFoundException e) {
throw new ConfigurationException("Unable to find db.properties");
} catch (IOException e) {
throw new ConfigurationException("Unable to load db.properties content");
}
Properties dbProps = DbProperties.getDbProperties();
_clusterNodeIP = dbProps.getProperty("cluster.node.IP");
if (_clusterNodeIP == null) {
_clusterNodeIP = "127.0.0.1";

View File

@ -16,9 +16,6 @@
// under the License.
package com.cloud.cluster;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.Properties;
@ -26,14 +23,13 @@ import java.util.Properties;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.log4j.Logger;
import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.db.DbProperties;
public class ClusterServiceServletAdapter extends AdapterBase implements ClusterServiceAdapter {
@ -122,15 +118,7 @@ public class ClusterServiceServletAdapter extends AdapterBase implements Cluster
if (_mshostDao != null)
return;
File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
Properties dbProps = new Properties();
try {
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
} catch (FileNotFoundException e) {
throw new ConfigurationException("Unable to find db.properties");
} catch (IOException e) {
throw new ConfigurationException("Unable to load db.properties content");
}
Properties dbProps = DbProperties.getDbProperties();
_clusterServicePort = NumbersUtil.parseInt(dbProps.getProperty("cluster.servlet.port"), DEFAULT_SERVICE_PORT);
if (s_logger.isInfoEnabled())

View File

@ -93,12 +93,6 @@ public class TransactionLegacy {
} catch (Exception e) {
s_logger.error("Unable to register mbean for transaction", e);
}
/* FIXME: We need a better solution for this
* Initialize encryption if we need it for db.properties
*/
EncryptionSecretKeyChecker enc = new EncryptionSecretKeyChecker();
enc.check();
}
private final LinkedList<StackElement> _stack;
@ -1025,30 +1019,21 @@ public class TransactionLegacy {
static {
// Initialize with assumed db.properties file
initDataSource("db.properties");
initDataSource(DbProperties.getDbProperties());
}
public static void initDataSource(String propsFileName) {
try {
File dbPropsFile = PropertiesUtil.findConfigFile(propsFileName);
final Properties dbProps;
if (EncryptionSecretKeyChecker.useEncryption()) {
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
dbProps = new EncryptableProperties(encryptor);
} else {
dbProps = new Properties();
}
try {
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
dbProps.load(new FileInputStream(dbPropsFile));
} catch (IOException e) {
s_logger.fatal("Unable to load db properties file, pl. check the classpath and file path configuration", e);
return;
} catch (NullPointerException e) {
s_logger.fatal("Unable to locate db properties file within classpath or absolute path: " + propsFileName);
return;
}
public static void initDataSource(String propsFileName) throws IOException {
Properties dbProps = new Properties();
File dbPropsFile = PropertiesUtil.findConfigFile(propsFileName);
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
initDataSource(dbProps);
}
public static void initDataSource(Properties dbProps) {
try {
if (dbProps.size() == 0)
return;
// FIXME: If params are missing...default them????
final int cloudMaxActive = Integer.parseInt(dbProps.getProperty("db.cloud.maxActive"));
final int cloudMaxIdle = Integer.parseInt(dbProps.getProperty("db.cloud.maxIdle"));

View File

@ -17,7 +17,6 @@
package org.apache.cloudstack.framework.jobs.impl;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
@ -34,7 +33,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -54,25 +52,26 @@ import org.apache.cloudstack.jobs.JobInfo;
import org.apache.cloudstack.jobs.JobInfo.Status;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.log4j.Logger;
import com.cloud.cluster.ClusterManagerListener;
import com.cloud.cluster.ManagementServerHost;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Predicate;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionUtil;
@ -865,10 +864,7 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
try {
final File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
final Properties dbProps = new Properties();
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
final Properties dbProps = DbProperties.getDbProperties();
final int cloudMaxActive = Integer.parseInt(dbProps.getProperty("db.cloud.maxActive"));
int poolSize = (cloudMaxActive * 2) / 3;

View File

@ -30,6 +30,8 @@ import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.crypt.EncryptionSecretKeyChecker;
import com.cloud.utils.db.DbProperties;
import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
@ -43,6 +45,7 @@ import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -71,23 +74,7 @@ public class RegionManagerImpl extends ManagerBase implements RegionManager, Man
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
_name = name;
File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
final Properties dbProps;
if (EncryptionSecretKeyChecker.useEncryption()) {
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
dbProps = new EncryptableProperties(encryptor);
} else {
dbProps = new Properties();
}
try {
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
} catch (IOException e) {
s_logger.fatal("Unable to load db properties file, pl. check the classpath and file path configuration", e);
return false;
} catch (NullPointerException e) {
s_logger.fatal("Unable to locate db properties file within classpath or absolute path: db.properties");
return false;
}
final Properties dbProps = DbProperties.getDbProperties();
String regionId = dbProps.getProperty("region.id");
_id = 1;
if(regionId != null){

View File

@ -41,12 +41,12 @@ public class PropertiesUtil {
public static File findConfigFile(String path) {
ClassLoader cl = PropertiesUtil.class.getClassLoader();
URL url = cl.getResource(path);
if (url != null) {
if (url != null && "file".equals(url.getProtocol())) {
return new File(url.getFile());
}
url = ClassLoader.getSystemResource(path);
if (url != null) {
if (url != null && "file".equals(url.getProtocol())) {
return new File(url.getFile());
}
@ -57,12 +57,12 @@ public class PropertiesUtil {
String newPath = "conf" + (path.startsWith(File.separator) ? "" : "/") + path;
url = ClassLoader.getSystemResource(newPath);
if (url != null) {
if (url != null && "file".equals(url.getProtocol())) {
return new File(url.getFile());
}
url = cl.getResource(newPath);
if (url != null) {
if (url != null && "file".equals(url.getProtocol())) {
return new File(url.getFile());
}

View File

@ -16,18 +16,13 @@
// under the License.package com.cloud.utils.crypt;
package com.cloud.utils.crypt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.properties.EncryptableProperties;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.exception.CloudRuntimeException;
public class DBEncryptionUtil {
@ -69,27 +64,16 @@ public class DBEncryptionUtil {
}
return plain;
}
private static void initialize(){
final File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
final Properties dbProps;
final Properties dbProps = DbProperties.getDbProperties();
if(EncryptionSecretKeyChecker.useEncryption()){
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
dbProps = new EncryptableProperties(encryptor);
try {
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
} catch (FileNotFoundException e) {
throw new CloudRuntimeException("db.properties file not found while reading DB secret key", e);
} catch (IOException e) {
throw new CloudRuntimeException("Erroe while reading DB secret key from db.properties", e);
}
String dbSecretKey = dbProps.getProperty("db.cloud.encrypt.secret");
if(dbSecretKey == null || dbSecretKey.isEmpty()){
throw new CloudRuntimeException("Empty DB secret key in db.properties");
}
s_encryptor = new StandardPBEStringEncryptor();
s_encryptor.setAlgorithm("PBEWithMD5AndDES");
s_encryptor.setPassword(dbSecretKey);

View File

@ -27,20 +27,17 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import javax.ejb.Local;
import javax.annotation.PostConstruct;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.ComponentLifecycle;
import com.cloud.utils.component.SystemIntegrityChecker;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value = {SystemIntegrityChecker.class})
public class EncryptionSecretKeyChecker extends AdapterBase implements SystemIntegrityChecker {
public class EncryptionSecretKeyChecker {
private static final Logger s_logger = Logger.getLogger(EncryptionSecretKeyChecker.class);
@ -50,98 +47,92 @@ public class EncryptionSecretKeyChecker extends AdapterBase implements SystemInt
private static final String s_envKey = "CLOUD_SECRET_KEY";
private static StandardPBEStringEncryptor s_encryptor = new StandardPBEStringEncryptor();
private static boolean s_useEncryption = false;
public EncryptionSecretKeyChecker() {
setRunLevel(ComponentLifecycle.RUN_LEVEL_FRAMEWORK_BOOTSTRAP);
@PostConstruct
public void init() {
/* This will call DbProperties, which will call this to initialize the encryption. Yep,
* round about and annoying */
DbProperties.getDbProperties();
}
@Override
public void check() {
//Get encryption type from db.properties
final File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
final Properties dbProps = new Properties();
try {
PropertiesUtil.loadFromFile(dbProps, dbPropsFile);
public void check(Properties dbProps) throws IOException {
String encryptionType = dbProps.getProperty("db.cloud.encryption.type");
final String encryptionType = dbProps.getProperty("db.cloud.encryption.type");
s_logger.debug("Encryption Type: "+ encryptionType);
s_logger.debug("Encryption Type: "+ encryptionType);
if(encryptionType == null || encryptionType.equals("none")){
return;
}
if (s_useEncryption) {
s_logger.warn("Encryption already enabled, is check() called twice?");
return;
}
s_encryptor.setAlgorithm("PBEWithMD5AndDES");
String secretKey = null;
SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig();
if(encryptionType.equals("file")){
File keyFile = new File(s_keyFile);
if (!keyFile.exists()) {
keyFile = new File(s_altKeyFile);
}
try {
BufferedReader in = new BufferedReader(new FileReader(keyFile));
secretKey = in.readLine();
//Check for null or empty secret key
} catch (FileNotFoundException e) {
throw new CloudRuntimeException("File containing secret key not found: "+s_keyFile, e);
} catch (IOException e) {
throw new CloudRuntimeException("Error while reading secret key from: "+s_keyFile, e);
}
if(secretKey == null || secretKey.isEmpty()){
throw new CloudRuntimeException("Secret key is null or empty in file "+s_keyFile);
}
} else if(encryptionType.equals("env")){
secretKey = System.getenv(s_envKey);
if(secretKey == null || secretKey.isEmpty()){
throw new CloudRuntimeException("Environment variable "+s_envKey+" is not set or empty");
}
} else if(encryptionType.equals("web")){
ServerSocket serverSocket = null;
int port = 8097;
try {
serverSocket = new ServerSocket(port);
} catch (IOException ioex) {
throw new CloudRuntimeException("Error initializing secret key reciever", ioex);
}
s_logger.info("Waiting for admin to send secret key on port "+port);
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
throw new CloudRuntimeException("Accept failed on "+port);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
if ((inputLine = in.readLine()) != null) {
secretKey = inputLine;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
} else {
throw new CloudRuntimeException("Invalid encryption type: "+encryptionType);
}
stringConfig.setPassword(secretKey);
s_encryptor.setConfig(stringConfig);
s_useEncryption = true;
} catch (FileNotFoundException e) {
throw new CloudRuntimeException("File db.properties not found", e);
} catch (IOException e) {
throw new CloudRuntimeException("Error while reading db.properties", e);
if(encryptionType == null || encryptionType.equals("none")){
return;
}
if (s_useEncryption) {
s_logger.warn("Encryption already enabled, is check() called twice?");
return;
}
s_encryptor.setAlgorithm("PBEWithMD5AndDES");
String secretKey = null;
SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig();
if(encryptionType.equals("file")){
File keyFile = new File(s_keyFile);
if (!keyFile.exists()) {
keyFile = new File(s_altKeyFile);
}
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(keyFile));
secretKey = in.readLine();
//Check for null or empty secret key
} catch (FileNotFoundException e) {
throw new CloudRuntimeException("File containing secret key not found: "+s_keyFile, e);
} catch (IOException e) {
throw new CloudRuntimeException("Error while reading secret key from: "+s_keyFile, e);
} finally {
IOUtils.closeQuietly(in);
}
if(secretKey == null || secretKey.isEmpty()){
throw new CloudRuntimeException("Secret key is null or empty in file "+s_keyFile);
}
} else if(encryptionType.equals("env")){
secretKey = System.getenv(s_envKey);
if(secretKey == null || secretKey.isEmpty()){
throw new CloudRuntimeException("Environment variable "+s_envKey+" is not set or empty");
}
} else if(encryptionType.equals("web")){
ServerSocket serverSocket = null;
int port = 8097;
try {
serverSocket = new ServerSocket(port);
} catch (IOException ioex) {
throw new CloudRuntimeException("Error initializing secret key reciever", ioex);
}
s_logger.info("Waiting for admin to send secret key on port "+port);
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
throw new CloudRuntimeException("Accept failed on "+port);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
if ((inputLine = in.readLine()) != null) {
secretKey = inputLine;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
} else {
throw new CloudRuntimeException("Invalid encryption type: "+encryptionType);
}
stringConfig.setPassword(secretKey);
s_encryptor.setConfig(stringConfig);
s_useEncryption = true;
}
public static StandardPBEStringEncryptor getEncryptor() {
@ -160,15 +151,4 @@ public class EncryptionSecretKeyChecker extends AdapterBase implements SystemInt
s_encryptor.setConfig(stringConfig);
s_useEncryption = true;
}
@Override
public boolean start() {
try {
check();
} catch (Exception e) {
s_logger.error("System integrity check exception", e);
System.exit(1);
}
return true;
}
}

View File

@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package com.cloud.utils.db;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.properties.EncryptableProperties;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.crypt.EncryptionSecretKeyChecker;
public class DbProperties {
private static final Logger log = Logger.getLogger(DbProperties.class);
private static Properties properties = new Properties();
private static boolean loaded = false;
protected static Properties wrapEncryption(Properties dbProps) throws IOException {
EncryptionSecretKeyChecker checker = new EncryptionSecretKeyChecker();
checker.check(dbProps);
if ( EncryptionSecretKeyChecker.useEncryption() ) {
return dbProps;
} else {
EncryptableProperties encrProps = new EncryptableProperties(EncryptionSecretKeyChecker.getEncryptor());
encrProps.putAll(dbProps);
return encrProps;
}
}
public synchronized static Properties getDbProperties() {
if ( ! loaded ) {
Properties dbProps = new Properties();
InputStream is = null;
try {
File props = PropertiesUtil.findConfigFile("db.properties");
if ( props != null && props.exists() ) {
is = new FileInputStream(props);
}
if ( is == null ) {
is = PropertiesUtil.openStreamFromURL("db.properties");
}
if ( is == null ) {
System.err.println("Failed to find db.properties");
log.error("Failed to find db.properties");
}
dbProps.load(is);
EncryptionSecretKeyChecker checker = new EncryptionSecretKeyChecker();
checker.check(dbProps);
if (EncryptionSecretKeyChecker.useEncryption()) {
StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
EncryptableProperties encrDbProps = new EncryptableProperties(encryptor);
encrDbProps.putAll(dbProps);
dbProps = encrDbProps;
}
} catch ( IOException e ) {
throw new IllegalStateException("Failed to load db.properties", e);
} finally {
IOUtils.closeQuietly(is);
}
properties = dbProps;
loaded = true;
}
return properties;
}
public synchronized static Properties setDbProperties(Properties props) throws IOException {
if ( loaded ) {
throw new IllegalStateException("DbProperties has already been loaded");
}
properties = wrapEncryption(props);
loaded = true;
return properties;
}
}