This is an automated email from the ASF dual-hosted git repository.
dmitriusan pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 2bfbef2 AMBARI-24871. Create an Ambari-server class that is called as
an entr… (#2589)
2bfbef2 is described below
commit 2bfbef2cab3cac2c4720dca0942fed8d3efd9bc9
Author: Lisnichenko Dmitro <[email protected]>
AuthorDate: Thu Nov 15 19:36:30 2018 +0200
AMBARI-24871. Create an Ambari-server class that is called as an entr…
(#2589)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data (dlysnichenko)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data. Fix spelling
(dlysnichenko)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data. Address review comments
(dlysnichenko)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data. Address review comments
(dlysnichenko)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data. Fix DI and tests
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data. Revert some cleanup
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data. Add test (dlysnichenko)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data - fix tests
(dlyscnichenko)
* AMBARI-24871. Create an Ambari-server class that is called as an entry
point to encrypt service configuration sensitive data - fix rat check
(dlyscnichenko)
---
.../configuration/ComponentSSLConfiguration.java | 2 +-
.../ambari/server/configuration/Configuration.java | 6 +-
.../internal/AmbariServerConfigurationHandler.java | 3 +-
.../security/encryption/AESEncryptionService.java | 8 +-
.../security/encryption/CredentialProvider.java | 19 +--
.../encryption/CredentialStoreServiceImpl.java | 10 +-
.../security/encryption/MasterKeyServiceImpl.java | 41 ++++--
.../encryption/SensitiveDataEncryption.java | 142 ++++++++++++++++++
.../apache/ambari/server/utils/PasswordUtils.java | 17 ++-
.../server/configuration/ConfigurationTest.java | 6 +-
...ComponentConfigurationResourceProviderTest.java | 5 +-
.../encryption/CredentialProviderTest.java | 27 ++--
.../security/encryption/EncryptionServiceTest.java | 42 +++++-
.../security/encryption/MasterKeyServiceTest.java | 9 +-
.../encryption/SensitiveDataEncryptionTest.java | 161 +++++++++++++++++++++
.../ambari/server/utils/PasswordUtilsTest.java | 8 +-
16 files changed, 422 insertions(+), 84 deletions(-)
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/ComponentSSLConfiguration.java
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/ComponentSSLConfiguration.java
index a9d485f..81c64c7 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/ComponentSSLConfiguration.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/ComponentSSLConfiguration.java
@@ -118,7 +118,7 @@ public class ComponentSSLConfiguration {
private String getPassword(Configuration configuration) {
String rawPassword =
configuration.getProperty(Configuration.SSL_TRUSTSTORE_PASSWORD.getKey());
- String password =
PasswordUtils.getInstance().readPasswordFromStore(rawPassword,
configuration.getMasterKeyLocation(), configuration.isMasterKeyPersisted(),
configuration.getMasterKeyStoreLocation());
+ String password =
PasswordUtils.getInstance().readPasswordFromStore(rawPassword, configuration);
return password == null ? rawPassword : password;
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 63c1777..18ba439 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -2937,7 +2937,7 @@ public class Configuration {
System.setProperty(JAVAX_SSL_TRUSTSTORE,
getProperty(SSL_TRUSTSTORE_PATH));
}
if (getProperty(SSL_TRUSTSTORE_PASSWORD) != null) {
- String ts_password =
PasswordUtils.getInstance().readPasswordFromStore(getProperty(SSL_TRUSTSTORE_PASSWORD),
getMasterKeyLocation(), isMasterKeyPersisted(), getMasterKeyStoreLocation());
+ String ts_password =
PasswordUtils.getInstance().readPasswordFromStore(getProperty(SSL_TRUSTSTORE_PASSWORD),
this);
if (ts_password != null) {
System.setProperty(JAVAX_SSL_TRUSTSTORE_PASSWORD, ts_password);
} else {
@@ -3920,7 +3920,7 @@ public class Configuration {
String dbpasswd = null;
boolean isPasswordAlias = false;
if (CredentialProvider.isAliasString(passwdProp)) {
- dbpasswd = PasswordUtils.getInstance().readPasswordFromStore(passwdProp,
getMasterKeyLocation(), isMasterKeyPersisted(), getMasterKeyStoreLocation());
+ dbpasswd = PasswordUtils.getInstance().readPasswordFromStore(passwdProp,
this);
isPasswordAlias =true;
}
@@ -5794,7 +5794,7 @@ public class Configuration {
JETTY_THREAD_POOL("Jetty API & Agent Thread Pools");
/**
- * A decription of the grouping.
+ * A description of the grouping.
*/
private String m_description;
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
index e8b68ee..8bfd348 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
@@ -204,8 +204,7 @@ public class AmbariServerConfigurationHandler extends
RootServiceComponentConfig
private CredentialProvider getCredentialProvider() throws AmbariException {
if (credentialProvider == null) {
- credentialProvider = new CredentialProvider(null,
ambariConfiguration.getMasterKeyLocation(),
- ambariConfiguration.isMasterKeyPersisted(),
ambariConfiguration.getMasterKeyStoreLocation());
+ credentialProvider = new CredentialProvider(null, ambariConfiguration);
}
return credentialProvider;
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/AESEncryptionService.java
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/AESEncryptionService.java
index 25b3fc7..c92a752 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/AESEncryptionService.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/AESEncryptionService.java
@@ -20,6 +20,9 @@ package org.apache.ambari.server.security.encryption;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
+import javax.inject.Inject;
+
+import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.utils.TextEncoding;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
@@ -38,6 +41,9 @@ public class AESEncryptionService implements
EncryptionService {
private MasterKeyService environmentMasterKeyService;
+ @Inject
+ private Configuration configuration;
+
@Override
public String encrypt(String toBeEncrypted) throws Exception {
return encrypt(toBeEncrypted, TextEncoding.BASE_64);
@@ -76,7 +82,7 @@ public class AESEncryptionService implements
EncryptionService {
private void initEnvironmentMasterKeyService() {
if (environmentMasterKeyService == null) {
- environmentMasterKeyService = new MasterKeyServiceImpl();
+ environmentMasterKeyService = new MasterKeyServiceImpl(configuration);
if (!environmentMasterKeyService.isMasterKeyInitialized()) {
throw new SecurityException("You are trying to use a persisted master
key but its initialization has been failed!");
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
index ce0e843..7d7bb68 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
@@ -44,25 +44,17 @@ public class CredentialProvider {
private CredentialStore keystoreService;
private static final Logger LOG =
LoggerFactory.getLogger(CredentialProvider.class);
- public CredentialProvider(String masterKey, File masterKeyLocation,
- boolean isMasterKeyPersisted, File
masterKeyStoreLocation) throws AmbariException {
+ public CredentialProvider(String masterKey, Configuration configuration)
throws AmbariException {
MasterKeyService masterKeyService;
if (masterKey != null) {
masterKeyService = new MasterKeyServiceImpl(masterKey);
} else {
- if (isMasterKeyPersisted) {
- if (masterKeyLocation == null) {
- throw new IllegalArgumentException("The master key file location
must be specified if the master key is persisted");
- }
- masterKeyService = new MasterKeyServiceImpl(masterKeyLocation);
- } else {
- masterKeyService = new MasterKeyServiceImpl();
- }
+ masterKeyService = new MasterKeyServiceImpl(configuration);
}
if (!masterKeyService.isMasterKeyInitialized()) {
throw new AmbariException("Master key initialization failed.");
}
- this.keystoreService = new
FileBasedCredentialStore(masterKeyStoreLocation);
+ this.keystoreService = new
FileBasedCredentialStore(configuration.getMasterKeyStoreLocation());
this.keystoreService.setMasterKeyService(masterKeyService);
}
@@ -145,10 +137,7 @@ public class CredentialProvider {
LOG.debug("Master key provided as an argument.");
}
try {
- credentialProvider = new CredentialProvider(masterKey,
- configuration.getMasterKeyLocation(),
- configuration.isMasterKeyPersisted(),
- configuration.getMasterKeyStoreLocation());
+ credentialProvider = new CredentialProvider(masterKey, configuration);
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
index c36d21f..9fb2fe5 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
@@ -51,8 +51,6 @@ public class CredentialStoreServiceImpl implements
CredentialStoreService {
this.securePasswordHelper = securePasswordHelper;
if (configuration != null) {
- File masterKeyLocation = configuration.getMasterKeyLocation();
-
try {
initializeTemporaryCredentialStore(configuration.getTemporaryKeyStoreRetentionMinutes(),
TimeUnit.MINUTES,
@@ -63,15 +61,9 @@ public class CredentialStoreServiceImpl implements
CredentialStoreService {
LOG.error("Failed to initialize the temporary credential store.
Storage of temporary credentials will fail.", e);
}
-
// If the MasterKeyService is initialized, assume that we should be
initializing the persistent
// CredentialStore; else do not initialize it.
- MasterKeyService masterKeyService = null;
- if(masterKeyLocation.exists()) {
- masterKeyService = new MasterKeyServiceImpl(masterKeyLocation);
- } else {
- masterKeyService = new MasterKeyServiceImpl();
- }
+ MasterKeyService masterKeyService = new
MasterKeyServiceImpl(configuration);
if (masterKeyService.isMasterKeyInitialized()) {
try {
initializePersistedCredentialStore(configuration.getMasterKeyStoreLocation(),
masterKeyService);
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
index 8a8dd58..e0568f9 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
@@ -51,6 +51,10 @@ public class MasterKeyServiceImpl implements
MasterKeyService {
* @param masterKeyFile the location of the master key file
*/
public MasterKeyServiceImpl(File masterKeyFile) {
+ initFromFile(masterKeyFile);
+ }
+
+ private void initFromFile(File masterKeyFile) {
if (masterKeyFile == null) {
throw new IllegalArgumentException("Master Key location not provided.");
}
@@ -84,12 +88,22 @@ public class MasterKeyServiceImpl implements
MasterKeyService {
}
/**
- * Constructs a new MasterKeyServiceImpl using the master key found in the
environment.
+ * default constructor
+ */
+ public MasterKeyServiceImpl(){}
+
+ /**
+ * Constructs a new MasterKeyServiceImpl using prefered source according
config.
+ * masterKey > masterKeyLocation > environment
*/
- public MasterKeyServiceImpl() {
- String key = readMasterKey();
- if (key != null) {
- master = key.toCharArray();
+ public MasterKeyServiceImpl(Configuration configuration) {
+ if (configuration!= null && configuration.isMasterKeyPersisted()) {
+ if (configuration.getMasterKeyLocation() == null) {
+ throw new IllegalArgumentException("The master key file location must
be specified if the master key is persisted");
+ }
+ initFromFile(configuration.getMasterKeyLocation());
+ } else {
+ initializeFromEnv();
}
}
@@ -113,7 +127,7 @@ public class MasterKeyServiceImpl implements
MasterKeyService {
masterKeyLocation = args[1];
}
if (args.length > 2 && !args[2].isEmpty()) {
- persistMasterKey = args[2].toLowerCase().equals("true");
+ persistMasterKey = args[2].equalsIgnoreCase("true");
}
}
@@ -196,7 +210,7 @@ public class MasterKeyServiceImpl implements
MasterKeyService {
* @return true if the file is identitified as "master key" file; otherwise
false
*/
private static boolean isMasterKeyFile(File file) {
- try (FileReader reader = new FileReader(file);) {
+ try (FileReader reader = new FileReader(file)) {
char[] buffer = new char[MASTER_PERSISTENCE_TAG_PREFIX.length()];
return (reader.read(buffer) == buffer.length) && Arrays.equals(buffer,
MASTER_PERSISTENCE_TAG_PREFIX.toCharArray());
} catch (Exception e) {
@@ -243,8 +257,8 @@ public class MasterKeyServiceImpl implements
MasterKeyService {
}
}
- private String readMasterKey() {
- String key = null;
+ private void initializeFromEnv() {
+ String key;
Map<String, String> envVariables = System.getenv();
if (envVariables != null && !envVariables.isEmpty()) {
key = envVariables.get(Configuration.MASTER_KEY_ENV_PROP);
@@ -255,19 +269,18 @@ public class MasterKeyServiceImpl implements
MasterKeyService {
if (keyFile.exists()) {
try {
initializeFromFile(keyFile);
- if (master != null) {
- key = new String(master);
- }
- FileUtils.deleteQuietly(keyFile);
} catch (Exception e) {
LOG.error("Cannot read master key from file: " + keyPath);
e.printStackTrace();
}
}
+ } else {
+ LOG.error("Cannot read master key property {1} or master key file
property {3} from environment");
}
+ } else {
+ master = key.toCharArray();
}
}
- return key;
}
private void initializeFromFile(File masterFile) throws Exception {
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/SensitiveDataEncryption.java
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/SensitiveDataEncryption.java
new file mode 100644
index 0000000..1d4bdc9
--- /dev/null
+++
b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/SensitiveDataEncryption.java
@@ -0,0 +1,142 @@
+/*
+ * 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 org.apache.ambari.server.security.encryption;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.ambari.server.audit.AuditLoggerModule;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.ldap.LdapModule;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+import org.apache.ambari.server.utils.EventBusSynchronizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+
+/**
+ * Ambari-server class that is called as an entry point to encrypt service
configuration sensitive data
+ */
+public class SensitiveDataEncryption {
+ private static final Logger LOG = LoggerFactory.getLogger
+ (SensitiveDataEncryption.class);
+
+ private final PersistService persistService;
+ private final Injector injector;
+
+
+ @Inject
+ public SensitiveDataEncryption(Injector injector,
+ PersistService persistService) {
+ this.injector = injector;
+ this.persistService = persistService;
+ }
+
+ /**
+ * Extension of main controller module
+ */
+ private static class EncryptionHelperControllerModule extends
ControllerModule {
+
+ public EncryptionHelperControllerModule() throws Exception {
+ }
+
+ @Override
+ protected void configure() {
+ super.configure();
+ EventBusSynchronizer.synchronizeAmbariEventPublisher(binder());
+ }
+ }
+
+ /**
+ * Extension of audit logger module
+ */
+ private static class EncryptionHelperAuditModule extends AuditLoggerModule {
+
+ @Override
+ protected void configure() {
+ super.configure();
+ }
+
+ }
+
+ public void startPersistenceService() {
+ persistService.start();
+ }
+
+ public void stopPersistenceService() {
+ persistService.stop();
+ }
+
+ /**
+ * Iterates thought all configs and encryption/decryption sensitive
properties according to action
+ * using the default configured masterkey
+ * @param args "encryption" or "decryption" action expected
+ */
+ public static void main(String[] args) {
+ if (args.length < 1 || (!"encryption".equals(args[0]) &&
!"decryption".equals(args[0] ))){
+ LOG.error("The action parameter (\"encryption\" or \"decryption\") is
required");
+ System.exit(-1);
+ }
+ boolean encrypt = "encryption".equals(args[0]);
+ SensitiveDataEncryption sensitiveDataEncryption = null;
+ try {
+ Injector injector = Guice.createInjector(new
EncryptionHelperControllerModule(), new EncryptionHelperAuditModule(), new
LdapModule());
+ sensitiveDataEncryption =
injector.getInstance(SensitiveDataEncryption.class);
+ sensitiveDataEncryption.startPersistenceService();
+ sensitiveDataEncryption.doEncryption(encrypt);
+ } catch (Throwable e) {
+ LOG.error("Exception occurred during config encryption/decryption:", e);
+ } finally {
+ if (sensitiveDataEncryption != null) {
+ sensitiveDataEncryption.stopPersistenceService();
+ }
+ }
+ }
+
+ /**
+ * @param encrypt selects mode: true=encrypt, false=decrypt
+ */
+ public void doEncryption(boolean encrypt) {
+ AmbariManagementController ambariManagementController =
injector.getInstance(AmbariManagementController.class);
+ Encryptor<Config> configEncryptor =
injector.getInstance(ConfigPropertiesEncryptor.class);
+ Clusters clusters = ambariManagementController.getClusters();
+ if (clusters != null) {
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+ if (clusterMap != null && !clusterMap.isEmpty()) {
+ for (final Cluster cluster : clusterMap.values()) {
+ Collection<Config> configs = cluster.getAllConfigs();
+ for (Config config : configs) {
+ if (encrypt) {
+ configEncryptor.encryptSensitiveData(config);
+ } else {
+ configEncryptor.decryptSensitiveData(config);
+ }
+ config.save();
+ }
+ }
+ }
+ }
+ }
+}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/utils/PasswordUtils.java
b/ambari-server/src/main/java/org/apache/ambari/server/utils/PasswordUtils.java
index dafc47c..5c21503 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/utils/PasswordUtils.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/utils/PasswordUtils.java
@@ -125,7 +125,7 @@ public class PasswordUtils {
}
private String readPasswordFromStore(String aliasStr) {
- return readPasswordFromStore(aliasStr,
configuration.getMasterKeyLocation(), configuration.isMasterKeyPersisted(),
configuration.getMasterKeyStoreLocation());
+ return readPasswordFromStore(aliasStr, configuration);
}
/**
@@ -133,19 +133,20 @@ public class PasswordUtils {
*
* @param aliasStr
* the Credential Store alias you want to read the password for
- * @param masterKeyLocation
+ * @param configuration with configured master key:
+ * masterKeyLocation
* the master key location file
- * @param isMasterKeyPersisted
+ * isMasterKeyPersisted
* a flag indicating whether the master key is persisted
- * @param masterKeyStoreLocation
+ * masterKeyStoreLocation
* the master key-store location file
* @return the password of the given alias if it is not <code>blank</code>
and
* there is password stored for this alias in Credential Store;
* <code>null</code> otherwise
*/
- public String readPasswordFromStore(String aliasStr, File masterKeyLocation,
boolean isMasterKeyPersisted, File masterKeyStoreLocation) {
+ public String readPasswordFromStore(String aliasStr, Configuration
configuration) {
String password = null;
- loadCredentialProvider(masterKeyLocation, isMasterKeyPersisted,
masterKeyStoreLocation);
+ loadCredentialProvider(configuration);
if (credentialProvider != null) {
char[] result = null;
try {
@@ -166,11 +167,11 @@ public class PasswordUtils {
return password;
}
- private void loadCredentialProvider(File masterKeyLocation, boolean
isMasterKeyPersisted, File masterKeyStoreLocation) {
+ private void loadCredentialProvider(Configuration configuration) {
if (credentialProvider == null) {
try {
LOCK.lock();
- credentialProvider = new CredentialProvider(null, masterKeyLocation,
isMasterKeyPersisted, masterKeyStoreLocation);
+ credentialProvider = new CredentialProvider(null, configuration);
} catch (Exception e) {
LOG.info("Credential provider creation failed", e);
credentialProvider = null;
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
index b8d95c7..52ef289 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
@@ -231,7 +231,7 @@ public class ConfigurationTest {
String encrypted = "fake-encrypted-password";
ambariProperties.setProperty(Configuration.SSL_TRUSTSTORE_PASSWORD.getKey(),
unencrypted);
Configuration conf = spy(new Configuration(ambariProperties));
- PowerMock.stub(PowerMock.method(PasswordUtils.class,
"readPasswordFromStore", String.class, File.class, boolean.class,
File.class)).toReturn(null);
+ PowerMock.stub(PowerMock.method(PasswordUtils.class,
"readPasswordFromStore", String.class, Configuration.class)).toReturn(null);
conf.loadSSLParams();
Assert.assertEquals(System.getProperty(Configuration.JAVAX_SSL_TRUSTSTORE_PASSWORD,
"unknown"), unencrypted);
}
@@ -243,7 +243,7 @@ public class ConfigurationTest {
String encrypted = "fake-encrypted-password";
ambariProperties.setProperty(Configuration.SSL_TRUSTSTORE_PASSWORD.getKey(),
unencrypted);
Configuration conf = spy(new Configuration(ambariProperties));
- PowerMock.stub(PowerMock.method(PasswordUtils.class,
"readPasswordFromStore", String.class, File.class, boolean.class,
File.class)).toReturn(encrypted);
+ PowerMock.stub(PowerMock.method(PasswordUtils.class,
"readPasswordFromStore", String.class,
Configuration.class)).toReturn(encrypted);
conf.loadSSLParams();
Assert.assertEquals(System.getProperty(Configuration.JAVAX_SSL_TRUSTSTORE_PASSWORD,
"unknown"), encrypted);
}
@@ -289,7 +289,7 @@ public class ConfigurationTest {
passwordFile);
Configuration conf = new Configuration(ambariProperties);
-
PowerMock.stub(PowerMock.method(PasswordUtils.class,"readPasswordFromStore",
String.class, File.class, boolean.class, File.class)).toReturn(null);
+
PowerMock.stub(PowerMock.method(PasswordUtils.class,"readPasswordFromStore",
String.class, Configuration.class)).toReturn(null);
Assert.assertEquals("ambaritest", conf.getDatabasePassword());
}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
index 0576528..f84fcf6 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
@@ -527,11 +527,8 @@ public class
RootServiceComponentConfigurationResourceProviderTest extends EasyM
File masterKeyLocation = createNiceMock(File.class);
File masterKeyStoreLocation = createNiceMock(File.class);
-
expect(configuration.getMasterKeyLocation()).andReturn(masterKeyLocation).once();
- expect(configuration.isMasterKeyPersisted()).andReturn(false).once();
-
expect(configuration.getMasterKeyStoreLocation()).andReturn(masterKeyStoreLocation).once();
CredentialProvider credentialProvider =
PowerMock.createMock(CredentialProvider.class);
- PowerMock.expectNew(CredentialProvider.class, null, null,
masterKeyLocation, false, masterKeyStoreLocation).andReturn(credentialProvider);
+ PowerMock.expectNew(CredentialProvider.class, null, null,
configuration).andReturn(credentialProvider);
credentialProvider.addAliasToCredentialStore("currentPasswd", "newPasswd");
PowerMock.expectLastCall().once();
PowerMock.replay(credentialProvider, CredentialProvider.class);
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
index cded559..2207ac3 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
@@ -19,6 +19,7 @@ package org.apache.ambari.server.security.encryption;
import java.io.File;
import java.io.IOException;
+import java.util.Properties;
import org.apache.ambari.server.configuration.Configuration;
import org.junit.After;
@@ -52,21 +53,20 @@ public class CredentialProviderTest {
CredentialProvider cr;
File msFile = tmpFolder.newFile(Configuration.MASTER_KEY_FILENAME_DEFAULT);
File mksFile =
tmpFolder.newFile(Configuration.MASTER_KEYSTORE_FILENAME_DEFAULT);
- try {
- new CredentialProvider(null, null, true, null);
- Assert.fail("Expected an exception");
- } catch (Throwable t) {
- Assert.assertTrue(t instanceof IllegalArgumentException);
- }
- // Without master key persisted
- cr = new CredentialProvider("blahblah!", msFile, false, mksFile);
+ Configuration configuration = new Configuration(new Properties());
+ configuration.setProperty(Configuration.MASTER_KEY_LOCATION,
msFile.getParent());
+ configuration.setProperty(Configuration.MASTER_KEYSTORE_LOCATION,
mksFile.getParent());
+
+ // With master key persisted
+ createMasterKey();
+ cr = new CredentialProvider(null, configuration);
Assert.assertNotNull(cr);
Assert.assertNotNull(cr.getKeystoreService());
- // With master key persisted
msFile.delete();
mksFile.delete();
- createMasterKey();
- cr = new CredentialProvider(null, msFile, true, mksFile);
+ // Without master key persisted
+
+ cr = new CredentialProvider("blahblah!", configuration);
Assert.assertNotNull(cr);
Assert.assertNotNull(cr.getKeystoreService());
}
@@ -91,10 +91,13 @@ public class CredentialProviderTest {
public void testCredentialStore() throws Exception {
File msFile = tmpFolder.newFile(Configuration.MASTER_KEY_FILENAME_DEFAULT);
File mksFile =
tmpFolder.newFile(Configuration.MASTER_KEYSTORE_FILENAME_DEFAULT);
+ Configuration configuration = new Configuration(new Properties());
+ configuration.setProperty(Configuration.MASTER_KEY_LOCATION,
msFile.getParent());
+ configuration.setProperty(Configuration.MASTER_KEYSTORE_LOCATION,
mksFile.getParent());
// With master key persisted
createMasterKey();
- CredentialProvider cr = new CredentialProvider(null, msFile, true,
mksFile);
+ CredentialProvider cr = new CredentialProvider(null, configuration);
Assert.assertNotNull(cr);
Assert.assertNotNull(cr.getKeystoreService());
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/EncryptionServiceTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/EncryptionServiceTest.java
index 49bd871..ee0ba01 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/EncryptionServiceTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/EncryptionServiceTest.java
@@ -26,9 +26,12 @@ import static org.powermock.api.easymock.PowerMock.verifyAll;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
+import java.util.Properties;
import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.state.stack.OsFamily;
import org.apache.ambari.server.utils.TextEncoding;
+import org.easymock.EasyMock;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -37,6 +40,10 @@ import
org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
import junit.framework.Assert;
@RunWith(PowerMockRunner.class)
@@ -47,7 +54,6 @@ public class EncryptionServiceTest {
@Rule
private final TemporaryFolder tmpFolder = new TemporaryFolder();
- private final EncryptionService encryptionService = new
AESEncryptionService();
@Test
public void testEncryptAndDecryptUsingCustomKeyWithBase64Encoding() throws
Exception {
@@ -62,13 +68,43 @@ public class EncryptionServiceTest {
public void testEncryptAndDecryptUsingCustomKey(TextEncoding textEncoding)
throws Exception {
final String key = "mySuperS3cr3tMast3rKey!";
final String toBeEncrypted = "mySuperS3cr3tP4ssW0rD!";
+ EncryptionService encryptionService = new AESEncryptionService();
final String encrypted = encryptionService.encrypt(toBeEncrypted, key,
textEncoding);
final String decrypted = encryptionService.decrypt(encrypted, key,
textEncoding);
assertEquals(toBeEncrypted, decrypted);
}
@Test
- public void testEncryptAndDecryptUsingPersistedMasterKey() throws Exception {
+ public void testEncryptAndDecryptUsingPersistedMasterKey()throws Exception {
+ final String fileDir = tmpFolder.newFolder("keys").getAbsolutePath();
+ final File masterKeyFile = new File(fileDir, "master");
+ final String masterKey = "mySuperS3cr3tMast3rKey!";
+ final MasterKeyServiceImpl ms = new MasterKeyServiceImpl("dummyKey");
+ Assert.assertTrue(ms.initializeMasterKeyFile(masterKeyFile, masterKey));
+
+ final String toBeEncrypted = "mySuperS3cr3tP4ssW0rD!";
+
+ Configuration configuration = new Configuration(new Properties());
+ configuration.setProperty(Configuration.MASTER_KEY_LOCATION,
masterKeyFile.getParent());
+ Injector injector = Guice.createInjector(new AbstractModule() {
+
+ @Override
+ protected void configure() {
+ bind(Configuration.class).toInstance(configuration);
+ bind(OsFamily.class).toInstance(EasyMock.createMock(OsFamily.class));
+ }
+ });
+ EncryptionService encryptionService = new AESEncryptionService();
+ injector.injectMembers(encryptionService);
+
+ final String encrypted = encryptionService.encrypt(toBeEncrypted);
+ final String decrypted = encryptionService.decrypt(encrypted);
+ verifyAll();
+ assertEquals(toBeEncrypted, decrypted);
+ }
+
+ @Test
+ public void testEncryptAndDecryptUsingEnvDefinedMasterKey() throws Exception
{
final String fileDir = tmpFolder.newFolder("keys").getAbsolutePath();
final File masterKeyFile = new File(fileDir, "master");
final String masterKey = "mySuperS3cr3tMast3rKey!";
@@ -78,6 +114,7 @@ public class EncryptionServiceTest {
final String toBeEncrypted = "mySuperS3cr3tP4ssW0rD!";
setupEnvironmentVariableExpectations(masterKeyFile);
+ EncryptionService encryptionService = new AESEncryptionService();
final String encrypted = encryptionService.encrypt(toBeEncrypted);
final String decrypted = encryptionService.decrypt(encrypted);
verifyAll();
@@ -87,6 +124,7 @@ public class EncryptionServiceTest {
@Test(expected = SecurityException.class)
public void
shouldThrowSecurityExceptionInCaseOfEncryptingWithNonExistingPersistedMasterKey()
throws Exception {
final String toBeEncrypted = "mySuperS3cr3tP4ssW0rD!";
+ EncryptionService encryptionService = new AESEncryptionService();
encryptionService.encrypt(toBeEncrypted);
}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
index 032bb23..6d61950 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
@@ -28,6 +28,7 @@ import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashMap;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
import org.apache.ambari.server.configuration.Configuration;
@@ -101,7 +102,8 @@ public class MasterKeyServiceTest extends TestCase {
mockStatic(System.class);
expect(System.getenv()).andReturn(mapRet);
replayAll();
- MasterKeyService ms = new MasterKeyServiceImpl();
+ Configuration configuration = new Configuration(new Properties());
+ MasterKeyService ms = new MasterKeyServiceImpl(configuration);
verifyAll();
Assert.assertTrue(ms.isMasterKeyInitialized());
Assert.assertNotNull(ms.getMasterSecret());
@@ -125,12 +127,13 @@ public class MasterKeyServiceTest extends TestCase {
mockStatic(System.class);
expect(System.getenv()).andReturn(mapRet);
replayAll();
- ms = new MasterKeyServiceImpl();
+ Configuration configuration = new Configuration(new Properties());
+ ms = new MasterKeyServiceImpl(configuration);
verifyAll();
Assert.assertTrue(ms.isMasterKeyInitialized());
Assert.assertNotNull(ms.getMasterSecret());
Assert.assertEquals("ThisisSomePassPhrase", new
String(ms.getMasterSecret()));
- Assert.assertFalse(masterKeyFile.exists());
+ Assert.assertTrue(masterKeyFile.exists());
}
@Override
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/SensitiveDataEncryptionTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/SensitiveDataEncryptionTest.java
new file mode 100644
index 0000000..842b570
--- /dev/null
+++
b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/SensitiveDataEncryptionTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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 org.apache.ambari.server.security.encryption;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.stack.StackManagerFactory;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.easymock.EasyMockSupport;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+
+public class SensitiveDataEncryptionTest {
+
+
+ @Rule
+ public TemporaryFolder tmpFolder = new TemporaryFolder();
+
+ @Before
+ public void setUp() throws Exception {
+ tmpFolder.create();
+ }
+
+
+ @Test
+ public void testSensitiveDataEncryption() throws Exception {
+ EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+ final DBAccessor mockDBDbAccessor =
easyMockSupport.createNiceMock(DBAccessor.class);
+
+ final StackManagerFactory mockStackManagerFactory =
easyMockSupport.createNiceMock(StackManagerFactory.class);
+ final EntityManager mockEntityManager =
easyMockSupport.createNiceMock(EntityManager.class);
+ final Clusters mockClusters =
easyMockSupport.createNiceMock(Clusters.class);
+ final AmbariManagementController mockAmbariManagementController =
easyMockSupport.createNiceMock(AmbariManagementController.class);
+ final OsFamily mockOSFamily =
easyMockSupport.createNiceMock(OsFamily.class);
+ final ConfigPropertiesEncryptor mockConfigPropertiesEncryptor =
easyMockSupport.createNiceMock(ConfigPropertiesEncryptor.class);
+ final Injector mockInjector = createInjector(mockDBDbAccessor,
mockStackManagerFactory,
+ mockEntityManager, mockClusters, mockAmbariManagementController,
mockOSFamily, mockConfigPropertiesEncryptor);
+
+ Map<String, Cluster> clusters = new HashMap<>();
+ Cluster cluster = easyMockSupport.createStrictMock(Cluster.class);
+ clusters.put("c1", cluster);
+
expect(mockAmbariManagementController.getClusters()).andReturn(mockClusters).once();
+ expect(mockClusters.getClusters()).andReturn(clusters).once();
+
+ List<Config> configs = new ArrayList<Config>();
+ Config config = easyMockSupport.createStrictMock(Config.class);
+ configs.add(config);
+ expect(cluster.getAllConfigs()).andReturn(configs).once();
+
+ mockConfigPropertiesEncryptor.encryptSensitiveData(config);
+
+ config.save();
+ expectLastCall();
+
+ final PersistService mockPersistService =
easyMockSupport.createNiceMock(PersistService.class);
+ SensitiveDataEncryption sensitiveDataEncryption = new
SensitiveDataEncryption(mockInjector, mockPersistService);
+
+ easyMockSupport.replayAll();
+
+ sensitiveDataEncryption.doEncryption(true);
+
+ easyMockSupport.verifyAll();
+ }
+
+
+ @Test
+ public void testSensitiveDataDecryption() throws Exception {
+ EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+ final DBAccessor mockDBDbAccessor =
easyMockSupport.createNiceMock(DBAccessor.class);
+
+ final StackManagerFactory mockStackManagerFactory =
easyMockSupport.createNiceMock(StackManagerFactory.class);
+ final EntityManager mockEntityManager =
easyMockSupport.createNiceMock(EntityManager.class);
+ final Clusters mockClusters =
easyMockSupport.createNiceMock(Clusters.class);
+ final AmbariManagementController mockAmbariManagementController =
easyMockSupport.createNiceMock(AmbariManagementController.class);
+ final OsFamily mockOSFamily =
easyMockSupport.createNiceMock(OsFamily.class);
+ final ConfigPropertiesEncryptor mockConfigPropertiesEncryptor =
easyMockSupport.createNiceMock(ConfigPropertiesEncryptor.class);
+ final Injector mockInjector = createInjector(mockDBDbAccessor,
mockStackManagerFactory,
+ mockEntityManager, mockClusters, mockAmbariManagementController,
mockOSFamily, mockConfigPropertiesEncryptor);
+
+ Map<String, Cluster> clusters = new HashMap<>();
+ Cluster cluster = easyMockSupport.createStrictMock(Cluster.class);
+ clusters.put("c1", cluster);
+
expect(mockAmbariManagementController.getClusters()).andReturn(mockClusters).once();
+ expect(mockClusters.getClusters()).andReturn(clusters).once();
+
+ List<Config> configs = new ArrayList<Config>();
+ Config config = easyMockSupport.createStrictMock(Config.class);
+ configs.add(config);
+ expect(cluster.getAllConfigs()).andReturn(configs).once();
+
+ mockConfigPropertiesEncryptor.decryptSensitiveData(config);
+
+ config.save();
+ expectLastCall();
+
+ final PersistService mockPersistService =
easyMockSupport.createNiceMock(PersistService.class);
+ SensitiveDataEncryption sensitiveDataEncryption = new
SensitiveDataEncryption(mockInjector, mockPersistService);
+
+ easyMockSupport.replayAll();
+
+ sensitiveDataEncryption.doEncryption(false);
+
+ easyMockSupport.verifyAll();
+ }
+
+ private Injector createInjector(DBAccessor mockDBDbAccessor,
StackManagerFactory mockStackManagerFactory,
+ EntityManager mockEntityManager, Clusters
mockClusters,
+ AmbariManagementController
mockAmbariManagementController, OsFamily mockOSFamily,
+ ConfigPropertiesEncryptor
mockConfigPropertiesEncryptor) {
+ return Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+ bind(EntityManager.class).toInstance(mockEntityManager);
+ bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+ bind(Clusters.class).toInstance(mockClusters);
+ bind(OsFamily.class).toInstance(mockOSFamily);
+
bind(AmbariManagementController.class).toInstance(mockAmbariManagementController);
+
bind(ConfigPropertiesEncryptor.class).toInstance(mockConfigPropertiesEncryptor);
+ }
+ });
+ }
+
+}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/utils/PasswordUtilsTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/utils/PasswordUtilsTest.java
index b18ebd3..bee4d04 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/utils/PasswordUtilsTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/utils/PasswordUtilsTest.java
@@ -18,7 +18,6 @@
package org.apache.ambari.server.utils;
-import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import java.io.File;
@@ -105,12 +104,7 @@ public class PasswordUtilsTest extends EasyMockSupport {
}
private void setupBasicCredentialProviderExpectations(CredentialProvider
credentialProvider) throws Exception {
- final File masterKeyLocation = createNiceMock(File.class);
- final File masterKeyStoreLocation = createNiceMock(File.class);
-
expect(configuration.getMasterKeyLocation()).andReturn(masterKeyLocation).once();
- expect(configuration.isMasterKeyPersisted()).andReturn(false).once();
-
expect(configuration.getMasterKeyStoreLocation()).andReturn(masterKeyStoreLocation).once();
- PowerMock.expectNew(CredentialProvider.class, null, (String) null,
masterKeyLocation, false, masterKeyStoreLocation).andReturn(credentialProvider);
+ PowerMock.expectNew(CredentialProvider.class, null, null,
configuration).andReturn(credentialProvider);
}
private Injector createInjector() {