You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2013/06/19 05:01:20 UTC
svn commit: r1494425 - in /incubator/ambari/trunk/ambari-server/src:
main/java/org/apache/ambari/server/configuration/
main/java/org/apache/ambari/server/controller/
main/java/org/apache/ambari/server/security/encryption/ main/python/
test/java/org/apa...
Author: swagle
Date: Wed Jun 19 03:01:19 2013
New Revision: 1494425
URL: http://svn.apache.org/r1494425
Log:
AMBARI-2397. Unencrypted master key stored in temporary file. (swagle)
Modified:
incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py
incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py
Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java Wed Jun 19 03:01:19 2013
@@ -36,6 +36,7 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -225,6 +226,7 @@ public class Configuration {
private Map<String, String> configsMap;
private CredentialProvider credentialProvider = null;
+ private volatile boolean credentialProviderInitialized = false;
public Configuration() {
this(readConfigFile());
@@ -311,8 +313,11 @@ public class Configuration {
}
}
- private void loadCredentialProvider() {
- if (credentialProvider == null) {
+ private synchronized void loadCredentialProvider() {
+ if (credentialProviderInitialized) {
+ return;
+ }
+ else {
try {
this.credentialProvider = new CredentialProvider(null,
getMasterKeyLocation(), isMasterKeyPersisted());
@@ -323,6 +328,7 @@ public class Configuration {
}
this.credentialProvider = null;
}
+ credentialProviderInitialized = true;
}
}
@@ -491,6 +497,7 @@ public class Configuration {
public String getDatabasePassword() {
String passwdProp = properties.getProperty(SERVER_JDBC_USER_PASSWD_KEY);
String dbpasswd = readPasswordFromStore(passwdProp);
+
if (dbpasswd != null)
return dbpasswd;
else
Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java Wed Jun 19 03:01:19 2013
@@ -114,6 +114,10 @@ public class AmbariServer {
}
public void run() throws Exception {
+ // Initialize meta info before heartbeat monitor
+ ambariMetaInfo.init();
+ LOG.info("********* Meta Info initialized **********");
+
performStaticInjection();
addInMemoryUsers();
server = new Server();
@@ -310,9 +314,6 @@ public class AmbariServer {
serverForAgent.setStopAtShutdown(true);
springAppContext.start();
- LOG.info("********* Initializing Meta Info **********");
- ambariMetaInfo.init();
-
String osType = getServerOsType();
if (osType == null || osType.isEmpty()) {
throw new RuntimeException(Configuration.OS_VERSION_KEY + " is not "
Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java Wed Jun 19 03:01:19 2013
@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -44,10 +45,6 @@ public class CredentialProvider {
public CredentialProvider(String masterKey, String masterKeyLocation,
boolean isMasterKeyPersisted) throws AmbariException {
- if (masterKeyLocation == null)
- throw new IllegalArgumentException("Master key location needed for " +
- "Credential Provider initialization.");
-
MasterKeyService masterKeyService;
if (masterKey != null) {
masterKeyService = new MasterKeyServiceImpl(masterKey);
@@ -75,8 +72,13 @@ public class CredentialProvider {
addAliasToCredentialStore(alias, passwordString);
}
- private void addAliasToCredentialStore(String alias, String passwordString)
+ public void addAliasToCredentialStore(String alias, String passwordString)
throws AmbariException {
+ if (alias == null || alias.isEmpty())
+ throw new IllegalArgumentException("Alias cannot be null or empty.");
+ if (passwordString == null || passwordString.isEmpty())
+ throw new IllegalArgumentException("Empty or null password not allowed" +
+ ".");
keystoreService.addCredential(alias, passwordString);
}
@@ -101,6 +103,10 @@ public class CredentialProvider {
strPasswd.length() - 1);
}
+ protected CredentialStoreService getKeystoreService() {
+ return keystoreService;
+ }
+
/**
* Credential Store entry point
* args[0] => Action (GET/PUT)
@@ -124,9 +130,10 @@ public class CredentialProvider {
System.exit(1);
}
// None - To avoid incorrectly assuming redirection as argument
- if (args.length > 3 && !args[2].isEmpty() && !args[2].equalsIgnoreCase
+ if (args.length > 3 && !args[3].isEmpty() && !args[3].equalsIgnoreCase
("None")) {
masterKey = args[3];
+ LOG.debug("Master key provided as an argument.");
}
try {
credentialProvider = new CredentialProvider(masterKey,
@@ -136,7 +143,7 @@ public class CredentialProvider {
ex.printStackTrace();
System.exit(1);
}
- LOG.info("action => " + action + ", alias =>" + alias);
+ LOG.info("action => " + action + ", alias => " + alias);
if (action.equalsIgnoreCase("PUT")) {
String password = null;
if (args.length > 2 && !args[2].isEmpty()) {
Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java Wed Jun 19 03:01:19 2013
@@ -59,6 +59,7 @@ public class CredentialStoreServiceImpl
final File keyStoreFile = new File(keyStoreDir + File.separator +
CREDENTIALS_SUFFIX);
+ LOG.debug("keystoreFile => " + keyStoreFile.getAbsolutePath());
if (!isCredentialStoreCreated) {
createCredentialStore();
}
@@ -95,8 +96,6 @@ public class CredentialStoreServiceImpl
if (ks != null && alias != null && !alias.isEmpty()) {
try {
LOG.debug("keystore = " + ks.aliases());
- LOG.debug("masterkey = " + new String(masterService.getMasterSecret()
- ));
Key key = ks.getKey(alias, masterService.getMasterSecret());
if (key == null) {
throw new AmbariException("Credential not found for alias: " +
Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java Wed Jun 19 03:01:19 2013
@@ -85,6 +85,8 @@ public class MasterKeyServiceImpl implem
* @param isPersisted
*/
public MasterKeyServiceImpl(String masterFileLocation, boolean isPersisted) {
+ if (masterFileLocation == null || masterFileLocation.isEmpty())
+ throw new IllegalArgumentException("Master Key location not provided.");
if (isPersisted) {
File masterFile = new File(masterFileLocation);
if (masterFile.exists()) {
@@ -104,8 +106,8 @@ public class MasterKeyServiceImpl implem
if (key != null) {
this.master = key.toCharArray();
} else {
- LOG.error("Master key: " + Configuration.MASTER_KEY_ENV_PROP + " is" +
- " not provided as a System property or an environment varialble.");
+ LOG.error("Master key is not provided as a System property or an " +
+ "environment varialble.");
}
}
}
@@ -146,11 +148,16 @@ public class MasterKeyServiceImpl implem
File keyFile = new File(keyPath);
if (keyFile.exists()) {
try {
- key = FileUtils.readFileToString(keyFile);
+ initializeFromFile(keyFile);
+ if (this.master != null)
+ key = new String(this.master);
FileUtils.deleteQuietly(keyFile);
} catch (IOException e) {
LOG.error("Cannot read master key from file: " + keyPath);
e.printStackTrace();
+ } catch (Exception e) {
+ LOG.error("Cannot read master key from file: " + keyPath);
+ e.printStackTrace();
}
}
}
@@ -205,10 +212,6 @@ public class MasterKeyServiceImpl implem
this.master = new String(aes.decrypt(Base64.decodeBase64(parts[0]),
Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])),
"UTF8").toCharArray();
- LOG.info("key: " + line);
- LOG.info("master: " + new String(aes.decrypt(Base64.decodeBase64(parts[0]),
- Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])),
- "UTF8"));
} catch (IOException e) {
e.printStackTrace();
throw e;
Modified: incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py (original)
+++ incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py Wed Jun 19 03:01:19 2013
@@ -1960,9 +1960,8 @@ def start(args):
masterKey = get_validated_string_input("Please provide master key " +\
"for unlocking credential store: ", "", ".*", "", False)
tempDir = tempfile.gettempdir()
- tempFilePath = tempDir + os.sep + "ambari.passwd"
- with open(tempFilePath, 'w+') as file:
- file.write(masterKey)
+ tempFilePath = tempDir + os.sep + "masterkey"
+ save_master_key(masterKey, tempFilePath, True)
os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
if tempFilePath is not None:
@@ -2300,7 +2299,7 @@ def setup_master_key(resetKey=False):
persist)
elif not persist and masterKeyFile is not None:
try:
- #os.remove(masterKeyFile)
+ os.remove(masterKeyFile)
print_warning_msg("Master key exists although security " +\
"is disabled. location: " + str(masterKeyFile))
except Exception, e:
@@ -2310,6 +2309,11 @@ def setup_master_key(resetKey=False):
update_properties({SECURITY_KEY_IS_PERSISTED : persist})
if resetKey:
+ # Blow up the credential store made with previous key
+ store_file = get_credential_store_location(properties)
+ if os.path.exists(store_file):
+ os.remove(store_file)
+
# Encrypt the passwords with new key
try:
db_password_alias = properties[JDBC_PASSWORD_PROPERTY]
@@ -2318,13 +2322,21 @@ def setup_master_key(resetKey=False):
print_warning_msg("KeyError: " + str(e))
if db_password_alias is not None and is_alias_string(db_password_alias):
- configure_database_password(True, False)
+ configure_database_password(True, key, True)
if ldap_password_alias is not None and is_alias_string(ldap_password_alias):
configure_ldap_password(True)
return key, True, persist
+def get_credential_store_location(properties):
+ store_loc = properties[SECURITY_KEYS_DIR]
+ if store_loc is None or store_loc == "":
+ store_loc = "/var/lib/ambari-server/keys/credentials.jceks"
+ else:
+ store_loc += os.sep + "credentials.jceks"
+ return store_loc
+
def get_master_key_location(properties):
keyLocation = properties[SECURITY_MASTER_KEY_LOCATION]
if keyLocation is None or keyLocation == "":
@@ -2374,7 +2386,7 @@ def read_passwd_for_alias(alias, masterK
os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
file.close()
- if masterKey is None:
+ if masterKey is None or masterKey == "":
masterKey = "None"
command = SECURITY_PROVIDER_GET_CMD.format(jdk_path,
@@ -2401,7 +2413,7 @@ def save_passwd_for_alias(alias, passwd,
"JDK manually to " + JDK_INSTALL_DIR)
return 1
- if masterKey is None:
+ if masterKey is None or masterKey == "":
masterKey = "None"
command = SECURITY_PROVIDER_PUT_CMD.format(jdk_path, get_conf_dir(),
Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java Wed Jun 19 03:01:19 2013
@@ -38,14 +38,14 @@ import static org.powermock.api.easymock
import static org.powermock.api.easymock.PowerMock.verifyAll;
@RunWith(PowerMockRunner.class)
-@PowerMockIgnore("javax.crypto.*")
+@PowerMockIgnore({"javax.crypto.*", "org.apache.log4j.*"})
@PrepareForTest({ MasterKeyServiceImpl.class })
public class MasterKeyServiceTest extends TestCase {
@Rule
public TemporaryFolder tmpFolder = new TemporaryFolder();
private String fileDir;
private static final Log LOG = LogFactory.getLog
- (CredentialStoreServiceTest.class);
+ (MasterKeyServiceTest.class);
@Override
protected void setUp() throws Exception {
@@ -70,7 +70,7 @@ public class MasterKeyServiceTest extend
}
@Test
- public void testReadFromEnv() throws Exception {
+ public void testReadFromEnvAsKey() throws Exception {
Map<String, String> mapRet = new HashMap<String, String>();
mapRet.put(Configuration.MASTER_KEY_ENV_PROP, "ThisisSomePassPhrase");
mockStatic(System.class);
@@ -84,6 +84,29 @@ public class MasterKeyServiceTest extend
new String(ms.getMasterSecret()));
}
+ @Test
+ public void testReadFromEnvAsPath() throws Exception {
+ // Create a master key
+ MasterKeyService ms = new MasterKeyServiceImpl("ThisisSomePassPhrase",
+ fileDir + File.separator + "master", true);
+ Assert.assertTrue(ms.isMasterKeyInitialized());
+ File f = new File(fileDir + File.separator + "master");
+ Assert.assertTrue(f.exists());
+
+ Map<String, String> mapRet = new HashMap<String, String>();
+ mapRet.put(Configuration.MASTER_KEY_LOCATION, f.getAbsolutePath());
+ mockStatic(System.class);
+ expect(System.getenv()).andReturn(mapRet);
+ replayAll();
+ ms = new MasterKeyServiceImpl();
+ verifyAll();
+ Assert.assertTrue(ms.isMasterKeyInitialized());
+ Assert.assertNotNull(ms.getMasterSecret());
+ Assert.assertEquals("ThisisSomePassPhrase",
+ new String(ms.getMasterSecret()));
+ Assert.assertFalse(f.exists());
+ }
+
@Override
protected void tearDown() throws Exception {
tmpFolder.delete();
Modified: incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py?rev=1494425&r1=1494424&r2=1494425&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py (original)
+++ incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py Wed Jun 19 03:01:19 2013
@@ -1299,6 +1299,7 @@ class TestAmbariServer(TestCase):
self.assertTrue(setup_db_mock.called)
+ @patch.object(ambari_server, 'save_master_key')
@patch('os.chmod', autospec=True)
@patch.object(ambari_server, 'get_validated_string_input')
@patch("os.environ")
@@ -1323,7 +1324,8 @@ class TestAmbariServer(TestCase):
print_error_msg_mock, find_jdk_mock, search_file_mock,
print_info_msg_mock, popenMock, openMock, pexistsMock,
killMock, get_ambari_properties_mock, os_environ_mock,
- get_validated_string_input_method, os_chmod_method):
+ get_validated_string_input_method, os_chmod_method,
+ save_master_key_method):
args = MagicMock()
f = MagicMock()
@@ -1487,6 +1489,7 @@ class TestAmbariServer(TestCase):
ambari_server.start(args)
self.assertFalse(get_validated_string_input_method.called)
+ self.assertFalse(save_master_key_method.called)
popen_arg = popenMock.call_args[1]['env']
self.assertEquals(os_environ_mock.copy.return_value, popen_arg)
@@ -1505,6 +1508,7 @@ class TestAmbariServer(TestCase):
ambari_server.start(args)
self.assertTrue(get_validated_string_input_method.called)
+ self.assertTrue(save_master_key_method.called)
popen_arg = popenMock.call_args[1]['env']
self.assertEquals(os_environ_mock.copy.return_value, popen_arg)