This is an automated email from the ASF dual-hosted git repository. rlevas 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 3b5343e [AMBARI-24955] Create Tproxy configuration provider and supporting infrastructure 3b5343e is described below commit 3b5343e14a9f9b5c103f4f2280ea735670dc8fd8 Author: Robert Levas <rle...@users.noreply.github.com> AuthorDate: Thu Nov 29 14:52:57 2018 -0500 [AMBARI-24955] Create Tproxy configuration provider and supporting infrastructure * [AMBARI-24955] Create Tproxy configuration provider and supporting infrastructure * [AMBARI-24955] Create Tproxy configuration provider and supporting infrastructure - removed unused method --- .../ambari/server/api/AmbariErrorHandler.java | 2 +- .../configuration/AmbariServerConfiguration.java | 68 +++++++++ .../AmbariServerConfigurationKey.java | 6 +- .../AmbariServerConfigurationProvider.java | 160 ++++++++++++++++++++ .../configuration/spring/GuiceBeansConfig.java | 6 + .../ambari/server/controller/AmbariServer.java | 2 +- .../ldap/domain/AmbariLdapConfiguration.java | 42 ++---- .../service/AmbariLdapConfigurationProvider.java | 94 ++---------- .../ambari/server/orm/GuiceJpaInitializer.java | 39 +++-- .../jwt/AmbariJwtAuthenticationFilter.java | 10 +- .../jwt/JwtAuthenticationProperties.java | 68 ++++++++- .../jwt/JwtAuthenticationPropertiesProvider.java | 151 ++----------------- .../tproxy/AmbariTProxyConfiguration.java | 117 +++++++++++++++ .../tproxy/AmbariTProxyConfigurationProvider.java | 62 ++++++++ .../ambari/server/upgrade/SchemaUpgradeHelper.java | 3 +- .../ambari/server/agent/AgentResourceTest.java | 2 + .../ambari/server/api/AmbariErrorHandlerTest.java | 2 +- .../AmbariServerConfigurationProviderTest.java | 166 +++++++++++++++++++++ .../AmbariServerConfigurationTest.java | 52 +++++++ .../server/controller/KerberosHelperTest.java | 2 + .../GroupPrivilegeResourceProviderTest.java | 2 + .../PreUpgradeCheckResourceProviderTest.java | 2 + .../StackUpgradeConfigurationMergeTest.java | 3 +- .../UserAuthorizationResourceProviderTest.java | 3 + .../UserPrivilegeResourceProviderTest.java | 2 + .../internal/UserResourceProviderTest.java | 3 + .../server/orm/InMemoryDefaultTestModule.java | 3 + .../AbstractAuthenticationProviderTest.java | 2 + .../jwt/AmbariJwtAuthenticationFilterTest.java | 28 ++-- .../jwt/JwtAuthenticationPropertiesTest.java | 8 +- .../pam/AmbariPamAuthenticationProviderTest.java | 2 + .../AmbariTProxyConfigurationProviderTest.java | 71 +++++++++ .../tproxy/AmbariTProxyConfigurationTest.java | 70 +++++++++ .../AmbariAuthorizationFilterTest.java | 2 + .../server/security/authorization/TestUsers.java | 27 ++-- .../server/security/authorization/UsersTest.java | 2 + .../AbstractPrepareKerberosServerActionTest.java | 2 + .../server/testutils/PartialNiceMockBinder.java | 6 +- 38 files changed, 984 insertions(+), 308 deletions(-) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java index f7c2bfa..9f69c60 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java @@ -75,7 +75,7 @@ public class AmbariErrorHandler extends ErrorHandler { if ((code == HttpServletResponse.SC_FORBIDDEN) || (code == HttpServletResponse.SC_UNAUTHORIZED)) { //if SSO is configured we should provide info about it in case of access error - JwtAuthenticationProperties jwtProperties = jwtAuthenticationPropertiesProvider.getProperties(); + JwtAuthenticationProperties jwtProperties = jwtAuthenticationPropertiesProvider.get(); if ((jwtProperties != null) && jwtProperties.isEnabledForAmbari()) { String providerUrl = jwtProperties.getAuthenticationProviderUrl(); String originalUrl = jwtProperties.getOriginalUrlQueryParam(); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfiguration.java new file mode 100644 index 0000000..fdffae7 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfiguration.java @@ -0,0 +1,68 @@ +/* + * 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.configuration; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * AmbariServerConfiguration is an abstract class to be extended by Ambari server configuration classes + * that encapsulate difference configuration categories such as 'ldap-configuration' and 'sso-configuration'. + * + * @see AmbariServerConfigurationCategory + * @see AmbariServerConfigurationKey + */ +public abstract class AmbariServerConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerConfiguration.class); + + /** + * Gets the configuration value for given {@link AmbariServerConfigurationKey}. + * <p> + * If no value is found in the supplied configuration map, the default value will be returned. + * + * @param ambariServerConfigurationKey the {@link AmbariServerConfigurationKey} for which to retrieve a value + * @param configurationMap a map of configuration property names to values + * @return the requested configuration value + */ + protected String getValue(AmbariServerConfigurationKey ambariServerConfigurationKey, Map<String, String> configurationMap) { + return getValue(ambariServerConfigurationKey.key(), configurationMap, ambariServerConfigurationKey.getDefaultValue()); + } + + /** + * Gets the configuration value for given {@link AmbariServerConfigurationKey}. + * <p> + * If no value is found in the supplied configuration map, the default value will be returned. + * + * @param propertyName the property name for which to retrieve a value + * @param configurationMap a map of configuration property names to values + * @param defaultValue the default value to use in the event the propery was not set in the configuration map + * @return the requested configuration value + */ + protected String getValue(String propertyName, Map<String, String> configurationMap, String defaultValue) { + if ((configurationMap != null) && configurationMap.containsKey(propertyName)) { + return configurationMap.get(propertyName); + } else { + LOGGER.debug("Ambari server configuration property [{}] hasn't been set; using default value", propertyName); + return defaultValue; + } + } + +} diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationKey.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationKey.java index a0b66f9..7c9d874 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationKey.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationKey.java @@ -101,9 +101,9 @@ public enum AmbariServerConfigurationKey { * Trusted Proxy Configuration Keys * ******************************************************** */ TPROXY_AUTHENTICATION_ENABLED(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari.tproxy.authentication.enabled", PLAINTEXT, "false", "Determines whether to allow a proxy user to specifiy a proxied user when logging into Ambari.", false), - TPROXY_ALLOWED_HOSTS(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari\\.tproxy\\.proxyuser\\..+\\.hosts", PLAINTEXT, "*", "List of hosts from which trusted-proxy user can connect.", true), - TPROXY_ALLOWED_USERS(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari\\.tproxy\\.proxyuser\\..+\\.users", PLAINTEXT, "*", "List of users which the trusted-proxy user can proxy for.", true), - TPROXY_ALLOWED_GROUPS(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari\\.tproxy\\.proxyuser\\..+\\.groups", PLAINTEXT, "*", "List of groups which the trusted-proxy user can proxy user for.", true); + TPROXY_ALLOWED_HOSTS(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari\\.tproxy\\.proxyuser\\..+\\.hosts", PLAINTEXT, "", "List of hosts from which trusted-proxy user can connect.", true), + TPROXY_ALLOWED_USERS(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari\\.tproxy\\.proxyuser\\..+\\.users", PLAINTEXT, "", "List of users which the trusted-proxy user can proxy for.", true), + TPROXY_ALLOWED_GROUPS(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, "ambari\\.tproxy\\.proxyuser\\..+\\.groups", PLAINTEXT, "", "List of groups which the trusted-proxy user can proxy user for.", true); private static final Logger LOG = LoggerFactory.getLogger(AmbariServerConfigurationKey.class); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationProvider.java new file mode 100644 index 0000000..d4f31e8 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/AmbariServerConfigurationProvider.java @@ -0,0 +1,160 @@ +/* + * 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.configuration; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.ambari.server.events.AmbariConfigurationChangedEvent; +import org.apache.ambari.server.events.JpaInitializedEvent; +import org.apache.ambari.server.events.publishers.AmbariEventPublisher; +import org.apache.ambari.server.orm.GuiceJpaInitializer; +import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO; +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.eventbus.Subscribe; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * AmbariServerConfigurationProvider is an abstract class to be extended by Ambari server configuration + * provider classes. + * <p> + * This implementation registers for the following Ambari server events to help load the relevant properties + * when available and/or updated: + * + * <ul> + * <li>AmbariConfigurationChangedEvent</li> + * <li>JpaInitializedEvent</li> + * </ul> + */ +public abstract class AmbariServerConfigurationProvider<T extends AmbariServerConfiguration> implements Provider<T> { + private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerConfigurationProvider.class); + + @Inject + private Provider<AmbariConfigurationDAO> ambariConfigurationDAOProvider; + + private final AtomicBoolean jpaInitialized = new AtomicBoolean(false); + + private final AmbariServerConfigurationCategory configurationCategory; + + private T instance = null; + + protected AmbariServerConfigurationProvider(AmbariServerConfigurationCategory configurationCategory, AmbariEventPublisher publisher, GuiceJpaInitializer guiceJpaInitializer) { + this.configurationCategory = configurationCategory; + + if (publisher != null) { + publisher.register(this); + LOGGER.info("Registered {} in event publisher", this.getClass().getName()); + } + + if (guiceJpaInitializer != null) { + jpaInitialized.set(guiceJpaInitializer.isInitialized()); + } + } + + /** + * Upon receiving this event, if the expected configuration category has been updated, the data is + * reloaded. + * + * @param event the received {@link AmbariConfigurationChangedEvent} + */ + @Subscribe + public void ambariConfigurationChanged(AmbariConfigurationChangedEvent event) { + if (configurationCategory.getCategoryName().equalsIgnoreCase(event.getCategoryName())) { + LOGGER.info("Ambari configuration changed event received: {}", event); + instance = loadInstance(); + } + } + + /** + * Upon receiving this event, the JPA infrastructure has completed initialization and the relevant + * data may be retrieved. + * + * @param event the received {@link JpaInitializedEvent} + */ + @Subscribe + public void jpaInitialized(JpaInitializedEvent event) { + LOGGER.info("JPA initialized event received: {}", event); + jpaInitialized.getAndSet(true); + instance = loadInstance(); + } + + @Override + public T get() { + LOGGER.debug("Getting {} configuration...", configurationCategory.getCategoryName()); + if (instance == null) { + instance = loadInstance(); + } + return instance; + } + + /** + * Attempts to load the relevant configuration data. + * <p> + * If the JPA infrastructure has not been initialized, return the instance data that has already + * been set up or (if null) requests an empty instance. + * + * @return the loaded instance data + */ + private T loadInstance() { + if (jpaInitialized.get()) { + LOGGER.info("Loading {} configuration data", configurationCategory.getCategoryName()); + return loadInstance(ambariConfigurationDAOProvider.get().findByCategory(configurationCategory.getCategoryName())); + } else { + LOGGER.info("Cannot load {} configuration data since JPA is not initialized", configurationCategory.getCategoryName()); + if (instance == null) { + return loadInstance(Collections.emptyList()); + } else { + return instance; + } + } + } + + /** + * Converts a collection of {@link AmbariConfigurationEntity}s into a map of property names to values. + * + * @param configurationEntities the collection of {@link AmbariConfigurationEntity}s to process + * @return a map of property names to values; or an empty map if no entities are available to process + */ + protected Map<String, String> toProperties(Collection<AmbariConfigurationEntity> configurationEntities) { + Map<String, String> map = new HashMap<>(); + + if (configurationEntities != null) { + for (AmbariConfigurationEntity entity : configurationEntities) { + map.put(entity.getPropertyName(), entity.getPropertyValue()); + } + } + + return map; + } + + /** + * Returns a instance of the data configuration container implementation filled with data from the + * supplied collection of {@link AmbariConfigurationEntity}s + * + * @param configurationEntities a collection of {@link AmbariConfigurationEntity}s + * @return an instance of the data configuration container implementation + */ + protected abstract T loadInstance(Collection<AmbariConfigurationEntity> configurationEntities); +} diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/GuiceBeansConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/GuiceBeansConfig.java index 3e9e273..2c13cf2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/GuiceBeansConfig.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/GuiceBeansConfig.java @@ -24,6 +24,7 @@ import org.apache.ambari.server.security.authentication.AmbariLocalAuthenticatio import org.apache.ambari.server.security.authentication.jwt.AmbariJwtAuthenticationProvider; import org.apache.ambari.server.security.authentication.jwt.JwtAuthenticationPropertiesProvider; import org.apache.ambari.server.security.authentication.pam.AmbariPamAuthenticationProvider; +import org.apache.ambari.server.security.authentication.tproxy.AmbariTProxyConfigurationProvider; import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider; import org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter; import org.apache.ambari.server.security.authorization.PermissionHelper; @@ -118,4 +119,9 @@ public class GuiceBeansConfig { return new AgentsRegistrationQueue(injector); } + @Bean + public AmbariTProxyConfigurationProvider ambariTProxyConfigurationProvider() { + return injector.getInstance(AmbariTProxyConfigurationProvider.class); + } + } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java index 40fe567..6f98744 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java @@ -1096,7 +1096,7 @@ public class AmbariServer { // Start and Initialize JPA GuiceJpaInitializer jpaInitializer = injector.getInstance(GuiceJpaInitializer.class); - jpaInitializer.setInitialized(); // This must be called to alert Ambari that JPA is initialized. + jpaInitializer.setInitialized(injector.getInstance(AmbariEventPublisher.class)); // This must be called to alert Ambari that JPA is initialized. DatabaseConsistencyCheckHelper.checkDBVersionCompatible(); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java index 0647138..163e7b5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java @@ -16,10 +16,10 @@ package org.apache.ambari.server.ldap.domain; import static java.lang.Boolean.parseBoolean; -import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.apache.ambari.server.configuration.AmbariServerConfiguration; import org.apache.ambari.server.configuration.AmbariServerConfigurationCategory; import org.apache.ambari.server.configuration.AmbariServerConfigurationKey; import org.apache.ambari.server.configuration.LdapUsernameCollisionHandlingBehavior; @@ -28,47 +28,33 @@ import org.apache.ambari.server.utils.PasswordUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * This class is an immutable representation of all the LDAP related - * configurationMap entries. + * This class is a representation of all the LDAP related configuration properties. * <p> * <strong>IMPORTANT: </strong>in case you declare any new LDAP related property * please do it in the Python class * <code>stacks.ambari_configuration.AmbariLDAPConfiguration</code> too. */ -public class AmbariLdapConfiguration { +public class AmbariLdapConfiguration extends AmbariServerConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapConfiguration.class); - - private final Map<String, String> configurationMap; - - private String configValue(AmbariServerConfigurationKey ambariServerConfigurationKey) { - final String value; - if (configurationMap.containsKey(ambariServerConfigurationKey.key())) { - value = configurationMap.get(ambariServerConfigurationKey.key()); - } else { - LOGGER.debug("Ldap configuration property [{}] hasn't been set; using default value", ambariServerConfigurationKey.key()); - value = ambariServerConfigurationKey.getDefaultValue(); - } - return value; - } + private final Map<String, String> configurationMap = new HashMap<>(); public void setValueFor(AmbariServerConfigurationKey ambariServerConfigurationKey, String value) { - if(ambariServerConfigurationKey.getConfigurationCategory() != AmbariServerConfigurationCategory.LDAP_CONFIGURATION) { + if (ambariServerConfigurationKey.getConfigurationCategory() != AmbariServerConfigurationCategory.LDAP_CONFIGURATION) { throw new IllegalArgumentException(ambariServerConfigurationKey.name() + " is not an LDAP configuration"); } configurationMap.put(ambariServerConfigurationKey.key(), value); } - + public AmbariLdapConfiguration() { - this(new HashMap<>()); + this(null); } - public AmbariLdapConfiguration(Map<String, String> configuration) { - this.configurationMap = configuration; + public AmbariLdapConfiguration(Map<String, String> configurationMap) { + if (configurationMap != null) { + this.configurationMap.putAll(configurationMap); + } } public boolean isAmbariManagesLdapConfiguration() { @@ -221,7 +207,7 @@ public class AmbariLdapConfiguration { } public Map<String, String> toMap() { - return (configurationMap == null) ? Collections.emptyMap() : new HashMap<>(configurationMap); + return new HashMap<>(configurationMap); } @Override @@ -311,4 +297,8 @@ public class AmbariLdapConfiguration { return LdapUsernameCollisionHandlingBehavior.CONVERT; } + private String configValue(AmbariServerConfigurationKey ambariManagesLdapConfiguration) { + return getValue(ambariManagesLdapConfiguration, configurationMap); + } + } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java index ead03dd..1a977e1 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java @@ -18,24 +18,16 @@ package org.apache.ambari.server.ldap.service; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.Collection; import org.apache.ambari.server.configuration.AmbariServerConfigurationCategory; -import org.apache.ambari.server.events.AmbariConfigurationChangedEvent; -import org.apache.ambari.server.events.JpaInitializedEvent; +import org.apache.ambari.server.configuration.AmbariServerConfigurationProvider; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration; -import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO; +import org.apache.ambari.server.orm.GuiceJpaInitializer; import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.google.common.eventbus.Subscribe; import com.google.inject.Inject; -import com.google.inject.Provider; import com.google.inject.Singleton; /** @@ -47,85 +39,19 @@ import com.google.inject.Singleton; * <p> * The provider receives notifications on CRUD operations related to the persisted resource and reloads the cached * configuration instance accordingly. + * + * @see AmbariServerConfigurationProvider */ @Singleton -public class AmbariLdapConfigurationProvider implements Provider<AmbariLdapConfiguration> { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmbariLdapConfigurationProvider.class); - private AmbariLdapConfiguration instance; - - @Inject - private AmbariEventPublisher publisher; - - @Inject - private Provider<AmbariConfigurationDAO> ambariConfigurationDAOProvider; +public class AmbariLdapConfigurationProvider extends AmbariServerConfigurationProvider<AmbariLdapConfiguration> { @Inject - public AmbariLdapConfigurationProvider() { - } - - private AtomicBoolean jpaInitialized = new AtomicBoolean(false); - - @Inject - void register() { - publisher.register(this); - LOGGER.info("Registered AmbariLdapConfigurationProvider in event publisher"); + public AmbariLdapConfigurationProvider(AmbariEventPublisher publisher, GuiceJpaInitializer guiceJpaInitializer) { + super(AmbariServerConfigurationCategory.LDAP_CONFIGURATION, publisher, guiceJpaInitializer); } @Override - public AmbariLdapConfiguration get() { - LOGGER.debug("Getting LDAP configuration..."); - if (instance == null || instance.toMap().isEmpty()) { - loadInstance(); - } - return instance; - } - - /** - * Loads the AmbariLdapConfiguration from the database. - */ - private void loadInstance() { - List<AmbariConfigurationEntity> configEntities = null; - - LOGGER.info("Loading LDAP configuration ..."); - if (jpaInitialized.get()) { - LOGGER.info("Actually loading LDAP configuration from DB ..."); - configEntities = ambariConfigurationDAOProvider.get().findByCategory(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName()); - } - - if (configEntities != null) { - Map<String, String> properties = toProperties(configEntities); - instance = new AmbariLdapConfiguration(properties); - }else { - instance = new AmbariLdapConfiguration(); - } - - LOGGER.info("Loaded LDAP configuration instance: [ {} ]", instance.toMap()); - } - - private Map<String, String> toProperties(List<AmbariConfigurationEntity> configEntities) { - Map<String, String> map = new HashMap<>(); - - for (AmbariConfigurationEntity entity : configEntities) { - map.put(entity.getPropertyName(), entity.getPropertyValue()); - } - - return map; - } - - // On changing the configuration, the provider gets updated with the fresh value - @Subscribe - public void ambariLdapConfigChanged(AmbariConfigurationChangedEvent event) { - LOGGER.info("LDAP config changed event received: {}", event); - loadInstance(); - LOGGER.info("Refreshed LDAP config instance."); - } - - @Subscribe - public void jpaInitialized(JpaInitializedEvent event) { - LOGGER.info("JPA initialized event received: {}", event); - jpaInitialized.getAndSet(true); - loadInstance(); - LOGGER.info("Refreshed LDAP config instance."); + protected AmbariLdapConfiguration loadInstance(Collection<AmbariConfigurationEntity> configurationEntities) { + return new AmbariLdapConfiguration(toProperties(configurationEntities)); } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java index c049c72..c0049e5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java @@ -18,6 +18,8 @@ package org.apache.ambari.server.orm; +import java.util.concurrent.atomic.AtomicBoolean; + import org.apache.ambari.server.events.JpaInitializedEvent; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; @@ -31,20 +33,16 @@ import com.google.inject.persist.PersistService; @Singleton public class GuiceJpaInitializer { - private final AmbariEventPublisher publisher; + private final AtomicBoolean jpaInitialized = new AtomicBoolean(false); /** * GuiceJpaInitializer constructor. - * <p> - * Starts the JPA service and holds on to an {@link AmbariEventPublisher} for future use. - * - * @param service the persist service - * @param publisher the Ambari event publisher */ @Inject - public GuiceJpaInitializer(PersistService service, AmbariEventPublisher publisher) { - this.publisher = publisher; - service.start(); + public GuiceJpaInitializer(PersistService persistService) { + if (persistService != null) { + persistService.start(); + } } /** @@ -53,11 +51,26 @@ public class GuiceJpaInitializer { * This means that the schema for the underlying database matches the JPA entity objects expectations * and the PersistService has been started. * <p> - * A {@link JpaInitializedEvent} is published so that subscribers can perform database-related tasks - * when the infrastructure is ready. + * If an {@link AmbariEventPublisher} is supplied, a {@link JpaInitializedEvent} is published so + * that subscribers can perform database-related tasks when the infrastructure is ready. + * + * @param publisher an {@link AmbariEventPublisher} to use for publishing the event, optional */ - public void setInitialized() { - publisher.publish(new JpaInitializedEvent()); + public void setInitialized(AmbariEventPublisher publisher) { + jpaInitialized.set(true); + + if (publisher != null) { + publisher.publish(new JpaInitializedEvent()); + } } + /** + * Returns whether JPA has been initialized or not + * + * @return <code>true</code> if JPA has been initialized; <code>false</code> if JPA has not been initialized + * @see #setInitialized(AmbariEventPublisher) + */ + public boolean isInitialized() { + return jpaInitialized.get(); + } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java index 0e3e6eb..67e060c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java @@ -127,7 +127,7 @@ public class AmbariJwtAuthenticationFilter implements AmbariAuthenticationFilter public boolean shouldApply(HttpServletRequest httpServletRequest) { boolean shouldApply = false; - JwtAuthenticationProperties jwtProperties = propertiesProvider.getProperties(); + JwtAuthenticationProperties jwtProperties = propertiesProvider.get(); if (jwtProperties != null && jwtProperties.isEnabledForAmbari()) { String serializedJWT = getJWTFromCookie(httpServletRequest); shouldApply = (serializedJWT != null && isAuthenticationRequired(serializedJWT)); @@ -160,7 +160,7 @@ public class AmbariJwtAuthenticationFilter implements AmbariAuthenticationFilter eventHandler.beforeAttemptAuthentication(this, servletRequest, servletResponse); - JwtAuthenticationProperties jwtProperties = propertiesProvider.getProperties(); + JwtAuthenticationProperties jwtProperties = propertiesProvider.get(); if (jwtProperties == null || !jwtProperties.isEnabledForAmbari()) { //disable filter if not configured chain.doFilter(servletRequest, servletResponse); @@ -254,7 +254,7 @@ public class AmbariJwtAuthenticationFilter implements AmbariAuthenticationFilter String serializedJWT = null; Cookie[] cookies = req.getCookies(); if (cookies != null) { - JwtAuthenticationProperties jwtProperties = propertiesProvider.getProperties(); + JwtAuthenticationProperties jwtProperties = propertiesProvider.get(); String jwtCookieName = (jwtProperties == null) ? null : jwtProperties.getCookieName(); if (StringUtils.isEmpty(jwtCookieName)) { jwtCookieName = AmbariServerConfigurationKey.SSO_JWT_COOKIE_NAME.getDefaultValue(); @@ -313,7 +313,7 @@ public class AmbariJwtAuthenticationFilter implements AmbariAuthenticationFilter if (jwtToken.getSignature() != null) { LOG.debug("JWT token signature is not null"); - JwtAuthenticationProperties jwtProperties = propertiesProvider.getProperties(); + JwtAuthenticationProperties jwtProperties = propertiesProvider.get(); RSAPublicKey publicKey = (jwtProperties == null) ? null : jwtProperties.getPublicKey(); if (publicKey == null) { LOG.warn("SSO server public key has not be set, validation of the JWT token cannot be performed."); @@ -347,7 +347,7 @@ public class AmbariJwtAuthenticationFilter implements AmbariAuthenticationFilter boolean valid = false; try { List<String> tokenAudienceList = jwtToken.getJWTClaimsSet().getAudience(); - JwtAuthenticationProperties jwtProperties = propertiesProvider.getProperties(); + JwtAuthenticationProperties jwtProperties = propertiesProvider.get(); List<String> audiences = (jwtProperties == null) ? null : jwtProperties.getAudiences(); // if there were no expected audiences configured then just diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationProperties.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationProperties.java index f1edb19..4431bfb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationProperties.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationProperties.java @@ -17,17 +17,36 @@ */ package org.apache.ambari.server.security.authentication.jwt; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_AUTHENTICATION_ENABLED; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_JWT_AUDIENCES; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_JWT_COOKIE_NAME; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_PROVIDER_CERTIFICATE; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_PROVIDER_ORIGINAL_URL_PARAM_NAME; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_PROVIDER_URL; + +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import org.apache.ambari.server.configuration.AmbariServerConfiguration; +import org.apache.ambari.server.security.encryption.CertificateUtils; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Class describes parameters of external JWT authentication provider */ -public class JwtAuthenticationProperties { +public class JwtAuthenticationProperties extends AmbariServerConfiguration { + private static final Logger LOG = LoggerFactory.getLogger(JwtAuthenticationPropertiesProvider.class); + + private static final String PEM_CERTIFICATE_HEADER = "-----BEGIN CERTIFICATE-----"; + private static final String PEM_CERTIFICATE_FOOTER = "-----END CERTIFICATE-----"; + private String authenticationProviderUrl = null; private RSAPublicKey publicKey = null; private List<String> audiences = null; @@ -35,6 +54,15 @@ public class JwtAuthenticationProperties { private String originalUrlQueryParam = null; private boolean enabledForAmbari; + JwtAuthenticationProperties(Map<String, String> configurationMap) { + setEnabledForAmbari(Boolean.valueOf(getValue(SSO_AUTHENTICATION_ENABLED, configurationMap))); + setAudiencesString(getValue(SSO_JWT_AUDIENCES, configurationMap)); + setAuthenticationProviderUrl(getValue(SSO_PROVIDER_URL, configurationMap)); + setCookieName(getValue(SSO_JWT_COOKIE_NAME, configurationMap)); + setOriginalUrlQueryParam(getValue(SSO_PROVIDER_ORIGINAL_URL_PARAM_NAME, configurationMap)); + setPublicKey(getValue(SSO_PROVIDER_CERTIFICATE, configurationMap)); + } + public String getAuthenticationProviderUrl() { return authenticationProviderUrl; } @@ -47,6 +75,10 @@ public class JwtAuthenticationProperties { return publicKey; } + public void setPublicKey(String publicKey) { + setPublicKey(createPublicKey(publicKey)); + } + public void setPublicKey(RSAPublicKey publicKey) { this.publicKey = publicKey; } @@ -93,4 +125,38 @@ public class JwtAuthenticationProperties { public void setEnabledForAmbari(boolean enabledForAmbari) { this.enabledForAmbari = enabledForAmbari; } + + /** + * Given a String containing PEM-encode x509 certificate, an {@link RSAPublicKey} is created and + * returned. + * <p> + * If the certificate data is does not contain the proper PEM-encoded x509 digital certificate + * header and footer, they will be added. + * + * @param certificate a PEM-encode x509 certificate + * @return an {@link RSAPublicKey} + */ + private RSAPublicKey createPublicKey(String certificate) { + RSAPublicKey publicKey = null; + if (certificate != null) { + certificate = certificate.trim(); + } + if (!StringUtils.isEmpty(certificate)) { + // Ensure the PEM data is properly formatted + if (!certificate.startsWith(PEM_CERTIFICATE_HEADER)) { + certificate = PEM_CERTIFICATE_HEADER + "/n" + certificate; + } + if (!certificate.endsWith(PEM_CERTIFICATE_FOOTER)) { + certificate = certificate + "/n" + PEM_CERTIFICATE_FOOTER; + } + + try { + publicKey = CertificateUtils.getPublicKeyFromString(certificate); + } catch (CertificateException | UnsupportedEncodingException e) { + LOG.error("Unable to parse public certificate file. JTW authentication will fail.", e); + } + } + + return publicKey; + } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesProvider.java index 494dfcb..e357379 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesProvider.java @@ -19,30 +19,16 @@ package org.apache.ambari.server.security.authentication.jwt; import static org.apache.ambari.server.configuration.AmbariServerConfigurationCategory.SSO_CONFIGURATION; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_AUTHENTICATION_ENABLED; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_JWT_AUDIENCES; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_JWT_COOKIE_NAME; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_PROVIDER_CERTIFICATE; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_PROVIDER_ORIGINAL_URL_PARAM_NAME; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_PROVIDER_URL; -import java.io.UnsupportedEncodingException; -import java.security.cert.CertificateException; -import java.security.interfaces.RSAPublicKey; -import java.util.Map; +import java.util.Collection; -import org.apache.ambari.server.EagerSingleton; -import org.apache.ambari.server.configuration.AmbariServerConfigurationKey; -import org.apache.ambari.server.controller.internal.AmbariServerConfigurationHandler; -import org.apache.ambari.server.events.AmbariConfigurationChangedEvent; +import org.apache.ambari.server.configuration.AmbariServerConfigurationProvider; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; -import org.apache.ambari.server.security.encryption.CertificateUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.ambari.server.orm.GuiceJpaInitializer; +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; -import com.google.common.eventbus.Subscribe; import com.google.inject.Inject; +import com.google.inject.Singleton; /** * JwtAuthenticationPropertiesProvider manages a {@link JwtAuthenticationProperties} instance by @@ -51,129 +37,22 @@ import com.google.inject.Inject; * <p> * The {@link JwtAuthenticationProperties} are updated upon events received from the {@link AmbariEventPublisher}. */ -@EagerSingleton -public class JwtAuthenticationPropertiesProvider { - private static final Logger LOG = LoggerFactory.getLogger(JwtAuthenticationPropertiesProvider.class); - - private static final String PEM_CERTIFICATE_HEADER = "-----BEGIN CERTIFICATE-----"; - private static final String PEM_CERTIFICATE_FOOTER = "-----END CERTIFICATE-----"; - - private final AmbariServerConfigurationHandler configurationHandler; - - private JwtAuthenticationProperties properties = null; +@Singleton +public class JwtAuthenticationPropertiesProvider extends AmbariServerConfigurationProvider<JwtAuthenticationProperties> { @Inject - public JwtAuthenticationPropertiesProvider(AmbariServerConfigurationHandler configurationHandler, AmbariEventPublisher eventPublisher) { - this.configurationHandler = configurationHandler; - - eventPublisher.register(this); - } - - /** - * Retrieves the {@link JwtAuthenticationProperties} data. - * <p> - * This value is expected to contain the latest data from the Ambari configuration store in the - * Ambari DB. - * <p> - * If the stored reference is <code>null</code>, the properites will be loaded. - * - * @return a JwtAuthenticationProperties - */ - public JwtAuthenticationProperties getProperties() { - if (properties == null) { - loadProperties(false); - } - - return properties; - } - - /** - * (Reloads the {@link JwtAuthenticationProperties} when the sso-configuration data is updated - * and an {@link AmbariConfigurationChangedEvent} is triggered in the {@link AmbariEventPublisher}. - * - * @param event an {@link AmbariConfigurationChangedEvent} - */ - @Subscribe - public synchronized void reloadProperties(AmbariConfigurationChangedEvent event) { - if (SSO_CONFIGURATION.getCategoryName().equalsIgnoreCase(event.getCategoryName())) { - loadProperties(true); - } - } - - /** - * If the {@link JwtAuthenticationProperties} reference is <code>null</code> or the caller requests - * a force reload (forceReload == <code>true</code>), a new {@link JwtAuthenticationProperties} - * is created and this members are set to data retrieved from the Ambari databases. - * <p> - * This method is synchronzed so that multiple threads cannot step on each other when requesting - * the properties to be reloaded. - * - * @param forceReload <code>true</code> to force the properties to be reloaded; <code>false</code> - * to only reload the data if the {@link JwtAuthenticationProperties} reference - * is <code>null</code> - */ - private synchronized void loadProperties(boolean forceReload) { - if (forceReload || (properties == null)) { - Map<String, String> ssoProperties = configurationHandler.getConfigurationProperties(SSO_CONFIGURATION.getCategoryName()); - JwtAuthenticationProperties properties = new JwtAuthenticationProperties(); - properties.setEnabledForAmbari("true".equalsIgnoreCase(getValue(SSO_AUTHENTICATION_ENABLED, ssoProperties))); - properties.setAudiencesString(getValue(SSO_JWT_AUDIENCES, ssoProperties)); - properties.setAuthenticationProviderUrl(getValue(SSO_PROVIDER_URL, ssoProperties)); - properties.setCookieName(getValue(SSO_JWT_COOKIE_NAME, ssoProperties)); - properties.setOriginalUrlQueryParam(getValue(SSO_PROVIDER_ORIGINAL_URL_PARAM_NAME, ssoProperties)); - properties.setPublicKey(createPublicKey(getValue(SSO_PROVIDER_CERTIFICATE, ssoProperties))); - - this.properties = properties; - } - } - - /** - * Given a String containing PEM-encode x509 certificate, an {@link RSAPublicKey} is created and - * returned. - * <p> - * If the certificate data is does not contain the proper PEM-encoded x509 digital certificate - * header and footer, they will be added. - * - * @param certificate a PEM-encode x509 certificate - * @return an {@link RSAPublicKey} - */ - private RSAPublicKey createPublicKey(String certificate) { - RSAPublicKey publicKey = null; - if (certificate != null) { - certificate = certificate.trim(); - } - if (!StringUtils.isEmpty(certificate)) { - // Ensure the PEM data is properly formatted - if (!certificate.startsWith(PEM_CERTIFICATE_HEADER)) { - certificate = PEM_CERTIFICATE_HEADER + "/n" + certificate; - } - if (!certificate.endsWith(PEM_CERTIFICATE_FOOTER)) { - certificate = certificate + "/n" + PEM_CERTIFICATE_FOOTER; - } - - try { - publicKey = CertificateUtils.getPublicKeyFromString(certificate); - } catch (CertificateException | UnsupportedEncodingException e) { - LOG.error("Unable to parse public certificate file. JTW authentication will fai", e); - } - } - - return publicKey; + public JwtAuthenticationPropertiesProvider(AmbariEventPublisher ambariEventPublisher, GuiceJpaInitializer guiceJpaInitializer) { + super(SSO_CONFIGURATION, ambariEventPublisher, guiceJpaInitializer); } /** - * A helper method to retrieve the stored value or the default value for a given SSO confogiguration - * value. + * Creates a JwtAuthenticationProperties from a list of {@link AmbariConfigurationEntity}s. * - * @param key the {@link AmbariServerConfigurationKey} to retrieve the data for - * @param properties the map of properties to search - * @return the value + * @param configurationEntities a list of {@link AmbariConfigurationEntity}s + * @return a filled in {@link JwtAuthenticationProperties} */ - private String getValue(AmbariServerConfigurationKey key, Map<String, String> properties) { - if ((properties != null) && properties.containsKey(key.key())) { - return properties.get(key.key()); - } else { - return key.getDefaultValue(); - } + @Override + protected JwtAuthenticationProperties loadInstance(Collection<AmbariConfigurationEntity> configurationEntities) { + return new JwtAuthenticationProperties(toProperties(configurationEntities)); } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfiguration.java new file mode 100644 index 0000000..daf3788 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfiguration.java @@ -0,0 +1,117 @@ +/* + * 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.authentication.tproxy; + +import java.util.Map; + +import org.apache.ambari.server.configuration.AmbariServerConfiguration; +import org.apache.ambari.server.configuration.AmbariServerConfigurationKey; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import com.google.common.collect.ImmutableMap; + +/** + * AmbariTProxyConfiguration is a {@link AmbariServerConfiguration} implementation that contains + * configuration data for the Ambari server tproxy-configuration configuration properties. + */ +public class AmbariTProxyConfiguration extends AmbariServerConfiguration { + + private static final String TEMPLATE_PROXY_USER_ALLOWED_HOSTS = "ambari.tproxy.proxyuser.%s.hosts"; + private static final String TEMPLATE_PROXY_USER_ALLOWED_USERS = "ambari.tproxy.proxyuser.%s.users"; + private static final String TEMPLATE_PROXY_USER_ALLOWED_GROUPS = "ambari.tproxy.proxyuser.%s.groups"; + + private final ImmutableMap<String, String> configurationMap; + + /** + * Constructor + * <p> + * Copies the given configuration propery map into an {@link ImmutableMap} and pulls out propery + * values upon request. + * + * @param configurationMap a map of property names to values + */ + AmbariTProxyConfiguration(Map<String, String> configurationMap) { + ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + + if (configurationMap != null) { + builder.putAll(configurationMap); + } + + this.configurationMap = builder.build(); + } + + /** + * Returns an immutable map of the contained properties + * + * @return an immutable map property names to values + */ + public Map<String, String> toMap() { + return configurationMap; + } + + /** + * Determines of tristed proxy support is enabled based on the configuration data. + * + * @return <code>true</code> if trusted proxy support is enabed; <code>false</code> otherwise + * @see AmbariServerConfigurationKey#TPROXY_AUTHENTICATION_ENABLED + */ + boolean isEnabled() { + return Boolean.valueOf(getValue(AmbariServerConfigurationKey.TPROXY_AUTHENTICATION_ENABLED, configurationMap)); + } + + public String getAllowedHosts(String proxyUser) { + return getValue(String.format(TEMPLATE_PROXY_USER_ALLOWED_HOSTS, proxyUser), + configurationMap, + AmbariServerConfigurationKey.TPROXY_ALLOWED_HOSTS.getDefaultValue()); + } + + public String getAllowedUsers(String proxyUser) { + return getValue(String.format(TEMPLATE_PROXY_USER_ALLOWED_USERS, proxyUser), + configurationMap, + AmbariServerConfigurationKey.TPROXY_ALLOWED_USERS.getDefaultValue()); + } + + public String getAllowedGroups(String proxyUser) { + return getValue(String.format(TEMPLATE_PROXY_USER_ALLOWED_GROUPS, proxyUser), + configurationMap, + AmbariServerConfigurationKey.TPROXY_ALLOWED_GROUPS.getDefaultValue()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + return new EqualsBuilder() + .append(configurationMap, ((AmbariTProxyConfiguration) o).configurationMap) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(configurationMap) + .toHashCode(); + } +} \ No newline at end of file diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationProvider.java new file mode 100644 index 0000000..0bc413a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationProvider.java @@ -0,0 +1,62 @@ +/* + * 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.authentication.tproxy; + +import java.util.Collection; + +import org.apache.ambari.server.configuration.AmbariServerConfigurationCategory; +import org.apache.ambari.server.configuration.AmbariServerConfigurationProvider; +import org.apache.ambari.server.events.publishers.AmbariEventPublisher; +import org.apache.ambari.server.orm.GuiceJpaInitializer; +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * Provider implementation for {@link AmbariTProxyConfiguration} objects. + * Returned {@link AmbariTProxyConfiguration} instances are expected to contain the current values + * for the tproxy-configuration category of the Ambari Server Configuration data. + * <p> + * It needs to be registered in the related GUICE module as a provider. + * <p> + * The provider receives notifications on CRUD operations related to the persisted resource and reloads the cached + * configuration instance accordingly. + * + * @see AmbariServerConfigurationProvider + */ +@Singleton +public class AmbariTProxyConfigurationProvider extends AmbariServerConfigurationProvider<AmbariTProxyConfiguration> { + + @Inject + public AmbariTProxyConfigurationProvider(AmbariEventPublisher ambariEventPublisher, GuiceJpaInitializer guiceJpaInitializer) { + super(AmbariServerConfigurationCategory.TPROXY_CONFIGURATION, ambariEventPublisher, guiceJpaInitializer); + } + + /** + * Creates a AmbariTProxyConfiguration from a list of {@link AmbariConfigurationEntity}s. + * + * @param configurationEntities a list of {@link AmbariConfigurationEntity}s + * @return a filled in {@link AmbariTProxyConfiguration} + */ + @Override + protected AmbariTProxyConfiguration loadInstance(Collection<AmbariConfigurationEntity> configurationEntities) { + return new AmbariTProxyConfiguration(toProperties(configurationEntities)); + } +} diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java index 7563975..1aa0ff7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java @@ -36,6 +36,7 @@ import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.audit.AuditLoggerModule; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.ControllerModule; +import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.ldap.LdapModule; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.GuiceJpaInitializer; @@ -452,7 +453,7 @@ public class SchemaUpgradeHelper { // The DDL is expected to be updated, now send the JPA initialized event so Entity // implementations can be created. - jpaInitializer.setInitialized(); + jpaInitializer.setInitialized(injector.getInstance(AmbariEventPublisher.class)); schemaUpgradeHelper.executePreDMLUpdates(upgradeCatalogs); 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 142c62d..cb31375 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 @@ -50,6 +50,7 @@ import org.apache.ambari.server.hooks.HookService; import org.apache.ambari.server.hooks.users.PostUserCreationHookContext; import org.apache.ambari.server.hooks.users.UserCreatedEvent; import org.apache.ambari.server.hooks.users.UserHookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.ldap.service.LdapFacade; import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; @@ -362,6 +363,7 @@ public class AgentResourceTest extends RandomPortJerseyTest { bind(new TypeLiteral<Encryptor<AgentConfigsUpdateEvent>>() {}).annotatedWith(Names.named("AgentConfigEncryptor")).toInstance(Encryptor.NONE); bind(new TypeLiteral<Encryptor<Config>>() {}).annotatedWith(Names.named("ConfigPropertiesEncryptor")).toInstance(Encryptor.NONE); bind(LdapFacade.class).toInstance(createNiceMock(LdapFacade.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createNiceMock(AmbariLdapConfigurationProvider.class)); } private void installDependencies() { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java index f16aae1..827d0d9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java @@ -58,7 +58,7 @@ public class AmbariErrorHandlerTest extends EasyMockSupport { public void testErrorWithJetty() throws Exception { Server server = new Server(0); JwtAuthenticationPropertiesProvider propertiesProvider = createNiceMock(JwtAuthenticationPropertiesProvider.class); - expect(propertiesProvider.getProperties()).andReturn(null).anyTimes(); + expect(propertiesProvider.get()).andReturn(null).anyTimes(); replayAll(); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/configuration/AmbariServerConfigurationProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/configuration/AmbariServerConfigurationProviderTest.java new file mode 100644 index 0000000..af5a67c --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/configuration/AmbariServerConfigurationProviderTest.java @@ -0,0 +1,166 @@ +/* + * 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.configuration; + +import static org.apache.ambari.server.configuration.AmbariServerConfigurationCategory.TPROXY_CONFIGURATION; +import static org.easymock.EasyMock.expect; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityManager; + +import org.apache.ambari.server.events.AmbariConfigurationChangedEvent; +import org.apache.ambari.server.events.JpaInitializedEvent; +import org.apache.ambari.server.events.publishers.AmbariEventPublisher; +import org.apache.ambari.server.orm.GuiceJpaInitializer; +import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO; +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; +import org.apache.ambari.server.state.stack.OsFamily; +import org.easymock.EasyMockSupport; +import org.junit.Assert; +import org.junit.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class AmbariServerConfigurationProviderTest extends EasyMockSupport { + + private static final AmbariServerConfigurationCategory TEST_CONFIGURATION = TPROXY_CONFIGURATION; + + @Test + public void testGetAndLoadDataForVariousEvents() { + Injector injector = getInjector(); + + AmbariServerConfiguration emptyTestConfiguration = createMock(AmbariServerConfiguration.class); + + AmbariServerConfiguration filledTestConfiguration1 = createMock(AmbariServerConfiguration.class); + + AmbariServerConfiguration filledTestConfiguration2 = createMock(AmbariServerConfiguration.class); + + AmbariEventPublisher publisher = injector.getInstance(AmbariEventPublisher.class); + GuiceJpaInitializer jpaInitializer = injector.getInstance(GuiceJpaInitializer.class); + + AmbariServerConfigurationProvider provider = createMockBuilder(AmbariServerConfigurationProvider.class) + .addMockedMethod("loadInstance", Collection.class) + .withConstructor(TEST_CONFIGURATION, publisher, jpaInitializer) + .createMock(); + + expect(provider.loadInstance(Collections.emptyList())).andReturn(emptyTestConfiguration).once(); + expect(provider.loadInstance(null)).andReturn(filledTestConfiguration1).once(); + expect(provider.loadInstance(null)).andReturn(filledTestConfiguration2).once(); + + replayAll(); + + injector.injectMembers(provider); + + AmbariServerConfiguration configuration = provider.get(); + Assert.assertSame(emptyTestConfiguration, configuration); + + // Push a configuration change event... + provider.ambariConfigurationChanged(new AmbariConfigurationChangedEvent(TEST_CONFIGURATION.getCategoryName())); + + AmbariServerConfiguration configuration2 = provider.get(); + // This should return the same instance as before since loadInstance should not have done anything + Assert.assertSame(configuration, configuration2); + + // Push an initializing JPA event... + provider.jpaInitialized(new JpaInitializedEvent()); + + AmbariServerConfiguration configuration3 = provider.get(); + Assert.assertSame(filledTestConfiguration1, configuration3); + + // Push a configuration change event... + provider.ambariConfigurationChanged(new AmbariConfigurationChangedEvent(TEST_CONFIGURATION.getCategoryName())); + + AmbariServerConfiguration configuration4 = provider.get(); + // This should return a different instance since loadInstance should have done some work + Assert.assertNotSame(configuration3, configuration4); + + verifyAll(); + } + + @Test + public void testToProperties() { + Injector injector = getInjector(); + + AmbariEventPublisher publisher = injector.getInstance(AmbariEventPublisher.class); + GuiceJpaInitializer jpaInitializer = injector.getInstance(GuiceJpaInitializer.class); + + AmbariServerConfigurationProvider provider = createMockBuilder(AmbariServerConfigurationProvider.class) + .withConstructor(TEST_CONFIGURATION, publisher, jpaInitializer) + .createMock(); + + replayAll(); + + Map actualProperties; + + actualProperties = provider.toProperties(null); + Assert.assertNotNull(actualProperties); + Assert.assertEquals(Collections.emptyMap(), actualProperties); + + actualProperties = provider.toProperties(Collections.emptyList()); + Assert.assertNotNull(actualProperties); + Assert.assertEquals(Collections.emptyMap(), actualProperties); + + Map<String, String> expectedProperties = new HashMap<>(); + expectedProperties.put("one", "1"); + expectedProperties.put("two", "2"); + expectedProperties.put("three", "3"); + + actualProperties = provider.toProperties(createAmbariConfigurationEntities(expectedProperties)); + Assert.assertNotNull(actualProperties); + Assert.assertNotSame(expectedProperties, actualProperties); + Assert.assertEquals(expectedProperties, actualProperties); + + verifyAll(); + } + + private Collection<AmbariConfigurationEntity> createAmbariConfigurationEntities(Map<String, String> properties) { + List<AmbariConfigurationEntity> entities = new ArrayList<>(); + + for (Map.Entry<String, String> entry : properties.entrySet()) { + AmbariConfigurationEntity entity = new AmbariConfigurationEntity(); + entity.setCategoryName("some-category"); + entity.setPropertyName(entry.getKey()); + entity.setPropertyValue(entry.getValue()); + entities.add(entity); + } + + return entities; + } + + private Injector getInjector() { + return Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class)); + bind(GuiceJpaInitializer.class).toInstance(new GuiceJpaInitializer(null)); + bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class)); + bind(AmbariConfigurationDAO.class).toInstance(createNiceMock(AmbariConfigurationDAO.class)); + } + }); + } +} \ No newline at end of file diff --git a/ambari-server/src/test/java/org/apache/ambari/server/configuration/AmbariServerConfigurationTest.java b/ambari-server/src/test/java/org/apache/ambari/server/configuration/AmbariServerConfigurationTest.java new file mode 100644 index 0000000..e6c69c4 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/configuration/AmbariServerConfigurationTest.java @@ -0,0 +1,52 @@ +/* + * 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.configuration; + +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.LDAP_ENABLED; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.TPROXY_AUTHENTICATION_ENABLED; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +public class AmbariServerConfigurationTest { + + @Test + public void testGetValue() { + AmbariServerConfiguration ambariServerConfiguration = new AmbariServerConfiguration() { + + }; + + Map<String, String> configurationMap = Collections.singletonMap(TPROXY_AUTHENTICATION_ENABLED.key(), "true"); + + // Get the value specified in the configuration map + Assert.assertEquals("true", ambariServerConfiguration.getValue(TPROXY_AUTHENTICATION_ENABLED, configurationMap)); + + // Get the default value + Assert.assertEquals("false", LDAP_ENABLED.getDefaultValue()); + Assert.assertEquals(LDAP_ENABLED.getDefaultValue(), ambariServerConfiguration.getValue(LDAP_ENABLED, configurationMap)); + + // Handle a nulls + Assert.assertEquals("defaultValue", ambariServerConfiguration.getValue(null, configurationMap, "defaultValue")); + Assert.assertEquals("defaultValue", ambariServerConfiguration.getValue("property.name", null, "defaultValue")); + Assert.assertNull(ambariServerConfiguration.getValue("property.name", Collections.emptyMap(), null)); + } +} \ No newline at end of file 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 2366bb4..25c7b9e 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 @@ -158,6 +158,7 @@ import org.springframework.security.crypto.password.StandardPasswordEncoder; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.persist.PersistService; @SuppressWarnings("unchecked") @@ -242,6 +243,7 @@ public class KerberosHelperTest extends EasyMockSupport { PartialNiceMockBinder.newBuilder().addActionDBAccessorConfigsBindings().addFactoriesInstallBinding() .addPasswordEncryptorBindings().build().configure(binder()); + bind(PersistService.class).toInstance(createNiceMock(PersistService.class)); bind(ActionDBAccessor.class).to(ActionDBAccessorImpl.class); bind(ExecutionScheduler.class).to(ExecutionSchedulerImpl.class); bind(AbstractRootServiceResponseFactory.class).to(RootServiceResponseFactory.class); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java index a7c3a60..7c70d9a 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java @@ -38,6 +38,7 @@ import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.ClusterDAO; import org.apache.ambari.server.orm.dao.GroupDAO; @@ -349,6 +350,7 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport{ bind(PasswordEncoder.class).toInstance(createNiceMock(PasswordEncoder.class)); bind(HookService.class).toInstance(createMock(HookService.class)); bind(HookContextFactory.class).toInstance(createMock(HookContextFactory.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); bind(GroupDAO.class).toInstance(groupDAO); bind(ClusterDAO.class).toInstance(clusterDAO); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java index 417f17d..feff55a 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java @@ -56,6 +56,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.events.AgentConfigsUpdateEvent; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; import org.apache.ambari.server.mpack.MpackManagerFactory; import org.apache.ambari.server.orm.dao.AlertDefinitionDAO; @@ -334,6 +335,7 @@ public class PreUpgradeCheckResourceProviderTest extends EasyMockSupport { Provider<EntityManager> entityManagerProvider = createNiceMock(Provider.class); bind(EntityManager.class).toProvider(entityManagerProvider); bind(new TypeLiteral<Encryptor<AgentConfigsUpdateEvent>>() {}).annotatedWith(Names.named("AgentConfigEncryptor")).toInstance(Encryptor.NONE); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); requestStaticInjection(PreUpgradeCheckResourceProvider.class); } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java index 2e086d4..28ef5b7 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java @@ -48,6 +48,7 @@ import org.apache.ambari.server.controller.KerberosHelper; import org.apache.ambari.server.controller.spi.ClusterController; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; import org.apache.ambari.server.mpack.MpackManagerFactory; @@ -487,7 +488,7 @@ public class StackUpgradeConfigurationMergeTest extends EasyMockSupport { binder.bind(MetadataHolder.class).toInstance(createNiceMock(MetadataHolder.class)); binder.bind(AgentConfigsHolder.class).toInstance(createNiceMock(AgentConfigsHolder.class)); binder.bind(MpackManagerFactory.class).toInstance(createNiceMock(MpackManagerFactory.class)); - + binder.bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); binder.requestStaticInjection(UpgradeResourceProvider.class); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthorizationResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthorizationResourceProviderTest.java index f9f92d4..408ea78 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthorizationResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthorizationResourceProviderTest.java @@ -51,6 +51,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.events.AgentConfigsUpdateEvent; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; import org.apache.ambari.server.mpack.MpackManagerFactory; @@ -434,6 +435,8 @@ public class UserAuthorizationResourceProviderTest extends EasyMockSupport { bind(HostRoleCommandFactory.class).to(HostRoleCommandFactoryImpl.class); bind(PersistedState.class).to(PersistedStateImpl.class); bind(MpackManagerFactory.class).toInstance(createNiceMock(MpackManagerFactory.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); + bind(new TypeLiteral<Encryptor<AgentConfigsUpdateEvent>>() {}).annotatedWith(Names.named("AgentConfigEncryptor")).toInstance(Encryptor.NONE); } }); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java index 24e6e0a..d91d260 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java @@ -39,6 +39,7 @@ import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.ClusterDAO; import org.apache.ambari.server.orm.dao.GroupDAO; @@ -548,6 +549,7 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport { bind(ViewInstanceDAO.class).toInstance(createNiceMock(ViewInstanceDAO.class)); bind(PrivilegeDAO.class).toInstance(createMock(PrivilegeDAO.class)); bind(MemberDAO.class).toInstance(createMock(MemberDAO.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); } }); } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java index 1fa27cf..84cb5b3 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java @@ -63,6 +63,7 @@ import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.hooks.HookContext; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; import org.apache.ambari.server.mpack.MpackManagerFactory; @@ -436,6 +437,8 @@ public class UserResourceProviderTest extends EasyMockSupport { bind(ResourceDAO.class).toInstance(createMock(ResourceDAO.class)); bind(PrincipalTypeDAO.class).toInstance(createMock(PrincipalTypeDAO.class)); bind(MpackManagerFactory.class).toInstance(createNiceMock(MpackManagerFactory.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); + bind(new TypeLiteral<Encryptor<AgentConfigsUpdateEvent>>() {}).annotatedWith(Names.named("AgentConfigEncryptor")).toInstance(Encryptor.NONE); } }); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/InMemoryDefaultTestModule.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/InMemoryDefaultTestModule.java index caf013b..c13edf3 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/orm/InMemoryDefaultTestModule.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/InMemoryDefaultTestModule.java @@ -28,6 +28,7 @@ import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.ControllerModule; import org.apache.ambari.server.events.AgentConfigsUpdateEvent; import org.apache.ambari.server.ldap.LdapModule; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.mpack.MpackManager; import org.apache.ambari.server.mpack.MpackManagerFactory; import org.apache.ambari.server.mpack.MpackManagerMock; @@ -136,6 +137,8 @@ public class InMemoryDefaultTestModule extends AbstractModule { AuditLogger al = EasyMock.createNiceMock(AuditLogger.class); EasyMock.expect(al.isEnabled()).andReturn(false).anyTimes(); bind(AuditLogger.class).toInstance(al); + bind(AmbariLdapConfigurationProvider.class).toInstance(EasyMock.createMock(AmbariLdapConfigurationProvider.class)); + bind(new TypeLiteral<Encryptor<AgentConfigsUpdateEvent>>() {}).annotatedWith(Names.named("AgentConfigEncryptor")).toInstance(Encryptor.NONE); } catch (Exception e) { throw new RuntimeException(e); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java index ca47faa..d623a81 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java @@ -29,6 +29,7 @@ import javax.persistence.EntityManager; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.entities.UserEntity; import org.apache.ambari.server.security.authorization.Users; @@ -196,6 +197,7 @@ public abstract class AbstractAuthenticationProviderTest extends EasyMockSupport bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class)); bind(HookService.class).toInstance(createMock(HookService.class)); bind(HookContextFactory.class).toInstance(createMock(HookContextFactory.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); bind(Users.class).toInstance(users); bind(Configuration.class).toInstance(configuration); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java index 5668e49..2dac365 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java @@ -100,7 +100,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { } private JwtAuthenticationProperties createTestProperties(List<String> audiences) { - JwtAuthenticationProperties properties = new JwtAuthenticationProperties(); + JwtAuthenticationProperties properties = new JwtAuthenticationProperties(Collections.emptyMap()); properties.setCookieName("non-default"); properties.setPublicKey(publicKey); properties.setAudiences(audiences); @@ -175,7 +175,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { expect(request.getCookies()).andReturn(new Cookie[]{cookie}); JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -192,7 +192,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testValidateSignature() throws Exception { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -208,7 +208,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testValidateAudiences() throws Exception { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -225,7 +225,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testValidateNullAudiences() throws Exception { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties(null)).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties(null)).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -241,7 +241,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testValidateTokenWithoutAudiences() throws Exception { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -256,7 +256,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testValidateExpiration() throws Exception { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -272,7 +272,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testValidateNoExpiration() throws Exception { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); AmbariAuthenticationEventHandler eventHandler = createNiceMock(AmbariAuthenticationEventHandler.class); @@ -289,7 +289,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testShouldApplyTrue() throws JOSEException { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); SignedJWT token = getInvalidToken(); @@ -313,7 +313,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testShouldApplyTrueBadToken() throws JOSEException { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); Cookie cookie = createMock(Cookie.class); expect(cookie.getName()).andReturn("non-default").atLeastOnce(); @@ -335,7 +335,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testShouldApplyFalseMissingCookie() throws JOSEException { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); Cookie cookie = createMock(Cookie.class); expect(cookie.getName()).andReturn("some-other-cookie").atLeastOnce(); @@ -356,7 +356,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { @Test public void testShouldApplyFalseNotEnabled() throws JOSEException { JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(null).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(null).anyTimes(); HttpServletRequest request = createMock(HttpServletRequest.class); @@ -382,7 +382,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { SignedJWT token = getSignedToken(); JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); Configuration configuration = createNiceMock(Configuration.class); expect(configuration.getMaxAuthenticationFailures()).andReturn(10).anyTimes(); @@ -448,7 +448,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { Configuration configuration = createMock(Configuration.class); JwtAuthenticationPropertiesProvider jwtAuthenticationPropertiesProvider = createMock(JwtAuthenticationPropertiesProvider.class); - expect(jwtAuthenticationPropertiesProvider.getProperties()).andReturn(createTestProperties()).anyTimes(); + expect(jwtAuthenticationPropertiesProvider.get()).andReturn(createTestProperties()).anyTimes(); HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesTest.java index 9b7e482..3e46dc6 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/JwtAuthenticationPropertiesTest.java @@ -22,20 +22,22 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import java.util.Collections; + import org.junit.Test; public class JwtAuthenticationPropertiesTest { @Test public void testSetNullAudiences() { - JwtAuthenticationProperties jwtAuthenticationProperties = new JwtAuthenticationProperties(); + JwtAuthenticationProperties jwtAuthenticationProperties = new JwtAuthenticationProperties(Collections.emptyMap()); jwtAuthenticationProperties.setAudiencesString(null); assertNull(jwtAuthenticationProperties.getAudiences()); } @Test public void testSetEmptyAudiences() { - JwtAuthenticationProperties jwtAuthenticationProperties = new JwtAuthenticationProperties(); + JwtAuthenticationProperties jwtAuthenticationProperties = new JwtAuthenticationProperties(Collections.emptyMap()); jwtAuthenticationProperties.setAudiencesString(""); assertNull(jwtAuthenticationProperties.getAudiences()); } @@ -43,7 +45,7 @@ public class JwtAuthenticationPropertiesTest { @Test public void testSetValidAudiences() { String[] expectedAudiences = {"first", "second", "third"}; - JwtAuthenticationProperties jwtAuthenticationProperties = new JwtAuthenticationProperties(); + JwtAuthenticationProperties jwtAuthenticationProperties = new JwtAuthenticationProperties(Collections.emptyMap()); jwtAuthenticationProperties.setAudiencesString("first,second,third"); assertNotNull(jwtAuthenticationProperties.getAudiences()); assertArrayEquals(expectedAudiences, jwtAuthenticationProperties.getAudiences().toArray(new String[]{})); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java index 6a90ef7..11298a1 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java @@ -29,6 +29,7 @@ import javax.persistence.EntityManager; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.entities.PrincipalEntity; import org.apache.ambari.server.orm.entities.UserAuthenticationEntity; @@ -99,6 +100,7 @@ public class AmbariPamAuthenticationProviderTest extends EasyMockSupport { bind(PasswordEncoder.class).toInstance(new StandardPasswordEncoder()); bind(Users.class).toInstance(users); bind(Configuration.class).toInstance(configuration); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); } }); } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationProviderTest.java new file mode 100644 index 0000000..47a3011 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationProviderTest.java @@ -0,0 +1,71 @@ +/* + * 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.authentication.tproxy; + +import static org.apache.ambari.server.configuration.AmbariServerConfigurationCategory.TPROXY_CONFIGURATION; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.TPROXY_AUTHENTICATION_ENABLED; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; +import org.junit.Assert; +import org.junit.Test; + +public class AmbariTProxyConfigurationProviderTest { + + @Test + public void testLoadInstance() { + AmbariTProxyConfigurationProvider provider = new AmbariTProxyConfigurationProvider(null, null); + + Map<String, String> expectedProperties = new HashMap<>(); + expectedProperties.put(TPROXY_AUTHENTICATION_ENABLED.key(), "true"); + expectedProperties.put("ambari.tproxy.proxyuser.knox.hosts", "c7401.ambari.apache.org"); + expectedProperties.put("ambari.tproxy.proxyuser.knox.users", "*"); + expectedProperties.put("ambari.tproxy.proxyuser.knox.groups", "users"); + + AmbariTProxyConfiguration instance = provider.loadInstance(createAmbariConfigurationEntities(expectedProperties)); + Assert.assertNotNull(instance); + Assert.assertNotSame(expectedProperties, instance.toMap()); + Assert.assertEquals(expectedProperties, instance.toMap()); + + Assert.assertTrue(instance.isEnabled()); + Assert.assertEquals(expectedProperties.get("ambari.tproxy.proxyuser.knox.hosts"), instance.getAllowedHosts("knox")); + Assert.assertEquals(expectedProperties.get("ambari.tproxy.proxyuser.knox.users"), instance.getAllowedUsers("knox")); + Assert.assertEquals(expectedProperties.get("ambari.tproxy.proxyuser.knox.groups"), instance.getAllowedGroups("knox")); + } + + private Collection<AmbariConfigurationEntity> createAmbariConfigurationEntities(Map<String, String> properties) { + List<AmbariConfigurationEntity> entities = new ArrayList<>(); + + for (Map.Entry<String, String> entry : properties.entrySet()) { + AmbariConfigurationEntity entity = new AmbariConfigurationEntity(); + entity.setCategoryName(TPROXY_CONFIGURATION.getCategoryName()); + entity.setPropertyName(entry.getKey()); + entity.setPropertyValue(entry.getValue()); + entities.add(entity); + } + + return entities; + } + +} \ No newline at end of file diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationTest.java new file mode 100644 index 0000000..0c3e319 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/tproxy/AmbariTProxyConfigurationTest.java @@ -0,0 +1,70 @@ +/* + * 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.authentication.tproxy; + +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.TPROXY_ALLOWED_GROUPS; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.TPROXY_ALLOWED_HOSTS; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.TPROXY_ALLOWED_USERS; +import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.TPROXY_AUTHENTICATION_ENABLED; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +public class AmbariTProxyConfigurationTest { + + @Test + public void testEmptyConfiguration() { + AmbariTProxyConfiguration configuration = new AmbariTProxyConfiguration(null); + + Assert.assertFalse(configuration.isEnabled()); + + Assert.assertEquals(TPROXY_ALLOWED_HOSTS.getDefaultValue(), configuration.getAllowedHosts("knox")); + Assert.assertEquals(TPROXY_ALLOWED_USERS.getDefaultValue(), configuration.getAllowedUsers("knox")); + Assert.assertEquals(TPROXY_ALLOWED_GROUPS.getDefaultValue(), configuration.getAllowedGroups("knox")); + Assert.assertEquals(TPROXY_ALLOWED_HOSTS.getDefaultValue(), configuration.getAllowedHosts("otherproxyuser")); + Assert.assertEquals(TPROXY_ALLOWED_USERS.getDefaultValue(), configuration.getAllowedUsers("otherproxyuser")); + Assert.assertEquals(TPROXY_ALLOWED_GROUPS.getDefaultValue(), configuration.getAllowedGroups("otherproxyuser")); + } + + @Test + public void testNonEmptyConfiguration() { + Map<String, String> expectedProperties = new HashMap<>(); + expectedProperties.put(TPROXY_AUTHENTICATION_ENABLED.key(), "true"); + expectedProperties.put("ambari.tproxy.proxyuser.knox.hosts", "c7401.ambari.apache.org"); + expectedProperties.put("ambari.tproxy.proxyuser.knox.users", "*"); + expectedProperties.put("ambari.tproxy.proxyuser.knox.groups", "users"); + + AmbariTProxyConfiguration configuration = new AmbariTProxyConfiguration(expectedProperties); + + Assert.assertNotSame(expectedProperties, configuration.toMap()); + Assert.assertEquals(expectedProperties, configuration.toMap()); + + Assert.assertTrue(configuration.isEnabled()); + Assert.assertEquals(expectedProperties.get("ambari.tproxy.proxyuser.knox.hosts"), configuration.getAllowedHosts("knox")); + Assert.assertEquals(expectedProperties.get("ambari.tproxy.proxyuser.knox.users"), configuration.getAllowedUsers("knox")); + Assert.assertEquals(expectedProperties.get("ambari.tproxy.proxyuser.knox.groups"), configuration.getAllowedGroups("knox")); + + Assert.assertEquals(TPROXY_ALLOWED_HOSTS.getDefaultValue(), configuration.getAllowedHosts("otherproxyuser")); + Assert.assertEquals(TPROXY_ALLOWED_USERS.getDefaultValue(), configuration.getAllowedUsers("otherproxyuser")); + Assert.assertEquals(TPROXY_ALLOWED_GROUPS.getDefaultValue(), configuration.getAllowedGroups("otherproxyuser")); + } +} \ No newline at end of file diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java index b5f9dfe..2e9e9e0 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java @@ -36,6 +36,7 @@ import org.apache.ambari.server.audit.AuditLogger; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.UserDAO; import org.apache.ambari.server.security.AmbariEntryPoint; @@ -337,6 +338,7 @@ public class AmbariAuthorizationFilterTest { bind(AuditLogger.class).toInstance(EasyMock.createNiceMock(AuditLogger.class)); bind(HookService.class).toInstance(EasyMock.createMock(HookService.class)); bind(HookContextFactory.class).toInstance(EasyMock.createMock(HookContextFactory.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(EasyMock.createMock(AmbariLdapConfigurationProvider.class)); } }); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java index 8b52c9a..f7174f5 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java @@ -17,7 +17,6 @@ */ package org.apache.ambari.server.security.authorization; -import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.GROUP_MAPPING_RULES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; @@ -32,13 +31,10 @@ import java.util.List; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.H2DatabaseCleaner; -import org.apache.ambari.server.configuration.AmbariServerConfigurationCategory; -import org.apache.ambari.server.events.AmbariConfigurationChangedEvent; -import org.apache.ambari.server.events.JpaInitializedEvent; -import org.apache.ambari.server.events.publishers.AmbariEventPublisher; +import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.GuiceJpaInitializer; import org.apache.ambari.server.orm.InMemoryDefaultTestModule; -import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO; import org.apache.ambari.server.orm.dao.GroupDAO; import org.apache.ambari.server.orm.dao.PermissionDAO; import org.apache.ambari.server.orm.dao.PrincipalDAO; @@ -46,7 +42,6 @@ import org.apache.ambari.server.orm.dao.PrincipalTypeDAO; import org.apache.ambari.server.orm.dao.ResourceDAO; import org.apache.ambari.server.orm.dao.ResourceTypeDAO; import org.apache.ambari.server.orm.dao.UserDAO; -import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity; import org.apache.ambari.server.orm.entities.PermissionEntity; import org.apache.ambari.server.orm.entities.PrincipalEntity; import org.apache.ambari.server.orm.entities.PrincipalTypeEntity; @@ -58,6 +53,7 @@ import org.apache.ambari.server.security.ldap.LdapBatchDto; import org.apache.ambari.server.security.ldap.LdapGroupDto; import org.apache.ambari.server.security.ldap.LdapUserDto; import org.apache.ambari.server.security.ldap.LdapUserGroupMemberDto; +import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -540,16 +536,13 @@ public class TestUsers { @Test public void testProcessLdapSync() { - // Setup LDAP properties - AmbariConfigurationEntity entity = new AmbariConfigurationEntity(); - entity.setCategoryName(GROUP_MAPPING_RULES.getConfigurationCategory().getCategoryName()); - entity.setPropertyName(GROUP_MAPPING_RULES.key()); - entity.setPropertyValue("admins"); - injector.getInstance(AmbariConfigurationDAO.class).create(entity); - - AmbariEventPublisher eventPublisher = injector.getInstance(AmbariEventPublisher.class); - eventPublisher.publish(new JpaInitializedEvent()); - eventPublisher.publish(new AmbariConfigurationChangedEvent(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.name())); + AmbariLdapConfiguration ambariLdapConfiguration = EasyMock.createMock(AmbariLdapConfiguration.class); + EasyMock.expect(ambariLdapConfiguration.groupMappingRules()).andReturn("admins").anyTimes(); + + AmbariLdapConfigurationProvider ambariLdapConfigurationProvider = injector.getInstance(AmbariLdapConfigurationProvider.class); + EasyMock.expect(ambariLdapConfigurationProvider.get()).andReturn(ambariLdapConfiguration).anyTimes(); + + EasyMock.replay(ambariLdapConfigurationProvider, ambariLdapConfiguration); LdapBatchDto batchInfo = new LdapBatchDto(); LdapUserDto userToBeCreated; diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java index 5da80e6..cdb10be 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java @@ -38,6 +38,7 @@ import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.MemberDAO; import org.apache.ambari.server.orm.dao.PrincipalDAO; @@ -204,6 +205,7 @@ public class UsersTest extends EasyMockSupport { bind(HookContextFactory.class).toInstance(createMock(HookContextFactory.class)); bind(PrincipalDAO.class).toInstance(createMock(PrincipalDAO.class)); bind(Configuration.class).toInstance(createNiceMock(Configuration.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); } }); } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerActionTest.java index 9b6fe4f..cb29533 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerActionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerActionTest.java @@ -55,6 +55,7 @@ import org.apache.ambari.server.controller.UpdateConfigurationPolicy; import org.apache.ambari.server.events.AgentConfigsUpdateEvent; import org.apache.ambari.server.hooks.HookContextFactory; import org.apache.ambari.server.hooks.HookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; import org.apache.ambari.server.mpack.MpackManagerFactory; import org.apache.ambari.server.orm.dao.HostRoleCommandDAO; @@ -231,6 +232,7 @@ public class AbstractPrepareKerberosServerActionTest extends EasyMockSupport { Provider<EntityManager> entityManagerProvider = createNiceMock(Provider.class); bind(EntityManager.class).toProvider(entityManagerProvider); bind(MpackManagerFactory.class).toInstance(createNiceMock(MpackManagerFactory.class)); + bind(AmbariLdapConfigurationProvider.class).toInstance(createMock(AmbariLdapConfigurationProvider.class)); bind(new TypeLiteral<Encryptor<AgentConfigsUpdateEvent>>() {}).annotatedWith(Names.named("AgentConfigEncryptor")).toInstance(Encryptor.NONE); } }); 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 bb4db2f..9989f75 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 @@ -46,6 +46,7 @@ import org.apache.ambari.server.hooks.HookService; import org.apache.ambari.server.hooks.users.PostUserCreationHookContext; import org.apache.ambari.server.hooks.users.UserCreatedEvent; import org.apache.ambari.server.hooks.users.UserHookService; +import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider; import org.apache.ambari.server.ldap.service.LdapFacade; import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; @@ -246,7 +247,10 @@ public class PartialNiceMockBinder implements Module { } public Builder addLdapBindings() { - configurers.add((Binder binder) -> binder.bind(LdapFacade.class).toInstance(easyMockSupport.createNiceMock(LdapFacade.class))); + configurers.add((Binder binder) -> { + binder.bind(LdapFacade.class).toInstance(easyMockSupport.createNiceMock(LdapFacade.class)); + binder.bind(AmbariLdapConfigurationProvider.class).toInstance(easyMockSupport.createNiceMock(AmbariLdapConfigurationProvider.class)); + }); return this; }