content: /*
   * 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.authorization;
  
  import static java.util.Collections.emptySet;
  import static org.easymock.EasyMock.expect;
  import static org.easymock.EasyMock.mock;
  import static org.easymock.EasyMock.replay;
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNotNull;
  import static org.junit.Assert.assertNotSame;
  import static org.junit.Assert.assertNull;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
  
  import java.sql.SQLException;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.List;
  
  import org.apache.ambari.server.AmbariException;
  import org.apache.ambari.server.H2DatabaseCleaner;
  import org.apache.ambari.server.configuration.Configuration;
  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.GroupDAO;
  import org.apache.ambari.server.orm.dao.PermissionDAO;
  import org.apache.ambari.server.orm.dao.PrincipalDAO;
  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.PermissionEntity;
  import org.apache.ambari.server.orm.entities.PrincipalEntity;
  import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
  import org.apache.ambari.server.orm.entities.ResourceEntity;
  import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
  import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
  import org.apache.ambari.server.orm.entities.UserEntity;
  import org.apache.ambari.server.security.authentication.AmbariUserDetailsImpl;
  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;
  import org.springframework.security.core.Authentication;
  import org.springframework.security.core.context.SecurityContext;
  import org.springframework.security.core.context.SecurityContextHolder;
  import org.springframework.security.crypto.password.PasswordEncoder;
  
  import com.google.inject.Guice;
  import com.google.inject.Inject;
  import com.google.inject.Injector;
  
  import junit.framework.Assert;
  
  public class TestUsers {
    private Injector injector;
  
    @Inject
    protected Users users;
    @Inject
    protected UserDAO userDAO;
    @Inject
    protected GroupDAO groupDAO;
    @Inject
    protected PermissionDAO permissionDAO;
    @Inject
    protected ResourceDAO resourceDAO;
    @Inject
    protected ResourceTypeDAO resourceTypeDAO;
    @Inject
    protected PrincipalTypeDAO principalTypeDAO;
    @Inject
    protected PrincipalDAO principalDAO;
    @Inject
    protected PasswordEncoder passwordEncoder;
    @Inject
    protected Configuration configuration;
  
    @Before
    public void setup() throws AmbariException {
      InMemoryDefaultTestModule module = new InMemoryDefaultTestModule();
      injector = Guice.createInjector(module);
      injector.getInstance(GuiceJpaInitializer.class);
      injector.injectMembers(this);
  
      // create admin permission
      ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
      resourceTypeEntity.setId(ResourceType.AMBARI.getId());
      resourceTypeEntity.setName(ResourceType.AMBARI.name());
      resourceTypeDAO.create(resourceTypeEntity);
  
      ResourceEntity resourceEntity = new ResourceEntity();
      resourceEntity.setId(ResourceEntity.AMBARI_RESOURCE_ID);
      resourceEntity.setResourceType(resourceTypeEntity);
      resourceDAO.create(resourceEntity);
  
      PrincipalTypeEntity principalTypeEntity = new PrincipalTypeEntity();
      principalTypeEntity.setName("ROLE");
      principalTypeEntity = principalTypeDAO.merge(principalTypeEntity);
  
      PrincipalEntity principalEntity = new PrincipalEntity();
      principalEntity.setPrincipalType(principalTypeEntity);
      principalEntity = principalDAO.merge(principalEntity);
  
      PermissionEntity adminPermissionEntity = new PermissionEntity();
      adminPermissionEntity.setId(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION);
      adminPermissionEntity.setPermissionName(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION_NAME);
      adminPermissionEntity.setPrincipal(principalEntity);
      adminPermissionEntity.setResourceType(resourceTypeEntity);
      permissionDAO.create(adminPermissionEntity);
    }
  
    @After
    public void tearDown() throws AmbariException, SQLException {
      H2DatabaseCleaner.clearDatabaseAndStopPersistenceService(injector);
    }
  
  
    @Test
    public void testIsUserCanBeRemoved() throws Exception {
      UserEntity userEntity;
  
      userEntity = users.createUser("admin", "admin", "admin");
      users.grantAdminPrivilege(userEntity);
  
      userEntity = users.createUser("admin222", "admin222", "admin22");
      users.grantAdminPrivilege(userEntity);
  
      Assert.assertTrue(users.isUserCanBeRemoved(userDAO.findUserByName("admin")));
      Assert.assertTrue(users.isUserCanBeRemoved(userDAO.findUserByName("admin222")));
  
      users.removeUser(users.getUser("admin222"));
  
      Assert.assertFalse(users.isUserCanBeRemoved(userDAO.findUserByName("admin")));
      users.createUser("user", "user", "user");
      Assert.assertFalse(users.isUserCanBeRemoved(userDAO.findUserByName("admin")));
  
      userEntity = users.createUser("admin333", "admin333", "admin333");
      users.grantAdminPrivilege(userEntity);
  
      Assert.assertTrue(users.isUserCanBeRemoved(userDAO.findUserByName("admin")));
      Assert.assertTrue(users.isUserCanBeRemoved(userDAO.findUserByName("admin333")));
    }
  
    @Test
    public void testModifyPassword_UserByAdmin() throws Exception {
      UserEntity userEntity;
  
      userEntity = users.createUser("admin", "admin", "admin");
      users.grantAdminPrivilege(userEntity);
      users.addLocalAuthentication(userEntity, "test_password");
  
      setAuthenticatedUser(userEntity);
  
      userEntity = users.createUser("user", "user", "user");
      users.addLocalAuthentication(userEntity, "test_password");
  
      UserEntity foundUserEntity = userDAO.findUserByName("user");
      assertNotNull(foundUserEntity);
  
      UserAuthenticationEntity foundLocalAuthenticationEntity;
      foundLocalAuthenticationEntity = getAuthenticationEntity(foundUserEntity, UserAuthenticationType.LOCAL);
      assertNotNull(foundLocalAuthenticationEntity);
      assertNotSame("test_password", foundLocalAuthenticationEntity.getAuthenticationKey());
      assertTrue(passwordEncoder.matches("test_password", foundLocalAuthenticationEntity.getAuthenticationKey()));
  
      foundUserEntity = userDAO.findUserByName("admin");
      assertNotNull(foundUserEntity);
      users.modifyAuthentication(foundLocalAuthenticationEntity, "test_password", "new_test_password", false);
  
      foundUserEntity = userDAO.findUserByName("user");
      assertNotNull(foundUserEntity);
      foundLocalAuthenticationEntity = getAuthenticationEntity(foundUserEntity, UserAuthenticationType.LOCAL);
      assertNotNull(foundLocalAuthenticationEntity);
      assertTrue(passwordEncoder.matches("new_test_password", foundLocalAuthenticationEntity.getAuthenticationKey()));
    }
  
    @Test
    public void testModifyPassword_EmptyPassword() throws Exception {
      UserEntity userEntity;
  
      userEntity = users.createUser("user", "user", "user");
      users.addLocalAuthentication(userEntity, "test_password");
  
      UserEntity foundUserEntity = userDAO.findUserByName("user");
      assertNotNull(foundUserEntity);
  
      UserAuthenticationEntity foundLocalAuthenticationEntity;
      foundLocalAuthenticationEntity = getAuthenticationEntity(foundUserEntity, UserAuthenticationType.LOCAL);
      assertNotNull(foundLocalAuthenticationEntity);
      assertNotSame("test_password", foundLocalAuthenticationEntity.getAuthenticationKey());
      assertTrue(passwordEncoder.matches("test_password", foundLocalAuthenticationEntity.getAuthenticationKey()));
  
      try {
        users.modifyAuthentication(foundLocalAuthenticationEntity, "test_password", null, true);
        fail("Null password should not be allowed");
      } catch (IllegalArgumentException e) {
        assertEquals("The password does not meet the password policy requirements", e.getLocalizedMessage());
      }
  
      try {
        users.modifyAuthentication(foundLocalAuthenticationEntity, "test_password", "", false);
        fail("Empty password should not be allowed");
      } catch (IllegalArgumentException e) {
        assertEquals("The password does not meet the password policy requirements", e.getLocalizedMessage());
      }
  
      //Minimum eight characters, at least one letter and one number:
      configuration.setProperty(Configuration.PASSWORD_POLICY_REGEXP, "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$");
      configuration.setProperty(Configuration.PASSWORD_POLICY_DESCRIPTION, "test description");
      try {
        users.modifyAuthentication(foundLocalAuthenticationEntity, "test_password", "abc123", false);
        fail("Should not pass validation");
      } catch (IllegalArgumentException e) {
        assertEquals("The password does not meet the Ambari user password policy : test description", e.getLocalizedMessage());
      }
      users.modifyAuthentication(foundLocalAuthenticationEntity, "test_password", "abcd1234", false);
    }
  
    @Test
    public void testRevokeAdminPrivilege() throws Exception {
      final UserEntity userEntity = users.createUser("old_admin", "old_admin", "old_admin");
      users.grantAdminPrivilege(userEntity);
  
      final User admin = users.getUser("old_admin");
      users.revokeAdminPrivilege(admin.getUserId());
  
      Assert.assertFalse(users.getUser("old_admin").isAdmin());
    }
  
    @Test
    public void testGrantAdminPrivilege() throws Exception {
      users.createUser("user", "user", "user");
  
      final User user = users.getUser("user");
      users.grantAdminPrivilege(user.getUserId());
  
      Assert.assertTrue(users.getUser("user").isAdmin());
    }
  
    @Test
    public void testCreateGetRemoveUser() throws Exception {
      users.createUser("user1", "user1", null);
      users.createUser("user", "user", null, false);
  
      UserEntity userEntity = users.createUser("user_ldap", "user_ldap", null);
      users.grantAdminPrivilege(userEntity);
      users.addLdapAuthentication(userEntity, "some dn");
  
      User createdUser = users.getUser("user");
      User createdUser1 = users.getUser("user1");
      User createdLdapUser = users.getUser("user_ldap");
  
      Assert.assertEquals("user1", createdUser1.getUserName());
      Assert.assertEquals(true, createdUser1.isActive());
      Assert.assertEquals(false, createdUser1.isLdapUser());
      Assert.assertEquals(false, createdUser1.isAdmin());
  
      Assert.assertEquals("user", createdUser.getUserName());
      Assert.assertEquals(false, createdUser.isActive());
      Assert.assertEquals(false, createdUser.isLdapUser());
      Assert.assertEquals(false, createdUser.isAdmin());
  
      Assert.assertEquals("user_ldap", createdLdapUser.getUserName());
      Assert.assertEquals(true, createdLdapUser.isActive());
      Assert.assertEquals(true, createdLdapUser.isLdapUser());
      Assert.assertEquals(true, createdLdapUser.isAdmin());
  
      assertEquals("user", users.getUser("user").getUserName());
      assertEquals("user_ldap", users.getUser("user_ldap").getUserName());
      Assert.assertNull(users.getUser("non_existing"));
  
      // create duplicate user
      try {
        users.createUser("user1", "user1", null);
        fail("It shouldn't be possible to create duplicate user");
      } catch (AmbariException e) {
        // This is expected
      }
  
      try {
        users.createUser("USER1", "user1", null);
        fail("It shouldn't be possible to create duplicate user");
      } catch (AmbariException e) {
        // This is expected
      }
  
      // test get all users
      List<User> userList = users.getAllUsers();
  
      Assert.assertEquals(3, userList.size());
  
      // check get any user case insensitive
      assertEquals("user", users.getUser("USER").getUserName());
      assertEquals("user_ldap", users.getUser("USER_LDAP").getUserName());
      Assert.assertNull(users.getUser("non_existing"));
  
      // get user by id
      User userById = users.getUser(createdUser.getUserId());
  
      assertNotNull(userById);
      assertEquals(createdUser.getUserId(), userById.getUserId());
  
      // get user by invalid id
      User userByInvalidId = users.getUser(-1);
  
      assertNull(userByInvalidId);
  
      // get user if unique
      Assert.assertNotNull(users.getUser("user"));
  
      //remove user
      Assert.assertEquals(3, users.getAllUsers().size());
  
      users.removeUser(users.getUser("user1"));
  
      Assert.assertNull(users.getUser("user1"));
      Assert.assertEquals(2, users.getAllUsers().size());
    }
  
    @Test
    public void testSetUserActive() throws Exception {
      users.createUser("user", "user", null);
  
      users.setUserActive("user", false);
      Assert.assertEquals(false, users.getUser("user").isActive());
      users.setUserActive("user", true);
      Assert.assertEquals(true, users.getUser("user").isActive());
  
      try {
        users.setUserActive("fake user", true);
        fail("It shouldn't be possible to call setUserActive() on non-existing user");
      } catch (Exception ex) {
        // This is expected
      }
    }
  
    @Test
    public void testSetUserLdap() throws Exception {
      UserEntity userEntity;
  
      users.createUser("user", "user", null);
      users.addLdapAuthentication(users.getUserEntity("user"), "some dn");
  
      userEntity = users.createUser("user_ldap", "user_ldap", null);
      users.addLdapAuthentication(userEntity, "some dn");
  
      Assert.assertEquals(true, users.getUser("user").isLdapUser());
      Assert.assertEquals(true, users.getUser("user_ldap").isLdapUser());
  
      try {
        users.addLdapAuthentication(users.getUserEntity("fake user"), "some other dn");
        fail("It shouldn't be possible to call setUserLdap() on non-existing user");
      } catch (AmbariException ex) {
        // This is expected
      }
    }
  
    @Test
    public void testSetGroupLdap() throws Exception {
      users.createGroup("group", GroupType.LOCAL);
  
      users.setGroupLdap("group");
      Assert.assertNotNull(users.getGroup("group"));
      Assert.assertTrue(users.getGroup("group").isLdapGroup());
  
      try {
        users.setGroupLdap("fake group");
        fail("It shouldn't be possible to call setGroupLdap() on non-existing group");
      } catch (AmbariException ex) {
        // This is expected
      }
    }
  
    @Test
    public void testCreateGetRemoveGroup() throws Exception {
      final String groupName = "engineering1";
      final String groupName2 = "engineering2";
      users.createGroup(groupName, GroupType.LOCAL);
      users.createGroup(groupName2, GroupType.LOCAL);
  
      final Group group = users.getGroup(groupName);
      assertNotNull(group);
      assertEquals(false, group.isLdapGroup());
      assertEquals(groupName, group.getGroupName());
  
      assertNotNull(groupDAO.findGroupByName(groupName));
  
      // get all groups
      final List<Group> groupList = users.getAllGroups();
  
      assertEquals(2, groupList.size());
      assertEquals(2, groupDAO.findAll().size());
  
      // remove group
      users.removeGroup(group);
      assertNull(users.getGroup(group.getGroupName()));
      assertEquals(1, users.getAllGroups().size());
    }
  
    @Test
    public void testMembers() throws Exception {
      final String groupName = "engineering";
      final String groupName2 = "engineering2";
      users.createGroup(groupName, GroupType.LOCAL);
      users.createGroup(groupName2, GroupType.LOCAL);
      users.createUser("user1", "user1", null);
      users.createUser("user2", "user2", null);
      users.createUser("user3", "user3", null);
      users.addMemberToGroup(groupName, "user1");
      users.addMemberToGroup(groupName, "user2");
      assertEquals(2, users.getAllMembers(groupName).size());
      assertEquals(0, users.getAllMembers(groupName2).size());
  
      try {
        users.getAllMembers("non existing");
        fail("It shouldn't be possible to call getAllMembers() on non-existing group");
      } catch (Exception ex) {
        // This is expected
      }
  
      // get members from not unexisting group
      assertEquals(users.getGroupMembers("unexisting"), null);
  
      // remove member from group
      users.removeMemberFromGroup(groupName, "user1");
      assertEquals(1, groupDAO.findGroupByName(groupName).getMemberEntities().size());
      assertEquals("user2", groupDAO.findGroupByName(groupName).getMemberEntities().iterator().next().getUser().getUserName());
    }
  
    @Test
    public void testModifyPassword_UserByHimselfPasswordOk() throws Exception {
      UserEntity userEntity = users.createUser("user", "user", null);
      users.addLocalAuthentication(userEntity, "test_password");
  
      userEntity = userDAO.findUserByName("user");
      UserAuthenticationEntity localAuthenticationEntity = getAuthenticationEntity(userEntity, UserAuthenticationType.LOCAL);
      assertNotNull(localAuthenticationEntity);
  
      assertNotSame("test_password", localAuthenticationEntity.getAuthenticationKey());
      assertTrue(passwordEncoder.matches("test_password", localAuthenticationEntity.getAuthenticationKey()));
  
      users.modifyAuthentication(localAuthenticationEntity, "test_password", "new_test_password", true);
      userEntity = userDAO.findUserByName("user");
      localAuthenticationEntity = getAuthenticationEntity(userEntity, UserAuthenticationType.LOCAL);
      assertNotNull(localAuthenticationEntity);
  
      assertTrue(passwordEncoder.matches("new_test_password", localAuthenticationEntity.getAuthenticationKey()));
    }
  
    @Test
    public void testModifyPassword_UserByHimselfPasswordNotOk() throws Exception {
      UserEntity userEntity = users.createUser("user", "user", null);
      users.addLocalAuthentication(userEntity, "test_password");
  
      userEntity = userDAO.findUserByName("user");
      UserAuthenticationEntity foundLocalAuthenticationEntity;
      foundLocalAuthenticationEntity = getAuthenticationEntity(userEntity, UserAuthenticationType.LOCAL);
      assertNotNull(foundLocalAuthenticationEntity);
      assertNotSame("test_password", foundLocalAuthenticationEntity.getAuthenticationKey());
      assertTrue(passwordEncoder.matches("test_password", foundLocalAuthenticationEntity.getAuthenticationKey()));
  
      try {
        users.modifyAuthentication(foundLocalAuthenticationEntity, "incorrect_test_password", "new_test_password", true);
        fail("Exception should be thrown here as password is incorrect");
      } catch (AmbariException ex) {
        // This is expected
      }
    }
  
    @Test
    public void testAddAndRemoveAuthentication() throws Exception {
      users.createUser("user", "user", "user");
  
      UserEntity userEntity = userDAO.findUserByName("user");
      assertNotNull(userEntity);
      assertEquals("user", userEntity.getUserName());
  
      UserEntity userEntity2 = userDAO.findUserByName("user");
      assertNotNull(userEntity2);
      assertEquals("user", userEntity2.getUserName());
  
      assertEquals(0, users.getUserAuthenticationEntities("user", null).size());
  
      users.addAuthentication(userEntity, UserAuthenticationType.LOCAL, "local_key");
      assertEquals(1, users.getUserAuthenticationEntities("user", null).size());
      assertEquals(1, users.getUserAuthenticationEntities("user", UserAuthenticationType.LOCAL).size());
      assertTrue(passwordEncoder.matches("local_key", users.getUserAuthenticationEntities("user", UserAuthenticationType.LOCAL).iterator().next().getAuthenticationKey()));
      assertEquals(0, users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).size());
  
      users.addAuthentication(userEntity, UserAuthenticationType.PAM, "pam_key");
      assertEquals(2, users.getUserAuthenticationEntities("user", null).size());
      assertEquals(1, users.getUserAuthenticationEntities("user", UserAuthenticationType.PAM).size());
      assertEquals("pam_key", users.getUserAuthenticationEntities("user", UserAuthenticationType.PAM).iterator().next().getAuthenticationKey());
      assertEquals(0, users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).size());
  
      users.addAuthentication(userEntity, UserAuthenticationType.JWT, "jwt_key");
      assertEquals(3, users.getUserAuthenticationEntities("user", null).size());
      assertEquals(1, users.getUserAuthenticationEntities("user", UserAuthenticationType.JWT).size());
      assertEquals("jwt_key", users.getUserAuthenticationEntities("user", UserAuthenticationType.JWT).iterator().next().getAuthenticationKey());
      assertEquals(0, users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).size());
  
      users.addAuthentication(userEntity, UserAuthenticationType.LDAP, "ldap_key");
      assertEquals(4, users.getUserAuthenticationEntities("user", null).size());
      assertEquals(1, users.getUserAuthenticationEntities("user", UserAuthenticationType.LDAP).size());
      assertEquals("ldap_key", users.getUserAuthenticationEntities("user", UserAuthenticationType.LDAP).iterator().next().getAuthenticationKey());
      assertEquals(0, users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).size());
  
      users.addAuthentication(userEntity, UserAuthenticationType.KERBEROS, "kerberos_key");
      assertEquals(5, users.getUserAuthenticationEntities("user", null).size());
      assertEquals("kerberos_key", users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).iterator().next().getAuthenticationKey());
      assertEquals(1, users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).size());
  
      // UserEntity was updated by user.addAuthentication
      assertEquals(5, userEntity.getAuthenticationEntities().size());
  
      // UserEntity2 needs to be refreshed...
      assertEquals(0, userEntity2.getAuthenticationEntities().size());
      userEntity2 = userDAO.findUserByName("user");
      assertEquals(5, userEntity2.getAuthenticationEntities().size());
  
  
      // Test Remove
      Long kerberosAuthenticationId = users.getUserAuthenticationEntities("user", UserAuthenticationType.KERBEROS).iterator().next().getUserAuthenticationId();
      Long pamAuthenticationId = users.getUserAuthenticationEntities("user", UserAuthenticationType.PAM).iterator().next().getUserAuthenticationId();
  
      users.removeAuthentication("user", kerberosAuthenticationId);
      assertEquals(4, users.getUserAuthenticationEntities("user", null).size());
  
      users.removeAuthentication(userEntity, kerberosAuthenticationId);
      assertEquals(4, users.getUserAuthenticationEntities("user", null).size());
  
      users.removeAuthentication(userEntity, pamAuthenticationId);
      assertEquals(3, users.getUserAuthenticationEntities("user", null).size());
  
      assertEquals(3, userEntity2.getAuthenticationEntities().size());
    }
  
    @Test
    public void testProcessLdapSync() {
      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;
      LdapGroupDto groupToBeCreated;
  
      userToBeCreated = new LdapUserDto();
      userToBeCreated.setDn("dn=user1");
      userToBeCreated.setUid("user1");
      userToBeCreated.setUserName("User1");
      batchInfo.getUsersToBeCreated().add(userToBeCreated);
  
      userToBeCreated = new LdapUserDto();
      userToBeCreated.setDn("dn=user2");
      userToBeCreated.setUid("user2");
      userToBeCreated.setUserName("User2");
      batchInfo.getUsersToBeCreated().add(userToBeCreated);
  
      groupToBeCreated = new LdapGroupDto();
      groupToBeCreated.setGroupName("admins");
      groupToBeCreated.setMemberAttributes(Collections.singleton("dn=User1"));
      batchInfo.getGroupsToBeCreated().add(groupToBeCreated);
  
      groupToBeCreated = new LdapGroupDto();
      groupToBeCreated.setGroupName("non-admins");
      groupToBeCreated.setMemberAttributes(Collections.singleton("dn=User2"));
      batchInfo.getGroupsToBeCreated().add(groupToBeCreated);
  
      batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto("admins", "user1"));
      batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto("non-admins", "user2"));
  
      users.processLdapSync(batchInfo);
  
      assertNotNull(users.getUser("user1"));
      assertNotNull(users.getUser("user2"));
  
      Collection<AmbariGrantedAuthority> authorities;
  
      authorities = users.getUserAuthorities("user1");
      assertNotNull(authorities);
      assertEquals(1, authorities.size());
      assertEquals("AMBARI.ADMINISTRATOR", authorities.iterator().next().getPrivilegeEntity().getPermission().getPermissionName());
  
      authorities = users.getUserAuthorities("user2");
      assertNotNull(authorities);
      assertEquals(0, authorities.size());
    }
  
    private UserAuthenticationEntity getAuthenticationEntity(UserEntity userEntity, UserAuthenticationType type) {
      assertNotNull(userEntity);
      Collection<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
      assertNotNull(authenticationEntities);
      for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
        if (authenticationEntity.getAuthenticationType() == type) {
          return authenticationEntity;
        }
      }
  
      return null;
    }
  
    private void setAuthenticatedUser(UserEntity userEntity) {
      AmbariUserDetailsImpl principal = new AmbariUserDetailsImpl(new User(userEntity), "", emptySet());
      Authentication auth = mock(Authentication.class);
      expect(auth.getPrincipal()).andReturn(principal).anyTimes();
      SecurityContext securityContext = mock(SecurityContext.class);
      expect(securityContext.getAuthentication()).andReturn(auth).anyTimes();
      replay(auth, securityContext);
      SecurityContextHolder.setContext(securityContext);
    }
  }
  