/******************************************************************************* * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). * You may not use this product except in compliance with the License. * * This product includes a number of subcomponents with * separate copyright notices and license terms. Your use of these * subcomponents is subject to the terms and conditions of the * subcomponent's license, as noted in the LICENSE file. *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim.jdbc; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.resources.jdbc.JdbcPagingListFactory; import org.cloudfoundry.identity.uaa.scim.ScimGroup; import org.cloudfoundry.identity.uaa.scim.ScimGroupExternalMember; import org.cloudfoundry.identity.uaa.scim.exception.ScimResourceNotFoundException; import org.cloudfoundry.identity.uaa.scim.test.TestUtils; import org.cloudfoundry.identity.uaa.test.JdbcTestBase; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.JdbcIdentityZoneProvisioning; import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; import org.junit.Before; import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; public class JdbcScimGroupExternalMembershipManagerTests extends JdbcTestBase { private JdbcScimGroupProvisioning gdao; private JdbcScimGroupExternalMembershipManager edao; private static final String addGroupSqlFormat = "insert into groups (id, displayName, identity_zone_id) values ('%s','%s','%s')"; private String origin = OriginKeys.LDAP; private IdentityZone otherZone; @Before public void initJdbcScimGroupExternalMembershipManagerTests() { String zoneId = new RandomValueStringGenerator().generate(); otherZone = MultitenancyFixture.identityZone(zoneId,zoneId); otherZone = new JdbcIdentityZoneProvisioning(jdbcTemplate).create(otherZone); JdbcTemplate template = new JdbcTemplate(dataSource); JdbcPagingListFactory pagingListFactory = new JdbcPagingListFactory(template, limitSqlAdapter); gdao = new JdbcScimGroupProvisioning(template, pagingListFactory); edao = new JdbcScimGroupExternalMembershipManager(template, pagingListFactory); edao.setScimGroupProvisioning(gdao); for (IdentityZone zone : Arrays.asList(IdentityZone.getUaa(), otherZone)) { IdentityZoneHolder.set(zone); addGroup("g1-"+zone.getId(), "test1"); addGroup("g2-"+zone.getId(), "test2"); addGroup("g3-"+zone.getId(), "test3"); IdentityZoneHolder.clear(); } validateCount(0); } private void addGroup(String id, String name) { TestUtils.assertNoSuchUser(jdbcTemplate, "id", id); jdbcTemplate.execute(String.format(addGroupSqlFormat, id, name, IdentityZoneHolder.get().getId())); } private void validateCount(int expected) { int existingMemberCount = jdbcTemplate.queryForObject("select count(*) from external_group_mapping", Integer.class); assertEquals(expected, existingMemberCount); } @Test public void addExternalMappingToGroup() { createGroupMapping(); } @Test public void deleteGroupAndMappings() { createGroupMapping(); gdao.delete("g1-"+IdentityZoneHolder.get().getId(), -1); int mappingsCount = jdbcTemplate.queryForObject("select count(1) from " + JdbcScimGroupExternalMembershipManager.EXTERNAL_GROUP_MAPPING_TABLE, Integer.class); assertEquals(0, mappingsCount); } private void createGroupMapping() { ScimGroup group = gdao.retrieve("g1-"+IdentityZoneHolder.get().getId()); assertNotNull(group); ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); List<ScimGroupExternalMember> externalMapping = edao.getExternalGroupMapsByGroupId("g1-"+IdentityZoneHolder.get().getId(), origin); assertEquals(1, externalMapping.size()); } @Test(expected = ScimResourceNotFoundException.class) public void cannot_Retrieve_ById_For_OtherZone() { edao.getExternalGroupMapsByGroupId("g1-"+otherZone.getId(), origin); } @Test(expected = ScimResourceNotFoundException.class) public void cannot_Map_ById_For_OtherZone() { edao.mapExternalGroup("g1-" + otherZone.getId(), "CN=engineering,OU=groups,DC=example,DC=com", origin); } @Test public void using_filter_query_filters_by_zone() { map3GroupsInEachZone(); assertEquals(3, edao.query("").size()); assertEquals(3, edao.query("externalGroup sw \"cn\"").size()); assertEquals(3, edao.query("group_id sw \"g\"").size()); assertEquals(0, edao.query("origin eq \""+ OriginKeys.UAA+"\"").size()); assertEquals(3, edao.query("origin eq \""+ OriginKeys.LDAP+"\"").size()); } @Test public void using_filter_delete_filters_by_zone() { map3GroupsInEachZone(); assertEquals(3, edao.query("").size()); edao.delete(""); assertEquals(0, edao.query("").size()); assertThat(jdbcTemplate.queryForObject("select count(*) from external_group_mapping", Integer.class), is(3)); map3GroupsInEachZone(); assertEquals(3, edao.query("").size()); edao.delete("origin eq \""+ OriginKeys.LDAP+"\""); assertEquals(0, edao.query("").size()); assertThat(jdbcTemplate.queryForObject("select count(*) from external_group_mapping", Integer.class), is(3)); map3GroupsInEachZone(); assertEquals(3, edao.query("").size()); edao.delete("origin eq \""+ OriginKeys.UAA+"\""); assertEquals(3, edao.query("").size()); assertThat(jdbcTemplate.queryForObject("select count(*) from external_group_mapping", Integer.class), is(6)); } protected void map3GroupsInEachZone() { for (IdentityZone zone : Arrays.asList(IdentityZone.getUaa(), otherZone)) { IdentityZoneHolder.set(zone); { ScimGroupExternalMember member = edao.mapExternalGroup("g1-" + IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-" + IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g1-" + IdentityZoneHolder.get().getId(), "cn=hr,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-" + IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g1-" + IdentityZoneHolder.get().getId(), "cn=mgmt,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-" + IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=mgmt,ou=groups,dc=example,dc=com"); } IdentityZoneHolder.clear(); } } @Test public void adding_ExternalMappingToGroup_IsCaseInsensitive() throws Exception { createGroupMapping(); ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "CN=engineering,OU=groups,DC=example,DC=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); List<ScimGroupExternalMember> externalMapping = edao.getExternalGroupMapsByGroupId("g1-"+IdentityZoneHolder.get().getId(), origin); assertEquals(externalMapping.size(), 1); } @Test public void addExternalMappingToGroupThatAlreadyExists() { createGroupMapping(); ScimGroupExternalMember dupMember = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(dupMember.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(dupMember.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); } @Test public void addMultipleExternalMappingsToGroup() { ScimGroup group = gdao.retrieve("g1-"+IdentityZoneHolder.get().getId()); assertNotNull(group); { ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=hr,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=mgmt,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=mgmt,ou=groups,dc=example,dc=com"); } List<ScimGroupExternalMember> externalMappings = edao.getExternalGroupMapsByGroupId("g1-"+IdentityZoneHolder.get().getId(), origin); assertEquals(externalMappings.size(), 3); List<String> testGroups = new ArrayList<>( Arrays.asList( new String[] { "cn=engineering,ou=groups,dc=example,dc=com", "cn=hr,ou=groups,dc=example,dc=com", "cn=mgmt,ou=groups,dc=example,dc=com" } ) ); for (ScimGroupExternalMember member : externalMappings) { assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertNotNull(testGroups.remove(member.getExternalGroup())); } assertEquals(testGroups.size(), 0); } @Test public void addMultipleExternalMappingsToMultipleGroup() { { ScimGroup group = gdao.retrieve("g1-"+IdentityZoneHolder.get().getId()); assertNotNull(group); { ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=HR,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g1-"+IdentityZoneHolder.get().getId(), "cn=mgmt,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g1-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=mgmt,ou=groups,dc=example,dc=com"); } List<ScimGroupExternalMember> externalMappings = edao.getExternalGroupMapsByGroupId("g1-"+IdentityZoneHolder.get().getId(), origin); assertEquals(externalMappings.size(), 3); } { ScimGroup group = gdao.retrieve("g2-"+IdentityZoneHolder.get().getId()); assertNotNull(group); { ScimGroupExternalMember member = edao.mapExternalGroup("g2-"+IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g2-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g2-"+IdentityZoneHolder.get().getId(), "cn=HR,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g2-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g2-"+IdentityZoneHolder.get().getId(), "cn=mgmt,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g2-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=mgmt,ou=groups,dc=example,dc=com"); } List<ScimGroupExternalMember> externalMappings = edao.getExternalGroupMapsByGroupId("g2-"+IdentityZoneHolder.get().getId(), origin); assertEquals(externalMappings.size(), 3); } { ScimGroup group = gdao.retrieve("g3-"+IdentityZoneHolder.get().getId()); assertNotNull(group); { ScimGroupExternalMember member = edao.mapExternalGroup("g3-"+IdentityZoneHolder.get().getId(), "cn=engineering,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g3-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g3-"+IdentityZoneHolder.get().getId(), "cn=HR,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g3-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); } { ScimGroupExternalMember member = edao.mapExternalGroup("g3-"+IdentityZoneHolder.get().getId(), "cn=mgmt,ou=groups,dc=example,dc=com", origin); assertEquals(member.getGroupId(), "g3-"+IdentityZoneHolder.get().getId()); assertEquals(member.getExternalGroup(), "cn=mgmt,ou=groups,dc=example,dc=com"); } List<ScimGroupExternalMember> externalMappings = edao.getExternalGroupMapsByGroupId("g3-"+IdentityZoneHolder.get().getId(), origin); assertEquals(externalMappings.size(), 3); } List<String> testGroups = new ArrayList<>(Arrays.asList(new String[] { "g1-"+IdentityZoneHolder.get().getId(), "g2-"+IdentityZoneHolder.get().getId(), "g3-"+IdentityZoneHolder.get().getId() })); { // LDAP groups are case preserving on fetch and case insensitive on // search List<ScimGroupExternalMember> externalMappings = edao .getExternalGroupMapsByExternalGroup("cn=engineering,ou=groups,dc=example,dc=com", origin); for (ScimGroupExternalMember member : externalMappings) { assertEquals(member.getExternalGroup(), "cn=engineering,ou=groups,dc=example,dc=com"); assertNotNull(testGroups.remove(member.getGroupId())); } assertEquals(testGroups.size(), 0); } { // LDAP groups are case preserving on fetch and case insensitive on // search List<ScimGroupExternalMember> externalMappings = edao .getExternalGroupMapsByExternalGroup("cn=hr,ou=groups,dc=example,dc=com", origin); for (ScimGroupExternalMember member : externalMappings) { assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); assertNotNull(testGroups.remove(member.getGroupId())); } assertEquals(testGroups.size(), 0); List<ScimGroupExternalMember> externalMappings2 = edao .getExternalGroupMapsByExternalGroup("cn=HR,ou=groups,dc=example,dc=com", origin); for (ScimGroupExternalMember member : externalMappings2) { assertEquals(member.getExternalGroup(), "cn=hr,ou=groups,dc=example,dc=com"); assertNotNull(testGroups.remove(member.getGroupId())); } assertEquals(testGroups.size(), 0); } { // LDAP groups are case preserving on fetch and case insensitive on // search List<ScimGroupExternalMember> externalMappings = edao .getExternalGroupMapsByExternalGroup("cn=mgmt,ou=groups,dc=example,dc=com", origin); for (ScimGroupExternalMember member : externalMappings) { assertEquals(member.getExternalGroup(), "cn=mgmt,ou=groups,dc=example,dc=com"); assertNotNull(testGroups.remove(member.getGroupId())); } assertEquals(testGroups.size(), 0); } } }