From da88e12ff573029f01ad81849e5939356fd360ca Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 20 Mar 2017 13:18:45 +0100 Subject: [PATCH] Fixing support for deprecated globalPassowrdPolicyRef (+test) --- .../midpoint/prism/delta/ReferenceDelta.java | 10 +- .../model/impl/security/SecurityHelper.java | 25 +- .../intest/password/AbstractPasswordTest.java | 16 +- .../password/TestPasswordDeprecated.java | 368 ++++++++++++++++++ .../src/test/resources/logback-test.xml | 1 + .../password/password-policy-deprecated.xml | 91 +++++ model/model-intest/testng-integration.xml | 1 + 7 files changed, 493 insertions(+), 19 deletions(-) create mode 100644 model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDeprecated.java create mode 100644 model/model-intest/src/test/resources/password/password-policy-deprecated.xml diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ReferenceDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ReferenceDelta.java index 23769e7a6ec..6cfd69dc95b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ReferenceDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ReferenceDelta.java @@ -112,12 +112,12 @@ public static ReferenceDelta createModificationReplace(ItemPath path, PrismObjec public static ReferenceDelta createModificationReplace(QName refName, Class type, PrismContext ctx , String oid) { PrismObjectDefinition objectDefinition = ctx.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(type); - return createModificationReplace(refName, objectDefinition, new PrismReferenceValue(oid)); + return createModificationReplace(refName, objectDefinition, oid==null?null:new PrismReferenceValue(oid)); } public static ReferenceDelta createModificationReplace(ItemPath path, Class type, PrismContext ctx, String oid) { PrismObjectDefinition objectDefinition = ctx.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(type); - return createModificationReplace(path, objectDefinition, new PrismReferenceValue(oid)); + return createModificationReplace(path, objectDefinition, oid==null?null:new PrismReferenceValue(oid)); } public static ReferenceDelta createModificationReplace(ItemPath path, PrismObjectDefinition objectDefinition, @@ -144,7 +144,11 @@ public static ReferenceDelta createModificationReplace(QName refName, PrismObjec PrismReferenceValue refValue) { PrismReferenceDefinition referenceDefinition = objectDefinition.findItemDefinition(refName, PrismReferenceDefinition.class); ReferenceDelta referenceDelta = new ReferenceDelta(refName, referenceDefinition, objectDefinition.getPrismContext()); // hoping the prismContext is there - referenceDelta.setValueToReplace(refValue); + if (refValue == null) { + referenceDelta.setValueToReplace(); + } else { + referenceDelta.setValueToReplace(refValue); + } return referenceDelta; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java index 587e31a5809..463e6c02f0e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java @@ -187,6 +187,7 @@ public SecurityPolicyType locateSecurityPolicy(PrismObject if (orgSecurityPolicy != null) { SecurityPolicyType orgSecurityPolicyType = orgSecurityPolicy.asObjectable(); postProcessSecurityPolicy(orgSecurityPolicyType, task, result); + traceSecurityPolicy(orgSecurityPolicyType, user); return orgSecurityPolicyType; } @@ -197,9 +198,11 @@ public SecurityPolicyType locateSecurityPolicy(PrismObject SecurityPolicyType globalSecurityPolicyType = objectResolver.resolve(globalSecurityPolicyRef, SecurityPolicyType.class, null, "global security policy reference in system configuration", task, result); LOGGER.trace("Using global security policy: {}", globalSecurityPolicyType); postProcessSecurityPolicy(globalSecurityPolicyType, task, result); + traceSecurityPolicy(globalSecurityPolicyType, user); return globalSecurityPolicyType; } catch (ObjectNotFoundException | SchemaException e) { LOGGER.error(e.getMessage(), e); + traceSecurityPolicy(null, user); return null; } } @@ -210,7 +213,9 @@ public SecurityPolicyType locateSecurityPolicy(PrismObject PrismObject orgPasswordPolicy = objectResolver.searchOrgTreeWidthFirstReference(user, o -> o.asObjectable().getPasswordPolicyRef(), "security policy", task, result); LOGGER.trace("Found organization password policy: {}", orgPasswordPolicy); if (orgPasswordPolicy != null) { - return postProcessPasswordPolicy(orgPasswordPolicy.asObjectable()); + SecurityPolicyType policy = postProcessPasswordPolicy(orgPasswordPolicy.asObjectable()); + traceSecurityPolicy(policy, user); + return policy; } if (systemConfiguration != null) { @@ -219,9 +224,12 @@ public SecurityPolicyType locateSecurityPolicy(PrismObject try { ValuePolicyType globalPasswordPolicyType = objectResolver.resolve(globalPasswordPolicyRef, ValuePolicyType.class, null, "global security policy reference in system configuration", task, result); LOGGER.trace("Using global password policy: {}", globalPasswordPolicyType); - return postProcessPasswordPolicy(globalPasswordPolicyType); + SecurityPolicyType policy = postProcessPasswordPolicy(globalPasswordPolicyType); + traceSecurityPolicy(policy, user); + return policy; } catch (ObjectNotFoundException | SchemaException e) { LOGGER.error(e.getMessage(), e); + traceSecurityPolicy(null, user); return null; } } @@ -231,6 +239,17 @@ public SecurityPolicyType locateSecurityPolicy(PrismObject } + private void traceSecurityPolicy(SecurityPolicyType securityPolicyType, PrismObject user) { + if (LOGGER.isTraceEnabled()) { + if (securityPolicyType == null) { + LOGGER.trace("Located security policy for {}: null", user); + } else { + LOGGER.trace("Located security policy for {}:\n{}", user, securityPolicyType.asPrismObject().debugDump(1)); + } + } + + } + private void postProcessSecurityPolicy(SecurityPolicyType securityPolicyType, Task task, OperationResult result) { CredentialsPolicyType creds = securityPolicyType.getCredentials(); if (creds != null) { @@ -293,7 +312,7 @@ private SecurityPolicyType postProcessPasswordPolicy(ValuePolicyType passwordPol creds.setPassword(passwd); securityPolicyType.setCredentials(creds); setDeprecatedPasswordPolicyProperties(passwordPolicyType, passwd); - return null; + return securityPolicyType; } private void setDeprecatedPasswordPolicyProperties(ValuePolicyType passwordPolicyType, diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java index aaf317a222d..d14147415a2 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java @@ -76,7 +76,7 @@ public abstract class AbstractPasswordTest extends AbstractInitializedModelInteg protected static final String USER_PASSWORD_VALID_3 = "abcd323"; protected static final String USER_PASSWORD_VALID_4 = "abcd423"; - protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "password"); + public static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "password"); protected static final File RESOURCE_DUMMY_UGLY_FILE = new File(TEST_DIR, "resource-dummy-ugly.xml"); protected static final String RESOURCE_DUMMY_UGLY_OID = "10000000-0000-0000-0000-000000344104"; @@ -94,11 +94,6 @@ public abstract class AbstractPasswordTest extends AbstractInitializedModelInteg protected static final String USER_JACK_EMPLOYEE_NUMBER_NEW_BAD = "No1"; protected static final String USER_JACK_EMPLOYEE_NUMBER_NEW_GOOD = "pir321"; - protected DummyResource dummyResourceUgly; - protected DummyResourceContoller dummyResourceCtlUgly; - protected ResourceType resourceDummyUglyType; - protected PrismObject resourceDummyUgly; - protected String accountJackOid; protected String accountJackRedOid; protected String accountJackUglyOid; @@ -116,12 +111,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti setGlobalSecurityPolicy(getSecurityPolicyOid(), initResult); - dummyResourceCtlUgly = DummyResourceContoller.create(RESOURCE_DUMMY_UGLY_NAME, resourceDummyUgly); - dummyResourceCtlUgly.extendSchemaPirate(); - dummyResourceUgly = dummyResourceCtlUgly.getDummyResource(); - resourceDummyUgly = importAndGetObjectFromFile(ResourceType.class, RESOURCE_DUMMY_UGLY_FILE, RESOURCE_DUMMY_UGLY_OID, initTask, initResult); - resourceDummyUglyType = resourceDummyUgly.asObjectable(); - dummyResourceCtlUgly.setResource(resourceDummyUgly); + initDummyResourcePirate(RESOURCE_DUMMY_UGLY_NAME, RESOURCE_DUMMY_UGLY_FILE, RESOURCE_DUMMY_UGLY_OID, initTask, initResult); login(USER_ADMINISTRATOR_USERNAME); } @@ -148,7 +138,7 @@ public void test010AddPasswordPolicy() throws Exception { assertEquals("Wrong OID after add", PASSWORD_POLICY_GLOBAL_OID, passwordPolicy.getOid()); // Check object - PrismObject accountShadow = repositoryService.getObject(ValuePolicyType.class, PASSWORD_POLICY_GLOBAL_OID, null, result); + PrismObject valuePolicy = repositoryService.getObject(ValuePolicyType.class, PASSWORD_POLICY_GLOBAL_OID, null, result); // TODO: more asserts } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDeprecated.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDeprecated.java new file mode 100644 index 00000000000..872018c83af --- /dev/null +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDeprecated.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2010-2017 Evolveum + * + * Licensed 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 com.evolveum.midpoint.model.intest.password; + +import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import static org.testng.AssertJUnit.*; + +import java.io.File; +import java.util.Collection; + +import javax.xml.datatype.XMLGregorianCalendar; + +import com.evolveum.icf.dummy.resource.DummyResource; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; +import com.evolveum.midpoint.test.DummyResourceContoller; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import com.evolveum.icf.dummy.resource.ConflictException; +import com.evolveum.icf.dummy.resource.SchemaViolationException; +import com.evolveum.midpoint.model.intest.AbstractInitializedModelIntegrationTest; +import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalsConfig; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.PolicyViolationException; + +/** + * Sketchy tests for deprecated password policy settings. + * Modified subset of AbstractPasswordTest. Just makes sure that the + * password policy configured in a deprecated way is applied and that it + * roughly works. It is not meant to be comprehensive. + * + * @author semancik + */ +@ContextConfiguration(locations = {"classpath:ctx-model-intest-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestPasswordDeprecated extends AbstractInitializedModelIntegrationTest { + + protected static final String USER_PASSWORD_0_CLEAR = "d3adM3nT3llN0Tal3s"; + protected static final String USER_PASSWORD_JACK_CLEAR = "12jAcK34"; // contains username + protected static final String USER_PASSWORD_SPARROW_CLEAR = "saRRow123"; // contains familyName + protected static final String USER_PASSWORD_VALID_1 = "abcd123"; + protected static final String USER_PASSWORD_VALID_2 = "abcd223"; + protected static final String USER_PASSWORD_VALID_3 = "abcd323"; + protected static final String USER_PASSWORD_VALID_4 = "abcd423"; + + protected static final File TEST_DIR = AbstractPasswordTest.TEST_DIR; + + protected static final File PASSWORD_POLICY_DEPRECATED_FILE = new File(TEST_DIR, "password-policy-deprecated.xml"); + protected static final String PASSWORD_POLICY_DEPRECATED_OID = "44bb6516-0d61-11e7-af71-73b639b25b04"; + + protected String accountJackOid; + protected XMLGregorianCalendar lastPasswordChangeStart; + protected XMLGregorianCalendar lastPasswordChangeEnd; + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + importObjectFromFile(PASSWORD_POLICY_DEPRECATED_FILE); + + setGlobalSecurityPolicy(null, initResult); + + login(USER_ADMINISTRATOR_USERNAME); + } + + @Test + public void test051ModifyUserJackPassword() throws Exception { + final String TEST_NAME = "test051ModifyUserJackPassword"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractPasswordTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + XMLGregorianCalendar startCal = clock.currentTimeXMLGregorianCalendar(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserChangePassword(USER_JACK_OID, USER_PASSWORD_0_CLEAR, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess("executeChanges result", result); + + XMLGregorianCalendar endCal = clock.currentTimeXMLGregorianCalendar(); + + PrismObject userJack = getUser(USER_JACK_OID); + display("User after change execution", userJack); + assertUserJack(userJack, "Jack Sparrow"); + + assertUserPassword(userJack, USER_PASSWORD_0_CLEAR); + assertPasswordMetadata(userJack, false, startCal, endCal); + // Password policy is not active yet. No history should be kept. + assertPasswordHistoryEntries(userJack); + } + + @Test + public void test100ModifyUserJackAssignAccount() throws Exception { + final String TEST_NAME = "test100ModifyUserJackAssignAccount"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(AbstractPasswordTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + // WHEN + assignAccount(USER_JACK_OID, RESOURCE_DUMMY_OID, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject userJack = getUser(USER_JACK_OID); + display("User after change execution", userJack); + assertUserJack(userJack); + accountJackOid = getSingleLinkOid(userJack); + + // Check shadow + PrismObject accountShadow = repositoryService.getObject(ShadowType.class, accountJackOid, null, result); + assertDummyAccountShadowRepo(accountShadow, accountJackOid, "jack"); + + // Check account + PrismObject accountModel = modelService.getObject(ShadowType.class, accountJackOid, null, task, result); + assertDummyAccountShadowModel(accountModel, accountJackOid, "jack", "Jack Sparrow"); + + // Check account in dummy resource + assertDefaultDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true); + assertDummyPassword(null, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_0_CLEAR); + } + + @Test + public void test200ApplyPasswordPolicy() throws Exception { + final String TEST_NAME = "test200ApplyPasswordPolicy"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + PrismReferenceValue passPolicyRef = new PrismReferenceValue(PASSWORD_POLICY_DEPRECATED_OID, ValuePolicyType.COMPLEX_TYPE); + + // WHEN + modifyObjectReplaceReference(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), + new ItemPath(SystemConfigurationType.F_GLOBAL_PASSWORD_POLICY_REF), + task, result, passPolicyRef); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + } + + + /** + * Change to password that complies with password policy. + */ + @Test + public void test210ModifyUserJackPasswordGood() throws Exception { + doTestModifyUserJackPasswordSuccessWithHistory("test210ModifyUserJackPasswordGood", + USER_PASSWORD_VALID_1, USER_PASSWORD_0_CLEAR); + } + + /** + * Reconcile user. Nothing should be changed. + * MID-3567 + */ + @Test + public void test212ReconcileUserJack() throws Exception { + final String TEST_NAME = "test212ReconcileUserJack"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + reconcileUser(USER_JACK_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertJackPasswordsWithHistory(USER_PASSWORD_VALID_1, USER_PASSWORD_0_CLEAR); + } + + /** + * Recompute user. Nothing should be changed. + * MID-3567 + */ + @Test + public void test214RecomputeUserJack() throws Exception { + final String TEST_NAME = "test214RecomputeUserJack"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + recomputeUser(USER_JACK_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertJackPasswordsWithHistory(USER_PASSWORD_VALID_1, USER_PASSWORD_0_CLEAR); + } + + /** + * Change to password that violates the password policy (but is still OK for yellow resource). + */ + @Test + public void test220ModifyUserJackPasswordBadA() throws Exception { + doTestModifyUserJackPasswordFailureWithHistory("test220ModifyUserJackPasswordBadA", + USER_PASSWORD_0_CLEAR, USER_PASSWORD_VALID_1, USER_PASSWORD_0_CLEAR); + } + + /** + * Change to password that violates the password policy (contains username) + * MID-1657 + */ + @Test + public void test224ModifyUserJackPasswordBadJack() throws Exception { + doTestModifyUserJackPasswordFailureWithHistory("test224ModifyUserJackPasswordBadJack", + USER_PASSWORD_JACK_CLEAR, USER_PASSWORD_VALID_1, USER_PASSWORD_0_CLEAR); + } + + /** + * Change to password that complies with password policy. Again. See that + * the change is applied correctly and that it is included in the history. + */ + @Test + public void test230ModifyUserJackPasswordGoodAgain() throws Exception { + doTestModifyUserJackPasswordSuccessWithHistory("test230ModifyUserJackPasswordGoodAgain", + USER_PASSWORD_VALID_2, USER_PASSWORD_0_CLEAR, USER_PASSWORD_VALID_1); + } + + /** + * Change to password that complies with password policy. Again. + * This time there are enough passwords in the history. So the history should + * be truncated. + */ + @Test + public void test240ModifyUserJackPasswordGoodAgainOverHistory() throws Exception { + doTestModifyUserJackPasswordSuccessWithHistory("test240ModifyUserJackPasswordGoodAgainOverHistory", + USER_PASSWORD_VALID_3, USER_PASSWORD_VALID_1, USER_PASSWORD_VALID_2); + } + + /** + * Change to password that complies with password policy. Again. + * This time there are enough passwords in the history. So the history should + * be truncated. + */ + @Test + public void test241ModifyUserJackPasswordGoodAgainOverHistoryAgain() throws Exception { + doTestModifyUserJackPasswordSuccessWithHistory("test241ModifyUserJackPasswordGoodAgainOverHistoryAgain", + USER_PASSWORD_VALID_4, USER_PASSWORD_VALID_2, USER_PASSWORD_VALID_3); + } + + /** + * Reuse old password. Now the password should be out of the history, so + * the system should allow its reuse. + */ + @Test + public void test248ModifyUserJackPasswordGoodReuse() throws Exception { + doTestModifyUserJackPasswordSuccessWithHistory("test248ModifyUserJackPasswordGoodReuse", + USER_PASSWORD_VALID_1, USER_PASSWORD_VALID_3, USER_PASSWORD_VALID_4); + } + + private void doTestModifyUserJackPasswordSuccessWithHistory(final String TEST_NAME, + String newPassword, String... expectedPasswordHistory) throws Exception { + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + lastPasswordChangeStart = clock.currentTimeXMLGregorianCalendar(); + + // WHEN + modifyUserChangePassword(USER_JACK_OID, newPassword, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + lastPasswordChangeEnd = clock.currentTimeXMLGregorianCalendar(); + + assertJackPasswordsWithHistory(newPassword, expectedPasswordHistory); + } + + private void doTestModifyUserJackPasswordFailureWithHistory(final String TEST_NAME, + String newPassword, String oldPassword, String... expectedPasswordHistory) throws Exception { + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + try { + // WHEN + modifyUserChangePassword(USER_JACK_OID, newPassword, task, result); + + AssertJUnit.fail("Unexpected success"); + + } catch (PolicyViolationException e) { + // This is expected + display("Exected exception", e); + } + + // THEN + result.computeStatus(); + TestUtil.assertFailure(result); + + assertJackPasswordsWithHistory(oldPassword, expectedPasswordHistory); + } + + private void assertJackPasswordsWithHistory(String expectedCurrentPassword, String... expectedPasswordHistory) throws Exception { + PrismObject userJack = getUser(USER_JACK_OID); + display("User after change execution", userJack); + assertLinks(userJack, 1); + + assertUserPassword(userJack, expectedCurrentPassword); + assertPasswordMetadata(userJack, false, lastPasswordChangeStart, lastPasswordChangeEnd); + + assertDummyPassword(null, ACCOUNT_JACK_DUMMY_USERNAME, expectedCurrentPassword); + + assertPasswordHistoryEntries(userJack, expectedPasswordHistory); + } + +} diff --git a/model/model-intest/src/test/resources/logback-test.xml b/model/model-intest/src/test/resources/logback-test.xml index 13228f205c1..d7e0a8ff866 100644 --- a/model/model-intest/src/test/resources/logback-test.xml +++ b/model/model-intest/src/test/resources/logback-test.xml @@ -89,6 +89,7 @@ + diff --git a/model/model-intest/src/test/resources/password/password-policy-deprecated.xml b/model/model-intest/src/test/resources/password/password-policy-deprecated.xml new file mode 100644 index 00000000000..2609782e1e8 --- /dev/null +++ b/model/model-intest/src/test/resources/password/password-policy-deprecated.xml @@ -0,0 +1,91 @@ + + + + + Deprecated Password Policy + + 999 + 9 + 0 + 0 + 3 + + + Testing string policy + + 5 + 12 + 3 + true + + + + + must not contain username + + + + + + must not contain family name and given name and additional names + + + Alphas + 1 + 5 + false + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + + + Numbers + 1 + 5 + false + + 1234567890 + + + + + \ No newline at end of file diff --git a/model/model-intest/testng-integration.xml b/model/model-intest/testng-integration.xml index c1115378704..6ea01e6f0ef 100644 --- a/model/model-intest/testng-integration.xml +++ b/model/model-intest/testng-integration.xml @@ -98,6 +98,7 @@ +