/** * */ package org.identityconnectors.oracle; import static org.fest.assertions.Assertions.assertThat; import static org.identityconnectors.oracle.OracleUserAttribute.PROFILE; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import java.sql.SQLException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.identityconnectors.common.CollectionUtil; import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.dbcommon.SQLUtil; import org.identityconnectors.framework.common.exceptions.ConnectorException; import org.identityconnectors.framework.common.exceptions.UnknownUidException; import org.identityconnectors.framework.common.objects.Attribute; import org.identityconnectors.framework.common.objects.AttributeBuilder; import org.identityconnectors.framework.common.objects.Name; import org.identityconnectors.framework.common.objects.ObjectClass; import org.identityconnectors.framework.common.objects.OperationalAttributes; import org.identityconnectors.framework.common.objects.Uid; import org.identityconnectors.framework.spi.operations.UpdateOp; import org.identityconnectors.test.common.TestHelpers; import org.testng.Assert; import org.testng.AssertJUnit; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * @author kitko * */ @Test(groups = { "integration" }) public class OracleOperationUpdateTest extends OracleConnectorAbstractTest { private static final String TEST_USER = "testUser"; private Uid uid; private GuardedString password; /** * Creates test user to be used in all test methods */ @BeforeMethod public void createTestUser() { uid = new Uid(TEST_USER); try { facade.delete(ObjectClass.ACCOUNT, uid, null); } catch (UnknownUidException e) { } Attribute authentication = AttributeBuilder.build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_LOCAL); Attribute name = new Name(TEST_USER); password = new GuardedString("hello".toCharArray()); Attribute passwordAttribute = AttributeBuilder.buildPassword(password); Attribute privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "create session"); uid = facade.create(ObjectClass.ACCOUNT, CollectionUtil.newSet(authentication, name, passwordAttribute, privileges), null); } /** * Deletes test user */ @AfterMethod public void deleteTestUser() { facade.delete(ObjectClass.ACCOUNT, uid, null); } /** * Test method for * {@link org.identityconnectors.oracle.OracleOperationUpdate#update(org.identityconnectors.framework.common.objects.ObjectClass, org.identityconnectors.framework.common.objects.Uid, java.util.Set, org.identityconnectors.framework.common.objects.OperationOptions)} * . */ @Test public void testUpdatePassword() { password = new GuardedString("newPassword".toCharArray()); Attribute passwordAttribute = AttributeBuilder.buildPassword(password); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(passwordAttribute), null); // now try to authenticate facade.authenticate(ObjectClass.ACCOUNT, uid.getUidValue(), password, null); // If password is present, for external auth we must fail try { facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL), AttributeBuilder .buildPassword("password".toCharArray())), null); Assert.fail("Update must fail with external authntication and password"); } catch (ConnectorException e) { } // Now set ignore extra attributes OracleConfiguration newConf = OracleConfigurationTest.createSystemConfiguration(); newConf.validate(); newConf.setExtraAttributesPolicySetup(new ExtraAttributesPolicySetupBuilder(TestHelpers .createDummyMessages()).definePolicy(OracleUserAttribute.PASSWORD, UpdateOp.class, ExtraAttributesPolicy.IGNORE).build()); OracleConnector testConnector = new OracleConnector(); testConnector.init(newConf); testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL), AttributeBuilder .buildPassword("password".toCharArray())), null); // update to external testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL)), null); // if we update only password, and no other attributes, this should fail try { testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPassword("password".toCharArray())), null); Assert.fail("Update must fail with external authntication and password"); } catch (ConnectorException e) { } // but if we update e.g also quota, it should pass testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPassword("newPassword".toCharArray()), AttributeBuilder.build( OracleConstants.ORACLE_DEF_TS_QUOTA_ATTR_NAME, "10k")), null); // If updating only extra attributes, this should fail newConf.setExtraAttributesPolicySetup(new ExtraAttributesPolicySetupBuilder(TestHelpers .createDummyMessages()).definePolicy(OracleUserAttribute.PASSWORD_EXPIRE, UpdateOp.class, ExtraAttributesPolicy.IGNORE).definePolicy( OracleUserAttribute.PASSWORD, UpdateOp.class, ExtraAttributesPolicy.IGNORE).build()); try { testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPasswordExpired(true), AttributeBuilder.buildPassword("newPassword" .toCharArray())), null); Assert.fail("Update must fail with external authentication and password and password expired"); } catch (ConnectorException e) { } testConnector.dispose(); } /** * Test updating authentication * * @throws SQLException */ @Test public void testUpdateAuthentication() throws SQLException { // Update to local facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil .newSet(AttributeBuilder.build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_LOCAL)), null); UserRecord record = userReader.readUserRecord(uid.getUidValue()); assertEquals(OracleAuthentication.LOCAL, OracleUserReader.resolveAuthentication(record)); // Update to external facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL)), null); record = userReader.readUserRecord(uid.getUidValue()); assertEquals(OracleAuthentication.EXTERNAL, OracleUserReader.resolveAuthentication(record)); // Update to global try { facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_GLOBAL), AttributeBuilder.build( OracleConstants.ORACLE_GLOBAL_ATTR_NAME, "anyGlobal")), null); record = userReader.readUserRecord(uid.getUidValue()); assertEquals(OracleAuthentication.GLOBAL, OracleUserReader .resolveAuthentication(record)); assertEquals("anyGlobal", record.getExternalName()); } catch (ConnectorException e) { if (e.getCause() instanceof SQLException) { if ("67000".equals(((SQLException) e.getCause()).getSQLState()) && 439 == ((SQLException) e.getCause()).getErrorCode()) { } else { Assert.fail(e.getMessage()); } } else { Assert.fail(e.getMessage()); } } } /** * Test update of profile * * @throws SQLException */ @Test public void testUpdateProfile() throws SQLException { String profileName = "myProfile"; try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop profile " + testConf.getCSSetup().normalizeAndFormatToken(PROFILE, profileName)); } catch (SQLException e) { } try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create profile " + testConf.getCSSetup().normalizeAndFormatToken(PROFILE, profileName) + "limit password_lock_time 6"); connector.getOrCreateAdminConnection().commit(); } catch (SQLException e) { Assert.fail(e.getMessage()); } Attribute profileAttr = AttributeBuilder.build(OracleConstants.ORACLE_PROFILE_ATTR_NAME, profileName); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(profileAttr), null); final UserRecord record = userReader.readUserRecord(uid.getUidValue()); assertEquals(testConf.getCSSetup().normalizeToken(PROFILE, profileName), record .getProfile()); try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop profile " + testConf.getCSSetup().normalizeAndFormatToken(PROFILE, profileName)); } catch (SQLException e) { } } @Test public void testUpdateDefTSQuota() throws SQLException { Attribute defaultTsQuotaAttr = AttributeBuilder.build(OracleConstants.ORACLE_DEF_TS_QUOTA_ATTR_NAME, "30k"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(defaultTsQuotaAttr), null); Long quota = userReader.readUserDefTSQuota(uid.getUidValue()); AssertJUnit.assertTrue("Quota must be at least 30k", new Long(30000).compareTo(quota) < 0); defaultTsQuotaAttr = AttributeBuilder.build(OracleConstants.ORACLE_DEF_TS_QUOTA_ATTR_NAME, "-1"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(defaultTsQuotaAttr), null); quota = userReader.readUserDefTSQuota(uid.getUidValue()); Assert.assertEquals(new Long(-1), quota, "Quota must be set to -1 for unlimited quota"); } @Test public void testUpdateDefTS() throws SQLException { // Test that update to same ts works String defaultTableSpace = userReader.readUserRecord(uid.getUidValue()).getDefaultTableSpace(); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder.build( OracleConstants.ORACLE_DEF_TS_ATTR_NAME, defaultTableSpace)), null); // Now try to update with other tablespaces, if update is successfull, // check whether it is correctly set for (String ts : findAllDefTS(connector.getOrCreateAdminConnection())) { try { facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .build(OracleConstants.ORACLE_DEF_TS_ATTR_NAME, ts)), null); } catch (Exception e) { // For any reason , when tablespace cannot be used for user continue; } assertEquals(ts, userReader.readUserRecord(uid.getUidValue()).getDefaultTableSpace()); } } @Test public void testUpdateTempTS() throws SQLException { // Test that update to same ts works String tempTableSpace = userReader.readUserRecord(uid.getUidValue()).getTemporaryTableSpace(); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder.build( OracleConstants.ORACLE_TEMP_TS_ATTR_NAME, tempTableSpace)), null); // Now try to update with other tablespaces, if update is successfull, // check whether it is correctly set for (String ts : findAllTempTS(connector.getOrCreateAdminConnection())) { try { facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .build(OracleConstants.ORACLE_TEMP_TS_ATTR_NAME, ts)), null); } catch (Exception e) { // For any reason , when tablespace cannot be used for user continue; } assertEquals(ts, userReader.readUserRecord(uid.getUidValue()).getTemporaryTableSpace()); } } @Test public void testUpdateRoles() throws SQLException { String role = "testrole"; final OracleCaseSensitivitySetup cs = testConf.getCSSetup(); try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role " + cs.normalizeAndFormatToken(OracleUserAttribute.ROLE, role)); } catch (SQLException e) { } SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create role " + cs.normalizeAndFormatToken(OracleUserAttribute.ROLE, role)); Attribute roles = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME, Arrays.asList(role)); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(roles), null); List<String> rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); assertThat(rolesRead).contains(cs.normalizeToken(OracleUserAttribute.ROLE, role)); // If sending null or empty roles attribute, all roles must get revoked roles = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(roles), null); rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); // Assert.assertThat("All roles must get revoked when sending null roles attribute",rolesRead, // new IsEqual<List<String>>(Collections.<String>emptyList())); // assertThat(rolesRead).as("All roles must get revoked when sending null roles attribute").isEqualTo(Collections.<String>emptyList()); assertThat(rolesRead).as("All roles must get revoked when sending null roles attribute") .isEmpty(); roles = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME, Collections .emptyList()); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(roles), null); rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); // Assert.assertThat("All roles must get revoked when sending empty list roles attribute",rolesRead, // new IsEqual<List<String>>(Collections.<String>emptyList())); assertThat(rolesRead).as( "All roles must get revoked when sending empty list roles attribute").isEmpty(); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role " + cs.normalizeAndFormatToken(OracleUserAttribute.ROLE, role)); } @Test public void testUpdatePrivileges() throws SQLException { try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE"); } catch (SQLException e) { } SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create table mytable(id number)"); Attribute privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "CREATE SESSION", "SELECT ON MYTABLE"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); List<String> privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE"); assertThat(privilegesRead).contains("CREATE SESSION"); // If sending null or empty privileges attribute, all roles must get // revoked privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); // Assert.assertThat("All privileges must get revoked when sending null privileges attribute",privilegesRead, // new IsEqual<List<String>>(Collections.<String>emptyList())); assertThat(privilegesRead).as( "All privileges must get revoked when sending null privileges attribute").isEmpty(); privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, Collections .emptyList()); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); // Assert.assertThat("All privileges must get revoked when sending empty list privileges attribute",privilegesRead, // new IsEqual<List<String>>(Collections.<String>emptyList())); assertThat(privilegesRead).as( "All privileges must get revoked when sending empty list privileges attribute") .isEmpty(); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table mytable"); } @Test public void testUpdateEnable() throws SQLException { // new created user will be enabled UserRecord record = userReader.readUserRecord(uid.getUidValue()); assertEquals("OPEN", record.getStatus()); Attribute enable = AttributeBuilder.build(OperationalAttributes.ENABLE_NAME, Boolean.FALSE); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(enable), null); record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals("LOCKED", record.getStatus()); enable = AttributeBuilder.build(OperationalAttributes.ENABLE_NAME, Boolean.TRUE); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(enable), null); record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals("OPEN", record.getStatus()); } @Test public void testUpdateExpirePasword() throws SQLException { Attribute expirePassword = AttributeBuilder.build(OperationalAttributes.PASSWORD_EXPIRED_NAME, Boolean.TRUE); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(expirePassword), null); UserRecord record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals("EXPIRED", record.getStatus()); // now unexpire expirePassword = AttributeBuilder.build(OperationalAttributes.PASSWORD_EXPIRED_NAME, Boolean.FALSE); try { facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(expirePassword), null); Assert.fail("Must fail for unexpire and missing password"); } catch (RuntimeException e) { } // now unexpire with password facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(expirePassword, AttributeBuilder.buildPassword("newPassword".toCharArray())), null); // And now perform dummy operation to unexpire again facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(expirePassword), null); facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(expirePassword, AttributeBuilder.buildPassword("newPassword".toCharArray())), null); record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals("OPEN", record.getStatus()); // expire must fail for not local authentication // Update to external facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL)), null); try { // Try expire facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .buildPasswordExpired(true)), null); Assert.fail("Update with expiredPassword for not local authentication must fail"); } catch (RuntimeException e) { if (e.getCause() instanceof SQLException) { Assert.fail("Update with expiredPassword for not local authentication should not fail with SQLException"); } } // Update back to local facade.update(ObjectClass.ACCOUNT, uid, Collections .singleton(AttributeBuilder.build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_LOCAL)), null); try { // Try update to external with expire in one call facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPasswordExpired(true), AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL)), null); Assert.fail("Update with expiredPassword for not local authentication must fail"); } catch (RuntimeException e) { if (e.getCause() instanceof SQLException) { Assert.fail("Update with expiredPassword for not local authentication should not fail with SQLException"); } } // Now set ignore extra attributes OracleConfiguration newConf = OracleConfigurationTest.createSystemConfiguration(); newConf.validate(); newConf.setExtraAttributesPolicySetup(new ExtraAttributesPolicySetupBuilder(TestHelpers .createDummyMessages()).definePolicy(OracleUserAttribute.PASSWORD_EXPIRE, UpdateOp.class, ExtraAttributesPolicy.IGNORE).build()); OracleConnector testConnector = new OracleConnector(); testConnector.init(newConf); testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL), AttributeBuilder .buildPasswordExpired(true)), null); // update to external testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL)), null); // if we update only password_expired, and no other attributes, this // should fail try { testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPasswordExpired(true)), null); Assert.fail("Update must fail with external authentication and password expired"); } catch (ConnectorException e) { } // but if we update e.g also quota, it should pass testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPasswordExpired(true), AttributeBuilder.build( OracleConstants.ORACLE_DEF_TS_QUOTA_ATTR_NAME, "10k")), null); // if we update just the ignored attributes, we should fail newConf.setExtraAttributesPolicySetup(new ExtraAttributesPolicySetupBuilder(TestHelpers .createDummyMessages()).definePolicy(OracleUserAttribute.PASSWORD_EXPIRE, UpdateOp.class, ExtraAttributesPolicy.IGNORE).definePolicy( OracleUserAttribute.PASSWORD, UpdateOp.class, ExtraAttributesPolicy.IGNORE).build()); try { testConnector.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .buildPasswordExpired(true), AttributeBuilder.buildPassword("newPassword" .toCharArray())), null); Assert.fail("Update must fail with external authentication and password expired"); } catch (ConnectorException e) { } testConnector.dispose(); } @Test public void testAddAttributeValuesPrivileges() throws SQLException { try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE1"); } catch (SQLException e) { } try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE2"); } catch (SQLException e) { } SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create table MYTABLE1(id number)"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create table MYTABLE2(id number)"); Attribute privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "CREATE SESSION", "SELECT ON MYTABLE1"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); List<String> privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE1"); assertThat(privilegesRead).contains("CREATE SESSION"); // Assert.assertThat(privilegesRead, new // IsNot<Iterable<String>>(JUnitMatchers.hasItem("SELECT ON " + // testConf.getUser() + ".MYTABLE2"))); assertThat("SELECT ON " + testConf.getUser() + ".MYTABLE2").isNotIn(privilegesRead); privileges = AttributeBuilder .build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "SELECT ON MYTABLE2"); facade.addAttributeValues(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE1"); assertThat(privilegesRead).contains("CREATE SESSION"); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE2"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE1"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE2"); } @Test public void testAddAttributeValuesRoles() throws SQLException { try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role ROLE1"); } catch (SQLException e) { } try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role ROLE2"); } catch (SQLException e) { } SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create role ROLE1"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create role ROLE2"); Attribute rolesAttr = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME, "ROLE1"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(rolesAttr), null); List<String> rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); assertThat(rolesRead).contains("ROLE1"); // Assert.assertThat(rolesRead, new // IsNot<Iterable<String>>(JUnitMatchers.hasItem("ROLE2"))); assertThat("ROLE2").isNotIn(rolesRead); rolesAttr = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME, "ROLE2"); facade.addAttributeValues(ObjectClass.ACCOUNT, uid, Collections.singleton(rolesAttr), null); rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); assertThat(rolesRead).contains("ROLE1"); assertThat(rolesRead).contains("ROLE2"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role role1"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role role2"); } @Test public void testRemoveAttributeValuesPrivileges() throws SQLException { try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE1"); } catch (SQLException e) { } try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE2"); } catch (SQLException e) { } SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create table MYTABLE1(id number)"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create table MYTABLE2(id number)"); Attribute privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "CREATE SESSION", "SELECT ON MYTABLE1", "SELECT ON MYTABLE2"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); List<String> privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE1"); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE2"); assertThat(privilegesRead).contains("CREATE SESSION"); privileges = AttributeBuilder .build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "SELECT ON MYTABLE1"); facade.removeAttributeValues(ObjectClass.ACCOUNT, uid, Collections.singleton(privileges), null); privilegesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()) .readAllPrivileges(uid.getUidValue()); assertThat(privilegesRead).contains("SELECT ON " + testConf.getUserOwner() + ".MYTABLE2"); assertThat(privilegesRead).contains("CREATE SESSION"); // Assert.assertThat(privilegesRead, new // IsNot<Iterable<String>>(JUnitMatchers.hasItem("SELECT ON " + // testConf.getUserOwner() + ".MYTABLE1"))); assertThat("SELECT ON " + testConf.getUserOwner() + ".MYTABLE1").isNotIn(privilegesRead); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE1"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop table MYTABLE2"); } @Test public void testRemoveAttributeValuesRoles() throws SQLException { try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role ROLE1"); } catch (SQLException e) { } try { SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role ROLE2"); } catch (SQLException e) { } SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create role ROLE1"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "create role ROLE2"); Attribute rolesAttr = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME, "ROLE1", "ROLE2"); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(rolesAttr), null); List<String> rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); assertThat(rolesRead).contains("ROLE1"); assertThat(rolesRead).contains("ROLE2"); rolesAttr = AttributeBuilder.build(OracleConstants.ORACLE_ROLES_ATTR_NAME, "ROLE1"); facade.removeAttributeValues(ObjectClass.ACCOUNT, uid, Collections.singleton(rolesAttr), null); rolesRead = new OracleRolePrivReader(connector.getOrCreateAdminConnection()).readRoles(uid .getUidValue()); assertThat(rolesRead).contains("ROLE2"); // Assert.assertThat(rolesRead, new // IsNot<Iterable<String>>(JUnitMatchers.hasItem("ROLE1"))); assertThat("ROLE1").isNotIn(rolesRead); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role role1"); SQLUtil.executeUpdateStatement(connector.getOrCreateAdminConnection(), "drop role role2"); } @Test public void testUpdateExternal() throws SQLException { // Test external authentication facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_EXTERNAL)), null); UserRecord record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals(OracleAuthentication.EXTERNAL, OracleUserReader.resolveAuthentication(record)); facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet( AttributeBuilder.build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_LOCAL), AttributeBuilder .buildPassword("password".toCharArray())), null); record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals(OracleAuthentication.LOCAL, OracleUserReader.resolveAuthentication(record)); } @Test public void testUpdateGlobal() throws SQLException { try { facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_GLOBAL)), null); Assert.fail("Must require global name"); } catch (RuntimeException e) { } try { facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_GLOBAL_ATTR_NAME, ""), AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_GLOBAL)), null); Assert.fail("Global name cannot be blank"); } catch (RuntimeException e) { } try { facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .build(OracleConstants.ORACLE_GLOBAL_ATTR_NAME), AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_GLOBAL)), null); Assert.fail("Global name cannot be null"); } catch (RuntimeException e) { } try { facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_GLOBAL), AttributeBuilder.build( OracleConstants.ORACLE_GLOBAL_ATTR_NAME, "anyGlobal")), null); UserRecord record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals(OracleAuthentication.GLOBAL, OracleUserReader .resolveAuthentication(record)); assertEquals("anyGlobal", record.getExternalName()); // update to newGlobal and check it facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_GLOBAL_ATTR_NAME, "newGlobal")), null); record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals(OracleAuthentication.GLOBAL, OracleUserReader .resolveAuthentication(record)); assertEquals("newGlobal", record.getExternalName()); // Set back to local and check it facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder.build( OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_LOCAL), AttributeBuilder.buildPassword("password" .toCharArray())), null); record = userReader.readUserRecord(uid.getUidValue()); assertNotNull(record); assertEquals(OracleAuthentication.LOCAL, OracleUserReader.resolveAuthentication(record)); // Now try to set Global name, which should fail try { facade.update(ObjectClass.ACCOUNT, uid, CollectionUtil.newSet(AttributeBuilder .build(OracleConstants.ORACLE_GLOBAL_ATTR_NAME, "newGlobal")), null); Assert.fail("Update with global name must fail for local authentication"); } catch (ConnectorException e) { } } catch (ConnectorException e) { if (e.getCause() instanceof SQLException) { if ("67000".equals(((SQLException) e.getCause()).getSQLState()) && 439 == ((SQLException) e.getCause()).getErrorCode()) { } else { Assert.fail(e.getMessage()); } } else { Assert.fail(e.getMessage()); } } } /** Test that update will fail on any not known attribute */ @Test public void testValidUpdateAttributes() { Attribute authentication = AttributeBuilder.build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME, OracleConstants.ORACLE_AUTH_LOCAL); GuardedString password = new GuardedString("hello".toCharArray()); Attribute passwordAttribute = AttributeBuilder.buildPassword(password); Attribute privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME, "CREATE SESSION"); Attribute enabled = AttributeBuilder.build(OperationalAttributes.ENABLE_NAME, Boolean.TRUE); Attribute expirePassword = AttributeBuilder.build(OperationalAttributes.PASSWORD_EXPIRED_NAME, Boolean.TRUE); Set<Attribute> attrs = new HashSet<Attribute>(Arrays.asList(authentication, passwordAttribute, privileges, enabled, expirePassword)); facade.update(ObjectClass.ACCOUNT, uid, attrs, null); // Now add some dummy attribute Set<Attribute> badAttrs = new HashSet<Attribute>(attrs); badAttrs.add(AttributeBuilder.buildDisableDate(0)); try { facade.update(ObjectClass.ACCOUNT, uid, badAttrs, null); Assert.fail("Disabled date should not be supported"); } catch (IllegalArgumentException e) { } badAttrs = new HashSet<Attribute>(attrs); badAttrs.add(AttributeBuilder.buildPasswordExpirationDate(0)); try { facade.update(ObjectClass.ACCOUNT, uid, badAttrs, null); Assert.fail("Expired password date should not be supported"); } catch (IllegalArgumentException e) { } badAttrs = new HashSet<Attribute>(attrs); badAttrs.add(AttributeBuilder.build("dummy", "dummyValue")); try { facade.update(ObjectClass.ACCOUNT, uid, badAttrs, null); Assert.fail("Dummy attribute should not be supported"); } catch (IllegalArgumentException e) { } // Call with no attributes, this must fail try { facade.update(ObjectClass.ACCOUNT, uid, Collections.<Attribute> emptySet(), null); Assert.fail("Update with no attributes should fail"); } catch (IllegalArgumentException e) { } try { facade.addAttributeValues(ObjectClass.ACCOUNT, uid, Collections.<Attribute> emptySet(), null); Assert.fail("AddAttributeValues with no attributes should fail"); } catch (IllegalArgumentException e) { } try { facade.removeAttributeValues(ObjectClass.ACCOUNT, uid, Collections .<Attribute> emptySet(), null); Assert.fail("RemoveAttributeValues with no attributes should fail"); } catch (IllegalArgumentException e) { } // try other case of attributes authentication = AttributeBuilder.build(OracleConstants.ORACLE_AUTHENTICATION_ATTR_NAME .toUpperCase(), OracleConstants.ORACLE_AUTH_LOCAL); password = new GuardedString("hello".toCharArray()); passwordAttribute = AttributeBuilder.build(OperationalAttributes.PASSWORD_NAME.toUpperCase(), password); privileges = AttributeBuilder.build(OracleConstants.ORACLE_PRIVS_ATTR_NAME.toUpperCase(), "CREATE SESSION"); enabled = AttributeBuilder.build(OperationalAttributes.ENABLE_NAME.toUpperCase(), Boolean.TRUE); expirePassword = AttributeBuilder.build(OperationalAttributes.PASSWORD_EXPIRED_NAME.toUpperCase(), Boolean.TRUE); attrs = new HashSet<Attribute>(Arrays.asList(authentication, passwordAttribute, privileges, enabled, expirePassword)); facade.update(ObjectClass.ACCOUNT, uid, attrs, null); // We do not need to verify update effect, we test that invalid // attributes are rejected } /** * Test that update will fail for sql error, e.g killed connection * * @throws SQLException */ @Test public void testUpdateFail() throws SQLException { OracleConnector testConnector = createTestConnector(); testConnector.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .buildPassword("newpassword".toCharArray())), null); // Now kill connection OracleSpecifics.killConnection(connector.getOrCreateAdminConnection(), testConnector .getOrCreateAdminConnection()); // now update should fail try { testConnector.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .buildPassword("newpassword".toCharArray())), null); Assert.fail("Update must fail for killed connection"); } catch (RuntimeException e) { } testConnector.dispose(); } @Test public void testUpdateNotExistingUser() { // Normal password update password = new GuardedString("newPassword".toCharArray()); Attribute passwordAttribute = AttributeBuilder.buildPassword(password); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(passwordAttribute), null); // now delete facade.delete(ObjectClass.ACCOUNT, uid, null); // update again must throw UnknowUIDException try { facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(passwordAttribute), null); Assert.fail("Update of not existing user must throw UnknownUidException"); } catch (UnknownUidException e) { } // Here recreate test user, otherwise after method will fail createTestUser(); } /** * Test setting lockout parameter * * @throws SQLException */ @Test public void testUpdateLockOut() throws SQLException { assertEquals("OPEN", userReader.readUserRecord(uid.getUidValue()).getStatus()); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .buildLockOut(true)), null); assertEquals("LOCKED", userReader.readUserRecord(uid.getUidValue()).getStatus()); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .buildPassword("newPassword".toCharArray())), null); assertEquals("LOCKED", userReader.readUserRecord(uid.getUidValue()).getStatus()); facade.update(ObjectClass.ACCOUNT, uid, Collections.singleton(AttributeBuilder .buildLockOut(false)), null); assertEquals("OPEN", userReader.readUserRecord(uid.getUidValue()).getStatus()); } }