This is an automated email from the ASF dual-hosted git repository. smolnar 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 9c61584 AMBARI-24742. Encrypting/decrypting PASSWORD type properties when inserting them into the DB/using them (#2458) 9c61584 is described below commit 9c61584bba46820f506b8cecd480da912df2fa90 Author: Sandor Molnar <smol...@apache.org> AuthorDate: Fri Oct 19 17:52:36 2018 +0200 AMBARI-24742. Encrypting/decrypting PASSWORD type properties when inserting them into the DB/using them (#2458) --- .../ambari/server/configuration/Configuration.java | 11 ++ .../ambari/server/controller/ControllerModule.java | 5 + .../security/encryption/AESEncryptionService.java | 19 ++- .../encryption/ConfigPropertiesEncryptor.java | 127 +++++++++++++++++++++ .../server/security/encryption/Encryptor.java | 43 +++++++ .../org/apache/ambari/server/state/Cluster.java | 10 +- .../org/apache/ambari/server/state/Config.java | 5 + .../org/apache/ambari/server/state/ConfigImpl.java | 30 +++-- .../ambari/server/state/cluster/ClusterImpl.java | 9 +- .../ambari/server/agent/AgentResourceTest.java | 7 ++ .../KerberosAdminPersistedCredentialCheckTest.java | 2 +- .../server/controller/KerberosHelperTest.java | 2 +- .../internal/HostResourceProviderTest.java | 2 +- .../server/testutils/PartialNiceMockBinder.java | 12 ++ .../ambari/server/update/HostUpdateHelperTest.java | 3 +- .../server/upgrade/UpgradeCatalog251Test.java | 3 +- .../server/upgrade/UpgradeCatalog252Test.java | 3 +- .../server/upgrade/UpgradeCatalog260Test.java | 4 +- .../server/upgrade/UpgradeCatalog270Test.java | 2 +- 19 files changed, 279 insertions(+), 20 deletions(-) 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 d644c08..63c1777 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 @@ -2572,6 +2572,9 @@ public class Configuration { @Markdown(description = "Whether security password encryption is enabled or not. In case it is we store passwords in their own file(s); otherwise we store passwords in the Ambari credential store.") public static final ConfigurationProperty<Boolean> SECURITY_PASSWORD_ENCRYPTON_ENABLED = new ConfigurationProperty<>("security.passwords.encryption.enabled", false); + @Markdown(description="Whether to encrypt sensitive data (at rest) on service level configuration.") + public static final ConfigurationProperty<Boolean> SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED = new ConfigurationProperty<>("security.server.encrypt_sensitive_data", false); + /** * The maximum number of authentication attempts permitted to a local user. Once the number of failures reaches this limit the user will be locked out. 0 indicates unlimited failures */ @@ -5518,6 +5521,14 @@ public class Configuration { return Boolean.parseBoolean(getProperty(SECURITY_PASSWORD_ENCRYPTON_ENABLED)); } + public boolean isSensitiveDataEncryptionEnabled() { + return Boolean.parseBoolean(getProperty(SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED)); + } + + public boolean shouldEncryptSensitiveData() { + return isSecurityPasswordEncryptionEnabled() && isSensitiveDataEncryptionEnabled(); + } + /** * @return default value of number of tasks to run in parallel during upgrades */ diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index 176e709..2e60deb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -115,9 +115,11 @@ import org.apache.ambari.server.security.authorization.AuthorizationHelper; import org.apache.ambari.server.security.authorization.internal.InternalAuthenticationInterceptor; import org.apache.ambari.server.security.authorization.internal.RunWithInternalSecurityContext; import org.apache.ambari.server.security.encryption.AESEncryptionService; +import org.apache.ambari.server.security.encryption.ConfigPropertiesEncryptor; import org.apache.ambari.server.security.encryption.CredentialStoreService; import org.apache.ambari.server.security.encryption.CredentialStoreServiceImpl; import org.apache.ambari.server.security.encryption.EncryptionService; +import org.apache.ambari.server.security.encryption.Encryptor; import org.apache.ambari.server.serveraction.kerberos.KerberosOperationHandlerFactory; import org.apache.ambari.server.serveraction.users.CollectionPersisterService; import org.apache.ambari.server.serveraction.users.CollectionPersisterServiceFactory; @@ -179,6 +181,7 @@ import com.google.gson.GsonBuilder; import com.google.inject.AbstractModule; import com.google.inject.Scopes; import com.google.inject.Singleton; +import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.name.Names; import com.google.inject.persist.PersistModule; @@ -332,6 +335,8 @@ public class ControllerModule extends AbstractModule { bind(CredentialStoreService.class).to(CredentialStoreServiceImpl.class); bind(EncryptionService.class).to(AESEncryptionService.class); + //to support different Encryptor implementation we have to annotate them by their name and use them as @Named injects + bind(new TypeLiteral<Encryptor<Config>>() {}).annotatedWith(Names.named("ConfigPropertiesEncryptor")).to(ConfigPropertiesEncryptor.class); bind(Configuration.class).toInstance(configuration); bind(OsFamily.class).toInstance(os_family); 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 ffb92ba..25b3fc7 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 @@ -24,6 +24,8 @@ import org.apache.ambari.server.utils.TextEncoding; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.inject.Singleton; @Singleton @@ -32,6 +34,8 @@ public class AESEncryptionService implements EncryptionService { private static final String ENCODED_TEXT_FIELD_DELIMITER = "::"; private static final String UTF_8_CHARSET = StandardCharsets.UTF_8.name(); + private final Cache<String, AESEncryptor> aesEncryptorCache = CacheBuilder.newBuilder().build(); + private MasterKeyService environmentMasterKeyService; @Override @@ -51,11 +55,20 @@ public class AESEncryptionService implements EncryptionService { @Override public String encrypt(String toBeEncrypted, String key, TextEncoding textEncoding) throws Exception { - final AESEncryptor aes = new AESEncryptor(key); - final EncryptionResult encryptionResult = aes.encrypt(toBeEncrypted); + final EncryptionResult encryptionResult = getAesEncryptor(key).encrypt(toBeEncrypted); return TextEncoding.BASE_64 == textEncoding ? encodeEncryptionResultBase64(encryptionResult) : encodeEncryptionResultBinHex(encryptionResult); } + private AESEncryptor getAesEncryptor(String key) { + AESEncryptor aesEncryptor = aesEncryptorCache.getIfPresent(key); + if (aesEncryptor == null) { + aesEncryptor = new AESEncryptor(key); + aesEncryptorCache.put(key, aesEncryptor); + } + + return aesEncryptor; + } + private final String getAmbariMasterKey() { initEnvironmentMasterKeyService(); return String.valueOf(environmentMasterKeyService.getMasterSecret()); @@ -100,7 +113,7 @@ public class AESEncryptionService implements EncryptionService { final byte[] decodedValue = TextEncoding.BASE_64 == textEncoding ? Base64.decodeBase64(toBeDecrypted) : Hex.decodeHex(toBeDecrypted.toCharArray()); final String decodedText = new String(decodedValue, UTF_8_CHARSET); final String[] decodedParts = decodedText.split(ENCODED_TEXT_FIELD_DELIMITER); - final AESEncryptor aes = new AESEncryptor(key); + final AESEncryptor aes = getAesEncryptor(key); if (TextEncoding.BASE_64 == textEncoding) { return new String(aes.decrypt(Base64.decodeBase64(decodedParts[0]), Base64.decodeBase64(decodedParts[1]), Base64.decodeBase64(decodedParts[2])), UTF_8_CHARSET); } else { diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/ConfigPropertiesEncryptor.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/ConfigPropertiesEncryptor.java new file mode 100644 index 0000000..68710f4 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/ConfigPropertiesEncryptor.java @@ -0,0 +1,127 @@ +/* + * 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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * 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.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.AmbariRuntimeException; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Config; +import org.apache.ambari.server.state.PropertyInfo.PropertyType; +import org.apache.ambari.server.state.StackId; +import org.apache.ambari.server.utils.TextEncoding; +import org.apache.commons.collections.CollectionUtils; + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * {@link Encryptor} implementation for encrypting/decrypting PASSWORD type + * properties in {@link Config}'s properties + */ + +@Singleton +public class ConfigPropertiesEncryptor implements Encryptor<Config> { + + private static final String ENCRYPTED_PROPERTY_PREFIX = "${enc=aes256_hex, value="; + private static final String ENCRYPTED_PROPERTY_SCHEME = ENCRYPTED_PROPERTY_PREFIX + "%s}"; + + private final EncryptionService encryptionService; + private final Map<Long, Map<StackId, Map<String, Set<String>>>> clusterPasswordProperties = new ConcurrentHashMap<>(); //Map<clusterId, <Map<stackId, Map<configType, Set<passwordPropertyKeys>>>>; + + @Inject + public ConfigPropertiesEncryptor(EncryptionService encryptionService) { + this.encryptionService = encryptionService; + } + + @Override + public void encryptSensitiveData(Config config) { + try { + final Map<String, String> configProperties = config.getProperties(); + if (configProperties != null) { + final Set<String> passwordProperties = getPasswordProperties(config.getCluster(), config.getType()); + if (CollectionUtils.isNotEmpty(passwordProperties)) { + final Map<String, String> encryptedProperties = new HashMap<>(configProperties); + for (Map.Entry<String, String> property : configProperties.entrySet()) { + if (passwordProperties.contains(property.getKey()) && !isEncryptedPassword(property.getValue())) { + encryptedProperties.put(property.getKey(), encryptAndDecoratePropertyValue(property.getValue())); + } + } + config.setProperties(encryptedProperties); + } + } + } catch (Exception e) { + throw new AmbariRuntimeException("Error while encrypting sensitive data", e); + } + } + + private boolean isEncryptedPassword(String password) { + return password != null && password.startsWith(ENCRYPTED_PROPERTY_PREFIX); // assuming previous encryption by this class + } + + private Set<String> getPasswordProperties(Cluster cluster, String configType) throws AmbariException { + //in case of normal configuration change on the UI - or via the API - the current and desired stacks are equal + //in case of an upgrade they are different; in this case we want to get password properties from the desired stack + if (cluster.getCurrentStackVersion().equals(cluster.getDesiredStackVersion())) { + return getPasswordProperties(cluster, cluster.getCurrentStackVersion(), configType); + } else { + return getPasswordProperties(cluster, cluster.getDesiredStackVersion(), configType); + } + } + + private Set<String> getPasswordProperties(Cluster cluster, StackId stackId, String configType) { + final long clusterId = cluster.getClusterId(); + clusterPasswordProperties.computeIfAbsent(clusterId, v -> new ConcurrentHashMap<>()).computeIfAbsent(stackId, v -> new ConcurrentHashMap<>()) + .computeIfAbsent(configType, v -> cluster.getConfigPropertiesTypes(configType, stackId).getOrDefault(PropertyType.PASSWORD, new HashSet<>())); + return clusterPasswordProperties.get(clusterId).get(stackId).getOrDefault(configType, new HashSet<>()); + } + + private String encryptAndDecoratePropertyValue(String propertyValue) throws Exception { + final String encrypted = encryptionService.encrypt(propertyValue, TextEncoding.BIN_HEX); + return String.format(ENCRYPTED_PROPERTY_SCHEME, encrypted); + } + + @Override + public void decryptSensitiveData(Config config) { + final Map<String, String> configProperties = config.getProperties(); + if (configProperties != null) { + final Map<String, String> decryptedProperties = new HashMap<>(configProperties); + for (Map.Entry<String, String> property : configProperties.entrySet()) { + if (isEncryptedPassword(property.getValue())) { + decryptedProperties.put(property.getKey(), decryptProperty(property.getValue())); + } + } + config.setProperties(decryptedProperties); + } + } + + private String decryptProperty(String property) { + try { + // sample value: ${enc=aes256_hex, value=5248...303d} + final String encrypted = property.substring(ENCRYPTED_PROPERTY_PREFIX.length(), property.indexOf('}')); + return encryptionService.decrypt(encrypted, TextEncoding.BIN_HEX); + } catch (Exception e) { + throw new AmbariRuntimeException("Error while decrypting property", e); + } + } +} diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/Encryptor.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/Encryptor.java new file mode 100644 index 0000000..4fad723 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/Encryptor.java @@ -0,0 +1,43 @@ +/* + * 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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * 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; + +/** + * Defines a generic contract on encrypting/decrypting sensitive data + */ +public interface Encryptor<T> { + + /** + * Encrypts the given encryptible object + * + * @param encryptible + * to be encrypted + * @return the encrypted value + */ + void encryptSensitiveData(T encryptible); + + /** + * Decrypts the given decryptible object + * + * @param decryptible + * to be decrypted + * @return the decrypted value + */ + void decryptSensitiveData(T decryptible); + +} diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java index c201310..a150796 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java @@ -268,13 +268,21 @@ public interface Cluster { Map<String, Config> getConfigsByType(String configType); /** - * Gets all properties types that mach the specified type. + * Gets all properties types that matches the specified type for the current stack. * @param configType the config type to return * @return properties types for given config type */ Map<PropertyInfo.PropertyType, Set<String>> getConfigPropertiesTypes(String configType); /** + * Gets all properties types that matches the specified type for the given stack. + * @param configType the config type to return + * @param stackId the stack to scan properties for + * @return properties types for given config type + */ + Map<PropertyInfo.PropertyType, Set<String>> getConfigPropertiesTypes(String configType, StackId stackId); + + /** * Gets the specific config that matches the specified type and tag. This not * necessarily a DESIRED configuration that applies to a cluster. * @param configType the config type to find diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Config.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Config.java index c1a8dc1..d687e84 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/Config.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Config.java @@ -97,4 +97,9 @@ public interface Config { * Persist the configuration. */ void save(); + + /** + * @return the cluster where this config belongs to + */ + Cluster getCluster(); } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java index b3ff843..e04a6bb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java @@ -27,7 +27,9 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.ReadWriteLock; import javax.annotation.Nullable; +import javax.inject.Named; +import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.events.ClusterConfigChangedEvent; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.logging.LockFactory; @@ -37,11 +39,13 @@ import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.orm.entities.ClusterConfigEntity; import org.apache.ambari.server.orm.entities.ClusterEntity; import org.apache.ambari.server.orm.entities.StackEntity; +import org.apache.ambari.server.security.encryption.Encryptor; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; @@ -104,9 +108,10 @@ public class ConfigImpl implements Config { @Assisted Map<String, String> properties, @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes, ClusterDAO clusterDAO, StackDAO stackDAO, - Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory) { + Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory, + Configuration serverConfiguration, @Named("ConfigPropertiesEncryptor") Encryptor<Config> configPropertiesEncryptor) { this(cluster.getDesiredStackVersion(), cluster, type, tag, properties, propertiesAttributes, - clusterDAO, stackDAO, gson, eventPublisher, lockFactory); + clusterDAO, stackDAO, gson, eventPublisher, lockFactory, serverConfiguration, configPropertiesEncryptor); } @@ -116,20 +121,24 @@ public class ConfigImpl implements Config { @Assisted Map<String, String> properties, @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes, ClusterDAO clusterDAO, StackDAO stackDAO, - Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory) { + Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory, + Configuration serverConfiguration, @Named("ConfigPropertiesEncryptor") Encryptor<Config> configPropertiesEncryptor) { propertyLock = lockFactory.newReadWriteLock(PROPERTY_LOCK_LABEL); this.cluster = cluster; this.type = type; this.properties = properties; + if (serverConfiguration.shouldEncryptSensitiveData()) { + configPropertiesEncryptor.encryptSensitiveData(this); + } // only set this if it's non-null this.propertiesAttributes = null == propertiesAttributes ? null : new HashMap<>(propertiesAttributes); this.clusterDAO = clusterDAO; - this.gson = gson; + this.gson = new GsonBuilder().disableHtmlEscaping().create(); this.eventPublisher = eventPublisher; version = cluster.getNextConfigVersion(type); @@ -148,10 +157,10 @@ public class ConfigImpl implements Config { entity.setTag(this.tag); entity.setTimestamp(System.currentTimeMillis()); entity.setStack(stackEntity); - entity.setData(gson.toJson(properties)); + entity.setData(this.gson.toJson(this.properties)); if (null != propertiesAttributes) { - entity.setAttributes(gson.toJson(propertiesAttributes)); + entity.setAttributes(this.gson.toJson(propertiesAttributes)); } // when creating a brand new config without a backing entity, use the @@ -161,12 +170,13 @@ public class ConfigImpl implements Config { persist(entity); configId = entity.getConfigId(); + configPropertiesEncryptor.decryptSensitiveData(this); } @AssistedInject ConfigImpl(@Assisted Cluster cluster, @Assisted ClusterConfigEntity entity, ClusterDAO clusterDAO, Gson gson, AmbariEventPublisher eventPublisher, - LockFactory lockFactory) { + LockFactory lockFactory, @Named("ConfigPropertiesEncryptor") Encryptor<Config> configPropertiesEncryptor) { propertyLock = lockFactory.newReadWriteLock(PROPERTY_LOCK_LABEL); this.cluster = cluster; @@ -194,6 +204,7 @@ public class ConfigImpl implements Config { } properties = deserializedProperties; + configPropertiesEncryptor.decryptSensitiveData(this); } catch (JsonSyntaxException e) { LOG.error("Malformed configuration JSON stored in the database for {}/{}", entity.getType(), entity.getTag()); @@ -324,6 +335,11 @@ public class ConfigImpl implements Config { } @Override + public Cluster getCluster() { + return cluster; + } + + @Override public List<Long> getServiceConfigVersions() { return serviceConfigDAO.getServiceConfigVersionsByConfig(cluster.getClusterId(), type, version); } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java index eb1176e..4ca2caf 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java @@ -2548,8 +2548,15 @@ public class ClusterImpl implements Cluster { */ @Override public Map<PropertyInfo.PropertyType, Set<String>> getConfigPropertiesTypes(String configType){ + return getConfigPropertiesTypes(configType, getCurrentStackVersion()); + } + + /** + * {@inheritDoc} + */ + @Override + public Map<PropertyInfo.PropertyType, Set<String>> getConfigPropertiesTypes(String configType, StackId stackId) { try { - StackId stackId = getCurrentStackVersion(); StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion()); return stackInfo.getConfigPropertiesTypes(configType); } catch (AmbariException ignored) { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java index 37d5166..d992d4a 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java @@ -59,8 +59,12 @@ import org.apache.ambari.server.scheduler.ExecutionScheduler; import org.apache.ambari.server.scheduler.ExecutionSchedulerImpl; import org.apache.ambari.server.security.SecurityHelper; import org.apache.ambari.server.security.SecurityHelperImpl; +import org.apache.ambari.server.security.encryption.AESEncryptionService; +import org.apache.ambari.server.security.encryption.ConfigPropertiesEncryptor; import org.apache.ambari.server.security.encryption.CredentialStoreService; import org.apache.ambari.server.security.encryption.CredentialStoreServiceImpl; +import org.apache.ambari.server.security.encryption.EncryptionService; +import org.apache.ambari.server.security.encryption.Encryptor; import org.apache.ambari.server.stack.StackManagerFactory; import org.apache.ambari.server.stack.upgrade.orchestrate.UpgradeContextFactory; import org.apache.ambari.server.stageplanner.RoleGraphFactory; @@ -107,6 +111,7 @@ import com.google.gson.GsonBuilder; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.name.Names; import com.sun.jersey.api.client.Client; @@ -352,6 +357,8 @@ public class AgentResourceTest extends RandomPortJerseyTest { bind(AmbariManagementController.class).toInstance(createNiceMock(AmbariManagementController.class)); bind(KerberosHelper.class).toInstance(createNiceMock(KerberosHelper.class)); bind(MpackManagerFactory.class).toInstance(createNiceMock(MpackManagerFactory.class)); + bind(EncryptionService.class).to(AESEncryptionService.class); + bind(new TypeLiteral<Encryptor<Config>>() {}).annotatedWith(Names.named("ConfigPropertiesEncryptor")).to(ConfigPropertiesEncryptor.class); } private void installDependencies() { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/KerberosAdminPersistedCredentialCheckTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/KerberosAdminPersistedCredentialCheckTest.java index edea0a7..ff3be49 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/checks/KerberosAdminPersistedCredentialCheckTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/KerberosAdminPersistedCredentialCheckTest.java @@ -217,7 +217,7 @@ public class KerberosAdminPersistedCredentialCheckTest extends EasyMockSupport { @Override protected void configure() { PartialNiceMockBinder.newBuilder().addActionDBAccessorConfigsBindings().addFactoriesInstallBinding() - .build().configure(binder()); + .addPasswordEncryptorBindings().build().configure(binder()); bind(ExecutionScheduler.class).toInstance(createNiceMock(ExecutionSchedulerImpl.class)); bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class)); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java index 584eff9..c229eb2 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java @@ -238,7 +238,7 @@ public class KerberosHelperTest extends EasyMockSupport { @Override protected void configure() { PartialNiceMockBinder.newBuilder().addActionDBAccessorConfigsBindings().addFactoriesInstallBinding() - .build().configure(binder()); + .addPasswordEncryptorBindings().build().configure(binder()); bind(ActionDBAccessor.class).to(ActionDBAccessorImpl.class); bind(ExecutionScheduler.class).to(ExecutionSchedulerImpl.class); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java index 3659019..125a9e9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java @@ -1403,7 +1403,7 @@ public class HostResourceProviderTest extends EasyMockSupport { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { - PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().build().configure(binder()); + PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().addPasswordEncryptorBindings().build().configure(binder()); bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class)); bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class)); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/testutils/PartialNiceMockBinder.java b/ambari-server/src/test/java/org/apache/ambari/server/testutils/PartialNiceMockBinder.java index d87a335..94d64ac 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/testutils/PartialNiceMockBinder.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/testutils/PartialNiceMockBinder.java @@ -55,6 +55,8 @@ import org.apache.ambari.server.orm.dao.HostRoleCommandDAO; import org.apache.ambari.server.scheduler.ExecutionScheduler; import org.apache.ambari.server.scheduler.ExecutionSchedulerImpl; import org.apache.ambari.server.security.encryption.CredentialStoreService; +import org.apache.ambari.server.security.encryption.EncryptionService; +import org.apache.ambari.server.security.encryption.Encryptor; import org.apache.ambari.server.stack.StackManagerFactory; import org.apache.ambari.server.stack.upgrade.orchestrate.UpgradeContextFactory; import org.apache.ambari.server.stageplanner.RoleGraphFactory; @@ -90,6 +92,7 @@ import org.springframework.security.crypto.password.StandardPasswordEncoder; import com.google.inject.Binder; import com.google.inject.Module; +import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.name.Names; import com.google.inject.persist.UnitOfWork; @@ -153,6 +156,7 @@ public class PartialNiceMockBinder implements Module { }); addConfigsBindings(); addFactoriesInstallBinding(); + addPasswordEncryptorBindings(); return this; } @@ -206,6 +210,14 @@ public class PartialNiceMockBinder implements Module { return this; } + public Builder addPasswordEncryptorBindings() { + configurers.add((Binder binder) -> { + binder.bind(EncryptionService.class).toInstance(easyMockSupport.createNiceMock(EncryptionService.class)); + binder.bind(new TypeLiteral<Encryptor<Config>>() {}).annotatedWith(Names.named("ConfigPropertiesEncryptor")).toInstance(easyMockSupport.createNiceMock(Encryptor.class)); + }); + return this; + } + public Builder addHostRoleCommandsConfigsBindings() { configurers.add((Binder binder) -> { binder.bindConstant().annotatedWith(Names.named(HostRoleCommandDAO.HRC_STATUS_SUMMARY_CACHE_ENABLED)).to(true); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/update/HostUpdateHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/update/HostUpdateHelperTest.java index 9c438c9..028f888 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/update/HostUpdateHelperTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/update/HostUpdateHelperTest.java @@ -495,7 +495,8 @@ public class HostUpdateHelperTest { @Override protected void configure() { - PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().build().configure(binder()); + PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().addPasswordEncryptorBindings() + .build().configure(binder()); bind(DBAccessor.class).toInstance(dbAccessor); bind(EntityManager.class).toInstance(entityManager); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog251Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog251Test.java index 6ecea16..03437fa 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog251Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog251Test.java @@ -292,7 +292,8 @@ public class UpgradeCatalog251Test { Module module = new Module() { @Override public void configure(Binder binder) { - PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().build().configure(binder); + PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding() + .addPasswordEncryptorBindings().build().configure(binder); binder.bind(DBAccessor.class).toInstance(dbAccessor); binder.bind(OsFamily.class).toInstance(osFamily); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog252Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog252Test.java index 1d5168c..7dfee87 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog252Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog252Test.java @@ -440,7 +440,8 @@ public class UpgradeCatalog252Test { Module module = new Module() { @Override public void configure(Binder binder) { - PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().build().configure(binder); + PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding() + .addPasswordEncryptorBindings().build().configure(binder); binder.bind(DBAccessor.class).toInstance(dbAccessor); binder.bind(OsFamily.class).toInstance(osFamily); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java index ba09e97..02a45c2 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java @@ -1025,7 +1025,8 @@ public class UpgradeCatalog260Test { final Injector mockInjector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { - PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().build().configure(binder()); + PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding() + .addPasswordEncryptorBindings().build().configure(binder()); bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class)); bind(AmbariManagementController.class).toInstance(controller); @@ -1083,6 +1084,7 @@ public class UpgradeCatalog260Test { return Guice.createInjector(new Module() { @Override public void configure(Binder binder) { + PartialNiceMockBinder.newBuilder().addPasswordEncryptorBindings().build().configure(binder); binder.bindConstant().annotatedWith(Names.named("actionTimeout")).to(600000L); binder.bindConstant().annotatedWith(Names.named("schedulerSleeptime")).to(1L); binder.bindConstant().annotatedWith(Names.named(HostRoleCommandDAO.HRC_STATUS_SUMMARY_CACHE_ENABLED)).to(true); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java index c2096d5..6fa317b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java @@ -600,7 +600,7 @@ public class UpgradeCatalog270Test { Module module = new AbstractModule() { @Override public void configure() { - PartialNiceMockBinder.newBuilder().addConfigsBindings().addFactoriesInstallBinding().build().configure(binder()); + PartialNiceMockBinder.newBuilder().addConfigsBindings().addPasswordEncryptorBindings().addFactoriesInstallBinding().build().configure(binder()); bind(DBAccessor.class).toInstance(dbAccessor); bind(OsFamily.class).toInstance(osFamily);