Skip to content

Commit

Permalink
Temporary fix for MID-3111: Remove user password button over GUI is n…
Browse files Browse the repository at this point in the history
…ot provisioned to target system when strong outbound mapping is set
  • Loading branch information
mederly committed Jun 15, 2016
1 parent 0085d8c commit 75472f3
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 42 deletions.
Expand Up @@ -179,7 +179,7 @@ public void access(char[] chars) {
}

/**
* Disposes of the {@link CSVFileConnector}'s resources.
* Disposes of the connector's resources.
*
* @see Connector#dispose()
*/
Expand Down Expand Up @@ -1808,23 +1808,25 @@ private Date getDate(Attribute attr) {


private void changePassword(final DummyAccount account, Attribute attr) throws ConnectException, FileNotFoundException, SchemaViolationException {
if (attr.getValue() == null || attr.getValue().isEmpty()) {
throw new IllegalArgumentException("Empty password was provided");
}
Object passwdObject = attr.getValue().get(0);
if (!(passwdObject instanceof GuardedString)) {
throw new IllegalArgumentException("Password was provided as "+passwdObject.getClass().getName()+" while expecting GuardedString");
}
final String[] passwdArray = { "" };
((GuardedString)passwdObject).access(new Accessor() {
@Override
public void access(char[] passwdChars) {
if (configuration.getMinPasswordLength() != null && passwdChars.length < configuration.getMinPasswordLength()) {
throw new InvalidAttributeValueException("Password too short");
}
passwdArray[0] = new String(passwdChars);
final String[] passwdArray = { null };
if (attr.getValue() != null && !attr.getValue().isEmpty()) {
Object passwdObject = attr.getValue().get(0);
if (!(passwdObject instanceof GuardedString)) {
throw new IllegalArgumentException(
"Password was provided as " + passwdObject.getClass().getName() + " while expecting GuardedString");
}
});
((GuardedString)passwdObject).access(new Accessor() {
@Override
public void access(char[] passwdChars) {
if (configuration.getMinPasswordLength() != null && passwdChars.length < configuration.getMinPasswordLength()) {
throw new InvalidAttributeValueException("Password too short");
}
passwdArray[0] = new String(passwdChars);
}
});
} else {
// empty password => null
}
account.setPassword(passwdArray[0]);
}

Expand Down
Expand Up @@ -16,7 +16,7 @@
package com.evolveum.midpoint.model.impl.lens.projector;

import java.util.Collection;
import java.util.List;
import java.util.Collections;

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
Expand Down Expand Up @@ -227,14 +227,27 @@ public StringPolicyType resolve() {
passwordMapping.setStringPolicyResolver(stringPolicyResolver);

mappingEvaluator.evaluateMapping(passwordMapping, context, task, result);

PrismProperty<ProtectedStringType> accountPasswordNew = (PrismProperty) passwordMapping.getOutput();
if (accountPasswordNew == null || accountPasswordNew.isEmpty()) {
LOGGER.trace("Credentials 'password' expression resulted in null, skipping credentials processing for {}", rat);
return;
}
PropertyDelta<ProtectedStringType> accountPasswordDeltaNew = new PropertyDelta<ProtectedStringType>(SchemaConstants.PATH_PASSWORD_VALUE, accountPasswordPropertyDefinition, prismContext);
accountPasswordDeltaNew.setValuesToReplace(accountPasswordNew.getClonedValues());

// TODO review all this code !! MID-3156
// Originally here was "do nothing if output is null or empty".
// But because of MID-3111 we have to be a bit more cautious
PrismProperty<ProtectedStringType> accountPasswordNew = (PrismProperty) passwordMapping.getOutput();
if (accountPasswordNew == null || accountPasswordNew.isEmpty()) {
if (passwordMapping.getOutputTriple() == null) {
LOGGER.trace("Credentials 'password' expression resulted in null output triple, skipping credentials processing for {}", rat);
return;
}
if (passwordMapping.getStrength() != MappingStrengthType.STRONG) {
LOGGER.trace("Credentials 'password' expression resulted in 'no value' via non-strong mapping, skipping credentials processing for {}", rat);
return;
}
}
PropertyDelta<ProtectedStringType> accountPasswordDeltaNew = new PropertyDelta<>(SchemaConstants.PATH_PASSWORD_VALUE, accountPasswordPropertyDefinition, prismContext);
if (accountPasswordNew != null) {
accountPasswordDeltaNew.setValuesToReplace(accountPasswordNew.getClonedValues());
} else {
accountPasswordDeltaNew.setValuesToReplace(Collections.<PrismPropertyValue<ProtectedStringType>>emptyList());
}
LOGGER.trace("Adding new password delta for account {}", rat);
accCtx.swallowToSecondaryDelta(accountPasswordDeltaNew);

Expand Down
Expand Up @@ -16,10 +16,7 @@
package com.evolveum.midpoint.model.intest;

import static com.evolveum.midpoint.test.IntegrationTestTools.display;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.*;

import java.io.File;
import java.util.ArrayList;
Expand Down Expand Up @@ -750,6 +747,47 @@ public void test300TwoParentOrgRefs() throws Exception {
assertDummyPassword(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID);
}

/*
* Remove password. It should be removed from red resource as well. (MID-3111)
* Also unassign yellow resource (requires non-empty password), all orgs, and remove default password policy.
*/
@Test
public void test310RemovePassword() throws Exception {
final String TEST_NAME = "test310RemovePassword";
TestUtil.displayTestTile(this, TEST_NAME);

// GIVEN
Task task = taskManager.createTaskInstance(TestPassword.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL);

unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_YELLOW_OID, null, task, result);
unassignOrg(USER_JACK_OID, ORG_GOVERNOR_OFFICE_OID, null, task, result);
unassignOrg(USER_JACK_OID, ORG_GOVERNOR_OFFICE_OID, SchemaConstants.ORG_MANAGER, task, result);
modifyObjectReplaceReference(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(),
SystemConfigurationType.F_GLOBAL_PASSWORD_POLICY_REF, task, result);

// WHEN
modifyUserReplace(USER_JACK_OID, PASSWORD_VALUE_PATH, task, result);

// THEN
result.computeStatus();
TestUtil.assertSuccess(result);

PrismObject<UserType> userJack = getUser(USER_JACK_OID);
display("User after change execution", userJack);
assertUserJack(userJack, "Jack Sparrow");

assertNull("User password is not null", userJack.asObjectable().getCredentials().getPassword().getValue());
assertDummyPassword(ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID); // password mapping is weak here - so no change is expected

assertNoDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME);

assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true);
assertDummyPassword(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, null); // password mapping is strong here
}


private void assertDummyPassword(String userId, String expectedClearPassword) throws SchemaViolationException {
assertDummyPassword(null, userId, expectedClearPassword);
}
Expand Down
Expand Up @@ -19,13 +19,7 @@

import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
Expand Down Expand Up @@ -2728,12 +2722,12 @@ private void convertFromPassword(Set<Attribute> attributes, PropertyDelta<Protec
}
PrismProperty<ProtectedStringType> newPassword = passwordDelta.getPropertyNewMatchingPath();
if (newPassword == null || newPassword.isEmpty()) {
LOGGER.trace("Skipping processing password delta. Password delta does not contain new value.");
return;
LOGGER.debug("Setting null password.");
attributes.add(AttributeBuilder.build(OperationalAttributes.PASSWORD_NAME, Collections.EMPTY_LIST));
} else {
GuardedString guardedPassword = IcfUtil.toGuardedString(newPassword.getValue().getValue(), "new password", protector);
attributes.add(AttributeBuilder.build(OperationalAttributes.PASSWORD_NAME, guardedPassword));
}
GuardedString guardedPassword = IcfUtil.toGuardedString(newPassword.getValue().getValue(), "new password", protector);
attributes.add(AttributeBuilder.build(OperationalAttributes.PASSWORD_NAME, guardedPassword));

}

private void addConvertedValues(Collection<PrismPropertyValue<QName>> pvals,
Expand Down

0 comments on commit 75472f3

Please sign in to comment.