Skip to content

Commit

Permalink
Password expiration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Mar 23, 2016
1 parent 51867e2 commit 404a0a7
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 23 deletions.
Expand Up @@ -139,6 +139,7 @@ public Authentication authenticateUserPassword(MidPointPrincipal principal, Conn
return token;

} else {
logFailure(principal, "password mismatch");

recordAuthenticationFailure(principal, connEnv, passwordType, passwordCredentialsPolicy);

Expand Down
Expand Up @@ -108,6 +108,7 @@ public class AbstractInternalModelIntegrationTest extends AbstractModelIntegrati

protected static final File USER_GUYBRUSH_FILE = new File(COMMON_DIR, "user-guybrush.xml");
protected static final String USER_GUYBRUSH_OID = "c0c010c0-d34d-b33f-f00d-111111111116";
protected static final String USER_GUYBRUSH_USERNAME = "guybrush";

static final File USER_ELAINE_FILE = new File(COMMON_DIR, "user-elaine.xml");
protected static final String USER_ELAINE_OID = "c0c010c0-d34d-b33f-f00d-11111111111e";
Expand Down
Expand Up @@ -39,6 +39,7 @@
import com.evolveum.midpoint.common.Clock;
import com.evolveum.midpoint.model.api.AuthenticationEvaluator;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.Authorization;
import com.evolveum.midpoint.security.api.ConnectionEnvironment;
Expand All @@ -57,6 +58,7 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.SecurityPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;

/**
* @author semancik
Expand All @@ -70,6 +72,8 @@ public class TestAuthenticationEvaluator extends AbstractInternalModelIntegratio
protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "security");

private static final Trace LOGGER = TraceManager.getTrace(TestAuthenticationEvaluator.class);

private static final String USER_GUYBRUSH_PASSWORD = "XmarksTHEspot";

@Autowired(required=true)
private AuthenticationEvaluator authenticationEvaluator;
Expand Down Expand Up @@ -417,7 +421,161 @@ public void test118PasswordLoginLockedoutLockExpires() throws Exception {
assertFailedLogins(userAfter, 0);
assertLastSuccessfulLogin(userAfter, startTs, endTs);
}

@Test
public void test200UserGuybrushSetPassword() throws Exception {
final String TEST_NAME = "test200UserGuybrushSetPassword";
TestUtil.displayTestTile(TEST_NAME);

// GIVEN
Task task = createTask(TestAuthenticationEvaluator.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

ProtectedStringType userPasswordPs = new ProtectedStringType();
userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD);

XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar();

// WHEN
TestUtil.displayWhen(TEST_NAME);
modifyUserReplace(USER_GUYBRUSH_OID, PASSWORD_VALUE_PATH,
task, result, userPasswordPs);

// THEN
TestUtil.displayThen(TEST_NAME);
XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar();

PrismObject<UserType> userAfter = getUser(USER_GUYBRUSH_OID);
display("user after", userAfter);

assertEncryptedPassword(userAfter, USER_GUYBRUSH_PASSWORD);
assertPasswordMetadata(userAfter, false, startTs, endTs, null, SchemaConstants.CHANNEL_GUI_USER_URI);

assertFailedLogins(userAfter, 0);
}

@Test
public void test201UserGuybrushPasswordLoginGoodPassword() throws Exception {
final String TEST_NAME = "test201UserGuybrushPasswordLoginGoodPassword";
TestUtil.displayTestTile(TEST_NAME);

// GIVEN
MidPointPrincipal principal = getAuthorizedPrincipal(USER_GUYBRUSH_USERNAME);
ConnectionEnvironment connEnv = createConnectionEnvironment();
XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar();

// WHEN
TestUtil.displayWhen(TEST_NAME);
Authentication authentication = authenticationEvaluator.authenticateUserPassword(principal, connEnv, USER_GUYBRUSH_PASSWORD);

// THEN
TestUtil.displayThen(TEST_NAME);
XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar();
assertGoodPasswordAuthentication(authentication, principal);

PrismObject<UserType> userAfter = getUser(USER_GUYBRUSH_OID);
display("user after", userAfter);
assertFailedLogins(userAfter, 0);
assertLastSuccessfulLogin(userAfter, startTs, endTs);
}

@Test
public void test202UserGuybrushPasswordLoginBadPassword() throws Exception {
final String TEST_NAME = "test202UserGuybrushPasswordLoginBadPassword";
TestUtil.displayTestTile(TEST_NAME);

// GIVEN
MidPointPrincipal principal = getAuthorizedPrincipal(USER_GUYBRUSH_USERNAME);
ConnectionEnvironment connEnv = createConnectionEnvironment();
XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar();

try {

// WHEN
TestUtil.displayWhen(TEST_NAME);

authenticationEvaluator.authenticateUserPassword(principal, connEnv, "thisIsNotMyPassword");

AssertJUnit.fail("Unexpected success");

} catch (BadCredentialsException e) {
// This is expected

// THEN
TestUtil.displayThen(TEST_NAME);
display("expected exception", e);
assertBadPasswordException(e, principal);
}
XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar();

PrismObject<UserType> userAfter = getUser(USER_GUYBRUSH_OID);
display("user after", userAfter);
assertFailedLogins(userAfter, 1);
assertLastFailedLogin(userAfter, startTs, endTs);
}

@Test
public void test209UserGuybrushPasswordLoginGoodPasswordBeforeExpiration() throws Exception {
final String TEST_NAME = "test209UserGuybrushPasswordLoginGoodPasswordBeforeExpiration";
TestUtil.displayTestTile(TEST_NAME);

// GIVEN
clock.overrideDuration("P29D");

MidPointPrincipal principal = getAuthorizedPrincipal(USER_GUYBRUSH_USERNAME);
ConnectionEnvironment connEnv = createConnectionEnvironment();
XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar();

// WHEN
TestUtil.displayWhen(TEST_NAME);
Authentication authentication = authenticationEvaluator.authenticateUserPassword(principal, connEnv, USER_GUYBRUSH_PASSWORD);

// THEN
TestUtil.displayThen(TEST_NAME);
XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar();
assertGoodPasswordAuthentication(authentication, principal);

PrismObject<UserType> userAfter = getUser(USER_GUYBRUSH_OID);
display("user after", userAfter);
assertFailedLogins(userAfter, 0);
assertLastSuccessfulLogin(userAfter, startTs, endTs);
}

@Test
public void test210UserGuybrushPasswordLoginGoodPasswordExpired() throws Exception {
final String TEST_NAME = "test210UserGuybrushPasswordLoginGoodPasswordExpired";
TestUtil.displayTestTile(TEST_NAME);

// GIVEN
clock.overrideDuration("P2D");

MidPointPrincipal principal = getAuthorizedPrincipal(USER_GUYBRUSH_USERNAME);
ConnectionEnvironment connEnv = createConnectionEnvironment();
XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar();

try {

// WHEN
TestUtil.displayWhen(TEST_NAME);

authenticationEvaluator.authenticateUserPassword(principal, connEnv, USER_GUYBRUSH_PASSWORD);

AssertJUnit.fail("Unexpected success");

} catch (BadCredentialsException e) {
// This is expected

// THEN
TestUtil.displayThen(TEST_NAME);
display("expected exception", e);
assertExpiredException(e, principal);
}
XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar();

PrismObject<UserType> userAfter = getUser(USER_GUYBRUSH_OID);
display("user after", userAfter);
assertFailedLogins(userAfter, 0);
}

private void assertGoodPasswordAuthentication(Authentication authentication, MidPointPrincipal principal) {
assertNotNull("No authentication", authentication);
Expand All @@ -438,6 +596,10 @@ private void assertLockedException(BadCredentialsException e, MidPointPrincipal
assertEquals("Wrong exception meessage (key)", "web.security.provider.locked", e.getMessage());
}

private void assertExpiredException(BadCredentialsException e, MidPointPrincipal principal) {
assertEquals("Wrong exception meessage (key)", "web.security.provider.password.bad", e.getMessage());
}

private ConnectionEnvironment createConnectionEnvironment() {
ConnectionEnvironment connEnv = new ConnectionEnvironment();
connEnv.setRemoteHost("remote.example.com");
Expand Down Expand Up @@ -467,9 +629,8 @@ private void assertLastFailedLogin(PrismObject<UserType> user, XMLGregorianCalen
TestUtil.assertBetween("wrong last failed login timestamp", startTs, endTs, failedLoginTs);
}

private MidPointPrincipal getAuthorizedPrincipal(String userJackUsername) throws ObjectNotFoundException {
MidPointPrincipal principal = userProfileService.getPrincipal(USER_JACK_USERNAME);
assertPrincipalJack(principal);
private MidPointPrincipal getAuthorizedPrincipal(String username) throws ObjectNotFoundException {
MidPointPrincipal principal = userProfileService.getPrincipal(username);
if (principal.getAuthorities().isEmpty()) {
AuthorizationType authorizationType = new AuthorizationType();
authorizationType.getAction().add("FAKE");
Expand Down
Expand Up @@ -20,7 +20,7 @@
<name>Security Policy</name>
<credentials>
<password>
<maxAge>P10Y</maxAge>
<maxAge>P30D</maxAge>
<lockoutMaxFailedAttempts>3</lockoutMaxFailedAttempts>
<lockoutFailedAttemptsDuration>PT3M</lockoutFailedAttemptsDuration>
<lockoutDuration>PT15M</lockoutDuration>
Expand Down
10 changes: 1 addition & 9 deletions model/model-impl/src/test/resources/common/user-guybrush.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2013 Evolveum
~ Copyright (c) 2010-2016 Evolveum
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,12 +30,4 @@
<familyName>Threepwood</familyName>
<locality>Melee Island</locality>

<!-- <credentials> -->
<!-- <password> -->
<!-- <value> -->
<!-- <clearValue>xM4rksTh3Sp0t</clearValue> -->
<!-- </value> -->
<!-- </password> -->
<!-- </credentials> -->

</user>
Expand Up @@ -72,9 +72,7 @@ public class TestPassword extends AbstractInitializedModelIntegrationTest {
private static final String USER_PASSWORD_3_CLEAR = "wh3r3sTheRum?";
private static final String USER_PASSWORD_4_CLEAR = "sh1v3rM3T1mb3rs";
private static final String USER_PASSWORD_5_CLEAR = "s3tSa1al";

private static final ItemPath PASSWORD_VALUE_PATH = new ItemPath(UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD, PasswordType.F_VALUE);


private String accountOid;
private String accountRedOid;
private XMLGregorianCalendar lastPasswordChangeStart;
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2015 Evolveum
* Copyright (c) 2010-2016 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -209,6 +209,8 @@ public abstract class AbstractModelIntegrationTest extends AbstractIntegrationTe
protected static final ItemPath ACTIVATION_VALID_TO_PATH = new ItemPath(UserType.F_ACTIVATION,
ActivationType.F_VALID_TO);

protected static final ItemPath PASSWORD_VALUE_PATH = new ItemPath(UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD, PasswordType.F_VALUE);

@Autowired(required = true)
protected ModelService modelService;

Expand Down Expand Up @@ -3006,15 +3008,19 @@ protected void assertPasswordMetadata(PrismObject<UserType> user, boolean create
assertNotNull("No password metadata in "+user, metadataContainer);
MetadataType metadataType = metadataContainer.getValue().asContainerable();
if (create) {
ObjectReferenceType creatorRef = metadataType.getCreatorRef();
assertNotNull("No creatorRef in password metadata in "+user, creatorRef);
assertEquals("Wrong creatorRef OID in password metadata in "+user, actorOid, creatorRef.getOid());
if (actorOid != null) {
ObjectReferenceType creatorRef = metadataType.getCreatorRef();
assertNotNull("No creatorRef in password metadata in "+user, creatorRef);
assertEquals("Wrong creatorRef OID in password metadata in "+user, actorOid, creatorRef.getOid());
}
TestUtil.assertBetween("Wrong password create timestamp in password metadata in "+user, start, end, metadataType.getCreateTimestamp());
assertEquals("Wrong create channel", channel, metadataType.getCreateChannel());
} else {
ObjectReferenceType modifierRef = metadataType.getModifierRef();
assertNotNull("No modifierRef in password metadata in "+user, modifierRef);
assertEquals("Wrong modifierRef OID in password metadata in "+user, actorOid, modifierRef.getOid());
if (actorOid != null) {
ObjectReferenceType modifierRef = metadataType.getModifierRef();
assertNotNull("No modifierRef in password metadata in "+user, modifierRef);
assertEquals("Wrong modifierRef OID in password metadata in "+user, actorOid, modifierRef.getOid());
}
TestUtil.assertBetween("Wrong password modify timestamp in password metadata in "+user, start, end, metadataType.getModifyTimestamp());
assertEquals("Wrong modification channel", channel, metadataType.getModifyChannel());
}
Expand Down

0 comments on commit 404a0a7

Please sign in to comment.