diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd
index 88598ba9e2c..8d60189ac1d 100644
--- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd
+++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd
@@ -11585,6 +11585,16 @@
+
+
+ Method used to store the values of this credential (encrypted, hashed, ...)
+ If storage method is not specified it defaults to encryption
+ (due to compatibility and convenience reasons).
+
+
+ 3.6
+
+
@@ -11655,6 +11665,18 @@
+
+
+
+ Method used to store historical values of the credential (encrypted, hashed, ...)
+ If storage type is not specified then it defaults to hashing.
+
+
+ 3.6
+
+
+
+
@@ -11839,6 +11861,13 @@
MidPoitn will only work with credential in the memory
while it is needed to complete current operation.
The credential will be discarded after the operation.
+
+ THIS IS ONLY PARTIALLY SUPPORTED
+
+ MidPoint should be able not to store the credentials when
+ this setting is used. But there may be side effects.
+ This is not entirelly tests and not supported.
+ Use at your own risk.
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/CredentialsProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/CredentialsProcessor.java
index 400419bee74..b44c51a093d 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/CredentialsProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/CredentialsProcessor.java
@@ -40,6 +40,7 @@
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
+import com.evolveum.midpoint.security.api.SecurityUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.SchemaFailableProcessor;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
@@ -433,12 +434,8 @@ private void transformFocusExectionDeltaCredential(LensCo
return;
}
CredentialPolicyType defaltCredPolicyType = credsType.getDefault();
- CredentialsStorageMethodType storageMethod = null;
- if (credPolicyType != null && credPolicyType.getStorageMethod() != null) {
- storageMethod = credPolicyType.getStorageMethod();
- } else if (defaltCredPolicyType != null && defaltCredPolicyType.getStorageMethod() != null) {
- storageMethod = defaltCredPolicyType.getStorageMethod();
- }
+ CredentialsStorageMethodType storageMethod =
+ SecurityUtil.getCredPolicyItem(defaltCredPolicyType, credPolicyType, pol -> pol.getStorageMethod());
if (storageMethod == null) {
return;
}
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/PasswordPolicyProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/PasswordPolicyProcessor.java
index 5ce5c208083..79d2137035a 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/PasswordPolicyProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/PasswordPolicyProcessor.java
@@ -59,6 +59,7 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
+import com.evolveum.midpoint.security.api.SecurityUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
@@ -70,6 +71,8 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.CharacterClassType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CheckExpressionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsPolicyType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsStorageMethodType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsStorageTypeType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
@@ -709,7 +712,6 @@ private String determinePasswordValue(ProtectedStringType passValue) {
return passwordStr;
}
-
public void processPasswordHistoryDeltas(LensFocusContext focusContext,
LensContext context, SecurityPolicyType securityPolicy, XMLGregorianCalendar now, Task task, OperationResult result)
throws SchemaException {
@@ -729,7 +731,7 @@ public void processPasswordHistoryDeltas(LensFocusContext<
List historyEntryValues = getSortedHistoryList(historyEntries, true);
int newHistoryEntries = 0;
if (maxPasswordsToSave > 0) {
- newHistoryEntries = createAddHistoryDelta(context, password, now);
+ newHistoryEntries = createAddHistoryDelta(context, password, securityPolicy, now);
}
createDeleteHistoryDeltasIfNeeded(historyEntryValues, maxPasswordsToSave, newHistoryEntries, context, task, result);
}
@@ -794,9 +796,24 @@ private int getMaxPasswordsToSave(LensFocusContext focu
private int createAddHistoryDelta(LensContext context,
- PrismContainer password, XMLGregorianCalendar now) throws SchemaException {
+ PrismContainer password, SecurityPolicyType securityPolicy, XMLGregorianCalendar now) throws SchemaException {
PrismContainerValue passwordValue = password.getValue();
- PasswordType passwordRealValue = passwordValue.asContainerable();
+ PasswordType passwordType = passwordValue.asContainerable();
+ if (passwordType == null || passwordType.getValue() == null) {
+ return 0;
+ }
+ ProtectedStringType passwordPsForStorage = passwordType.getValue().clone();
+
+ CredentialsStorageTypeType storageType = CredentialsStorageTypeType.HASHING;
+ CredentialsPolicyType creds = securityPolicy.getCredentials();
+ if (creds != null) {
+ CredentialsStorageMethodType storageMethod =
+ SecurityUtil.getCredPolicyItem(creds.getDefault(), creds.getPassword(), pol -> pol.getStorageMethod());
+ if (storageMethod != null && storageMethod.getStorageType() != null) {
+ storageType = storageMethod.getStorageType();
+ }
+ }
+ prepareProtectedStringForStorage(passwordPsForStorage, storageType);
PrismContainerDefinition historyEntryDefinition = password.getDefinition().findContainerDefinition(PasswordType.F_HISTORY_ENTRY);
PrismContainer historyEntry = historyEntryDefinition.instantiate();
@@ -804,8 +821,8 @@ private int createAddHistoryDelta(LensContext context,
PrismContainerValue hisotryEntryValue = historyEntry.createNewValue();
PasswordHistoryEntryType entryType = hisotryEntryValue.asContainerable();
- entryType.setValue(passwordRealValue.getValue());
- entryType.setMetadata(passwordRealValue.getMetadata());
+ entryType.setValue(passwordPsForStorage);
+ entryType.setMetadata(passwordType.getMetadata());
entryType.setChangeTimestamp(now);
ContainerDelta addHisotryDelta = ContainerDelta
@@ -815,6 +832,37 @@ private int createAddHistoryDelta(LensContext context,
return 1;
}
+
+ private void prepareProtectedStringForStorage(ProtectedStringType ps, CredentialsStorageTypeType storageType) throws SchemaException {
+ try {
+ switch (storageType) {
+ case ENCRYPTION:
+ if (ps.isEncrypted()) {
+ break;
+ }
+ if (ps.isHashed()) {
+ throw new SchemaException("Cannot store hashed value in an encrypted form");
+ }
+ protector.encrypt(ps);
+ break;
+
+ case HASHING:
+ if (ps.isHashed()) {
+ break;
+ }
+ protector.hash(ps);
+ break;
+
+ case NONE:
+ throw new SchemaException("Cannot store value on NONE storage form");
+
+ default:
+ throw new SchemaException("Unknown storage type: "+storageType);
+ }
+ } catch (EncryptionException e) {
+ throw new SystemException(e.getMessage(), e);
+ }
+ }
private void createDeleteHistoryDeltasIfNeeded(
List historyEntryValues, int maxPasswordsToSave, int newHistoryEntries, LensContext context, Task task,
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 da60d69e58c..1e5994d4b67 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
@@ -721,7 +721,10 @@ public void test202ReconcileUserJack() throws Exception {
// GIVEN
Task task = taskManager.createTaskInstance(AbstractPasswordTest.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
- assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL);
+
+ PrismObject userBefore = getUser(USER_JACK_OID);
+ display("User before", userBefore);
+ assertLinks(userBefore, 4);
// WHEN
reconcileUser(USER_JACK_OID, task, result);
@@ -730,27 +733,27 @@ public void test202ReconcileUserJack() throws Exception {
result.computeStatus();
TestUtil.assertSuccess(result);
- PrismObject userJack = getUser(USER_JACK_OID);
- display("User after change execution", userJack);
- assertLinks(userJack, 4);
- accountYellowOid = getLinkRefOid(userJack, RESOURCE_DUMMY_YELLOW_OID);
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertLinks(userAfter, 4);
+ accountYellowOid = getLinkRefOid(userAfter, RESOURCE_DUMMY_YELLOW_OID);
// Check account in dummy resource (yellow): password is too short for this, original password should remain there
assertDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true);
- assertDummyPassword(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_1_CLEAR);
+ assertDummyPasswordConditional(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_1_CLEAR);
// Check account in dummy resource (red)
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true);
assertDummyPassword(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_A_CLEAR);
// User and default dummy account should have unchanged passwords
- assertUserPassword(userJack, USER_PASSWORD_A_CLEAR);
+ assertUserPassword(userAfter, USER_PASSWORD_A_CLEAR);
assertDummyPassword(ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_A_CLEAR);
// this one is not changed
assertDummyPassword(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_EMPLOYEE_NUMBER_NEW_GOOD);
- assertPasswordHistoryEntries(userJack);
+ assertPasswordHistoryEntries(userAfter);
}
/**
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java
index 79af8155586..e1d7993f8b8 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java
@@ -49,6 +49,6 @@ protected String getSecurityPolicyOid() {
@Override
protected CredentialsStorageTypeType getPasswordStorageType() {
return CredentialsStorageTypeType.HASHING;
- }
+ }
}
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordNone.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordNone.java
index 9263924396a..0173cf133ba 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordNone.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordNone.java
@@ -29,6 +29,12 @@
/**
* Password test with NONE password storage (default storage for other types)
*
+ * This test is only partially working.
+ * IT IS NOT PART OF THE TEST SUITE. It is NOT executed automatically.
+ *
+ * E.g. new password will be generated on every recompute because the
+ * weak inbound mapping is activated.
+ *
* @author semancik
*
*/
@@ -50,5 +56,4 @@ protected String getSecurityPolicyOid() {
protected CredentialsStorageTypeType getPasswordStorageType() {
return CredentialsStorageTypeType.NONE;
}
-
}
diff --git a/model/model-intest/src/test/resources/logback-test.xml b/model/model-intest/src/test/resources/logback-test.xml
index 6e74a791037..13228f205c1 100644
--- a/model/model-intest/src/test/resources/logback-test.xml
+++ b/model/model-intest/src/test/resources/logback-test.xml
@@ -46,7 +46,7 @@
if any of the following is set to "TRACE" then it was changed by mistake and should be changed back -->
-
+
diff --git a/model/model-intest/testng-integration.xml b/model/model-intest/testng-integration.xml
index f733ac50372..f4545204b2c 100644
--- a/model/model-intest/testng-integration.xml
+++ b/model/model-intest/testng-integration.xml
@@ -95,7 +95,8 @@
-
+
+