use of eu.bcvsolutions.idm.acc.dto.AccPasswordFilterRequestDto in project CzechIdMng by bcvsolutions.
the class DefaultPasswordFilterManagerIntegrationTest method testValidateWithMinPasswordAgeUnderAdmin.
@Test
public void testValidateWithMinPasswordAgeUnderAdmin() {
SysSystemDto system = createSystem(false);
IdmPasswordPolicyDto policy = new IdmPasswordPolicyDto();
policy.setName(getHelper().createName());
policy.setType(IdmPasswordPolicyType.VALIDATE);
policy.setMinPasswordAge(1);
policy = passwordPolicyService.save(policy);
system.setPasswordPolicyValidate(policy.getId());
system = systemService.save(system);
IdmIdentityDto identity = createIdentity(system);
setPasswordFilter(system, true);
assignSystem(createUniformDefinition(true), system);
cleanProvivisioning(identity, system);
checkChangeInIdm(identity, 0);
String password = getHelper().createName();
PasswordRequest request = prepareRequest(identity.getUsername(), system.getCode(), password);
IdmPasswordDto idmPassword = passwordService.findOneByIdentity(identity.getId());
Assert.assertNull(idmPassword);
checkEmptyProvisioning(identity, system);
checkEcho(identity, system, EchoCheck.DOESNT_EXIST);
checkChangeInIdm(identity, 0);
processValidate(request, true);
checkEcho(identity, system, EchoCheck.VALIDATE);
checkChangeInIdm(identity, 0);
checkEmptyProvisioning(identity, system);
processChange(request, true);
checkEcho(identity, system, EchoCheck.VALIDATE_AND_CHANGE);
checkChangeInIdm(identity, 1);
checkEmptyProvisioning(identity, system);
idmPassword = passwordService.findOneByIdentity(identity.getId());
Assert.assertNotNull(idmPassword);
// under different user, but set
Assert.assertNotNull(idmPassword.getValidFrom());
// success => admin can change password
try {
request.setPassword(getHelper().createName());
getHelper().loginAdmin();
//
AccPasswordFilterRequestDto passwordFilterRequest = new AccPasswordFilterRequestDto();
passwordFilterRequest.setUsername(identity.getUsername());
// different password => new validate without cache
passwordFilterRequest.setPassword(new GuardedString(getHelper().createName()));
passwordFilterRequest.setResource(system.getCode());
//
passwordFilterManager.validate(passwordFilterRequest);
} finally {
getHelper().logout();
}
}
use of eu.bcvsolutions.idm.acc.dto.AccPasswordFilterRequestDto in project CzechIdMng by bcvsolutions.
the class DefaultPasswordFilterManagerIntegrationTest method testValidateWithMinPasswordAgeFailed.
@Test(expected = PasswordChangeException.class)
public void testValidateWithMinPasswordAgeFailed() {
SysSystemDto system = createSystem(false);
IdmPasswordPolicyDto policy = new IdmPasswordPolicyDto();
policy.setName(getHelper().createName());
policy.setType(IdmPasswordPolicyType.VALIDATE);
policy.setMinPasswordAge(1);
policy = passwordPolicyService.save(policy);
system.setPasswordPolicyValidate(policy.getId());
system = systemService.save(system);
IdmIdentityDto identity = createIdentity(system);
setPasswordFilter(system, true);
assignSystem(createUniformDefinition(true), system);
cleanProvivisioning(identity, system);
checkChangeInIdm(identity, 0);
String password = getHelper().createName();
PasswordRequest request = prepareRequest(identity.getUsername(), system.getCode(), password);
IdmPasswordDto idmPassword = passwordService.findOneByIdentity(identity.getId());
Assert.assertNull(idmPassword);
checkEmptyProvisioning(identity, system);
checkEcho(identity, system, EchoCheck.DOESNT_EXIST);
checkChangeInIdm(identity, 0);
processValidate(request, true);
checkEcho(identity, system, EchoCheck.VALIDATE);
checkChangeInIdm(identity, 0);
checkEmptyProvisioning(identity, system);
processChange(request, true);
checkEcho(identity, system, EchoCheck.VALIDATE_AND_CHANGE);
checkChangeInIdm(identity, 1);
checkEmptyProvisioning(identity, system);
idmPassword = passwordService.findOneByIdentity(identity.getId());
Assert.assertNotNull(idmPassword);
// under different user, but set
Assert.assertNotNull(idmPassword.getValidFrom());
// fail => cannot be changed again by policy
try {
request.setPassword(getHelper().createName());
IdmIdentityDto manager = getHelper().createIdentity();
getHelper().login(manager);
//
AccPasswordFilterRequestDto passwordFilterRequest = new AccPasswordFilterRequestDto();
passwordFilterRequest.setUsername(identity.getUsername());
// different password => new validate without cache
passwordFilterRequest.setPassword(new GuardedString(getHelper().createName()));
passwordFilterRequest.setResource(system.getCode());
//
passwordFilterManager.validate(passwordFilterRequest);
} finally {
getHelper().logout();
}
}
use of eu.bcvsolutions.idm.acc.dto.AccPasswordFilterRequestDto in project CzechIdMng by bcvsolutions.
the class DefaultPasswordFilterManager method change.
@Override
public void change(AccPasswordFilterRequestDto request) {
LOG.info("Change request from resource [{}] for identity identifier [{}] starting. {}", request.getResource(), request.getUsername(), request.getLogMetadata());
SysSystemDto system = getSystem(request.getResource());
SysSystemAttributeMappingDto passwordFilterAttribute = getAttributeMappingForPasswordFilter(system);
IdmIdentityDto identity = evaluateUsernameToIdentity(system, request, passwordFilterAttribute);
List<AccUniformPasswordDto> passwordDefinitions = getActiveUniformPasswordDefinitions(system);
final GuardedString password = request.getPassword();
final long timeout = passwordFilterAttribute.getEchoTimeout();
final boolean changeInIdm = changeInIdm(passwordDefinitions);
// Accounts with password filter support.
List<AccAccountDto> managedAccounts = null;
// Accounts only for password changed without echo and password filter system.
List<AccAccountDto> notManagedAccounts = null;
// System doesn't exists in password uniform feature.
if (CollectionUtils.isEmpty(passwordDefinitions)) {
LOG.debug("System [{}] isn't exist in uniform password definition. Password will be changed only trough the given system.");
// Try find one account for given system with supported passwod filter
managedAccounts = getAccountForSystemWithPasswordFilter(system, identity);
notManagedAccounts = Lists.newArrayList();
} else {
UUID identityId = identity.getId();
managedAccounts = getAccountsForPasswordChange(passwordDefinitions, identityId, Boolean.TRUE);
notManagedAccounts = getAccountsForPasswordChange(passwordDefinitions, identityId, Boolean.FALSE);
}
if (managedAccounts.isEmpty()) {
LOG.warn("Password will not be changed! For identifier [{}] (identity username: [{}]) and resource [{}] wasn't found any managed account. {}", request.getUsername(), identity.getUsername(), request.getResource(), request.getLogMetadata());
return;
}
// Accounts for current system only.
List<AccAccountDto> accounts = managedAccounts.stream().filter(account -> {
return account.getSystem().equals(system.getId());
}).collect(Collectors.toList());
for (AccAccountDto account : accounts) {
AccPasswordFilterEchoItemDto echo = getEcho(account.getId());
if (echo == null) {
// Echo doesn't exist yet validation must be executed first!
LOG.error("Echo record for validation doesn't exist! For account uid [{}] and system code [{}]. Execute validation first! {}", account.getUid(), system.getCode(), request.getLogMetadata());
throw new ResultCodeException(AccResultCode.PASSWORD_FILTER_NOT_VALID_CHANGE_REQUEST, ImmutableMap.of("identifier", identity.getId()));
}
boolean echoValid = echo.isEchoValid(timeout);
boolean passwordEqual = isPasswordEqual(echo, password);
if (!passwordEqual) {
// Password doesn't match with checked password - security problem.
LOG.error("Password doesn't match with validated password! For account uid [{}] and system code [{}]. {}", account.getUid(), system.getCode(), request.getLogMetadata());
throw new ResultCodeException(AccResultCode.PASSWORD_FILTER_NOT_VALID_CHANGE_REQUEST, ImmutableMap.of("identifier", identity.getId()));
}
if (BooleanUtils.isFalse(echo.isValidityChecked())) {
// Validation wasn't successfully executed yet - validation must pass.
LOG.error("Password wasn't successfully validated! For account id [{}] and system id [{}]. Validation must pass! {}", account.getId(), system.getId(), request.getLogMetadata());
throw new ResultCodeException(AccResultCode.PASSWORD_FILTER_NOT_VALID_CHANGE_REQUEST, ImmutableMap.of("identifier", identity.getId()));
}
if (echoValid && echo.isChanged()) {
// Classic valid echo that was already changed, for this echo will not be changed again - FOR ALL ANOTHER SYSTEMS.
LOG.info("Echo record found! For account uid [{}] and system code [{}]. Password will not be changed. {}", account.getUid(), system.getCode(), request.getLogMetadata());
// For one valid echo just skip password change
return;
}
}
// Create final account list for password change and check duplicate.
List<AccAccountDto> finalAccounts = Lists.newArrayList(managedAccounts);
notManagedAccounts.forEach(account -> {
if (!finalAccounts.contains(account)) {
finalAccounts.add(account);
}
});
// Remove account for original resource - is possible that account can be empty.
List<UUID> accountsForResource = Lists.newArrayList();
finalAccounts.removeIf(account -> {
if (account.getSystem().equals(system.getId())) {
accountsForResource.add(account.getId());
return true;
}
return false;
});
// When account is empty and uniform password doesn't required password change trough IdM skip password change process.
if (finalAccounts.isEmpty() && changeInIdm == false) {
LOG.info("Request for resource indetifier [{}] (identity username [{}]) and system code [{}] will not be processed! No suitable account found (including IdM). {}", request.getUsername(), identity.getUsername(), system.getCode(), request.getLogMetadata());
// Set echos for accounts by the given system, because there is password changed by the system.
accounts.forEach(account -> {
setEchoForChange(account.getId(), password);
});
return;
}
// Prepare account ids
List<String> accountsIds = Lists.newArrayList();
finalAccounts.forEach(account -> {
accountsIds.add(account.getId().toString());
});
if (finalAccounts.isEmpty()) {
LOG.info("Password change will be processed only trough IdM. For identity [{}] and system [{}]. {}", identity.getUsername(), system.getCode(), request.getLogMetadata());
} else {
LOG.info("Password change will be processed. For identity [{}] and system [{}] was found these accounts for change [{}]. {}", identity.getUsername(), system.getCode(), Strings.join(accountsIds, ','), request.getLogMetadata());
}
// Setup echo for resource from that was executed from event password.
accountsForResource.forEach(accountId -> {
setEchoForChange(accountId, password);
});
// Prepare request for password change.
PasswordChangeDto passwordChangeDto = new PasswordChangeDto();
// Not for all, but only for chosen
passwordChangeDto.setAll(false);
passwordChangeDto.setIdm(changeInIdm);
passwordChangeDto.setAccounts(accountsIds);
passwordChangeDto.setNewPassword(password);
passwordChangeDto.setSkipResetValidFrom(true);
//
IdentityEvent identityEvent = new IdentityEvent(IdentityEventType.PASSWORD, identity, ImmutableMap.of(IdentityPasswordProcessor.PROPERTY_PASSWORD_CHANGE_DTO, passwordChangeDto, // Managed accounts in event is for performance speedup in processor IdentityPasswordProvisioningProcessor and set echos
MANAGED_ACCOUNTS, Lists.newArrayList(managedAccounts.stream().map(AccAccountDto::getId).collect(Collectors.toList())), // Exclude all accounts for given system
EXCLUDED_SYSTEM, system.getId(), // Skip whole validation just change password - password was validate before
IdentityProcessor.SKIP_PASSWORD_VALIDATION, Boolean.TRUE));
// Classic password change event
identityService.passwordChange(identityEvent);
LOG.info("Password change was finished! For identity username [{}] and system code [{}]. {}", identity.getUsername(), system.getCode(), request.getLogMetadata());
}
use of eu.bcvsolutions.idm.acc.dto.AccPasswordFilterRequestDto in project CzechIdMng by bcvsolutions.
the class DefaultPasswordFilterManager method validate.
@Override
public void validate(AccPasswordFilterRequestDto request) {
LOG.info("Validation request from resource [{}] for identity identifier [{}] starting. {}", request.getResource(), request.getUsername(), request.getLogMetadata());
SysSystemDto system = getSystem(request.getResource());
SysSystemAttributeMappingDto passwordFilterAttribute = getAttributeMappingForPasswordFilter(system);
IdmIdentityDto identity = evaluateUsernameToIdentity(system, request, passwordFilterAttribute);
List<AccUniformPasswordDto> passwordDefinitions = getActiveUniformPasswordDefinitions(system);
final GuardedString password = request.getPassword();
final long timeout = passwordFilterAttribute.getEchoTimeout();
final boolean changeInIdm = changeInIdm(passwordDefinitions);
// Accounts with password filter support
List<AccAccountDto> managedAccounts = null;
// Accounts only for password changed without echo and password filter system
List<AccAccountDto> notManagedAccounts = null;
// System doesn't exists in password uniform feature
if (CollectionUtils.isEmpty(passwordDefinitions)) {
LOG.debug("System [{}] isn't exist in uniform password definition. Password will be check only trough the given system.");
// Try find one account for given system with supported password filter
managedAccounts = getAccountForSystemWithPasswordFilter(system, identity);
notManagedAccounts = Lists.newArrayList();
} else {
UUID identityId = identity.getId();
managedAccounts = getAccountsForPasswordChange(passwordDefinitions, identityId, Boolean.TRUE);
notManagedAccounts = getAccountsForPasswordChange(passwordDefinitions, identityId, Boolean.FALSE);
}
if (managedAccounts.isEmpty()) {
LOG.warn("For identifier [{}] (identity: [{}]) and resource [{}] wasn't found any managed account, validation will not be processed. {}", request.getUsername(), identity.getUsername(), request.getResource(), request.getLogMetadata());
return;
}
// Accounts for current system only
List<AccAccountDto> accounts = managedAccounts.stream().filter(account -> {
return account.getSystem().equals(system.getId());
}).collect(Collectors.toList());
for (AccAccountDto account : accounts) {
AccPasswordFilterEchoItemDto echo = getEcho(account.getId());
if (echo == null) {
// Echo doesn't exist yet we can continue for validation
LOG.debug("Echo for account id [{}] and system identifier [{}] doesn't exist. {}", account.getId(), request.getUsername(), request.getLogMetadata());
continue;
}
boolean echoValid = echo.isEchoValid(timeout);
boolean passwordEqual = isPasswordEqual(echo, password);
if (echoValid && passwordEqual && echo.isChanged()) {
// Classic valid echo that was already changed, for this echo will not validate again
LOG.info("Echo record found! Account uid [{}] and system code [{}]. Validation will be skipped. {}", account.getUid(), system.getCode(), request.getLogMetadata());
// For one valid echo just skip password validate for all another password from uniform password
return;
}
if (echo.isValidityChecked()) {
// Validation was successfully executed, now is second run
// TODO: can we skip this validation?
LOG.debug("For account [{}] and system [{}] exist only echo for validation. {}", account.getUid(), system.getCode(), request.getLogMetadata());
}
}
// Unite system from managed and not managed accounts
List<SysSystemDto> systems = getSystemForAccounts(managedAccounts);
systems.addAll(getSystemForAccounts(notManagedAccounts));
// Get password policies from managed systems
List<IdmPasswordPolicyDto> policies = getPasswordPolicy(systems);
// Default password policy must be also added when is setup change trough IdM
if (changeInIdm) {
IdmPasswordPolicyDto defaultPasswordPolicy = policyService.getDefaultPasswordPolicy(IdmPasswordPolicyType.VALIDATE);
// Password policy can be added by some system check for duplicate
if (defaultPasswordPolicy != null && !policies.contains(defaultPasswordPolicy)) {
policies.add(defaultPasswordPolicy);
}
}
// For empty policies is not required process validation
if (policies.isEmpty()) {
LOG.info("Any applicable password policy found! For identifier [{}] (identity: [{}]) and resource [{}]. {}", request.getUsername(), identity.getUsername(), request.getResource(), request.getLogMetadata());
} else {
// Compose validation request for IdM
IdmPasswordValidationDto passwordValidationDto = new IdmPasswordValidationDto();
passwordValidationDto.setPassword(password);
passwordValidationDto.setIdentity(identity);
// password is changed on different logged identity, but change by password filter is originally executed as target identity
passwordValidationDto.setEnforceMinPasswordAgeValidation(true);
try {
policyService.validate(passwordValidationDto, policies);
} catch (Exception e) {
// Just log the message and send error next
LOG.error("Validation didn't pass! For identity username [{}] and system code [{}]. Error message: [{}]. {}", identity.getUsername(), system.getCode(), StringUtils.defaultString(e.getMessage()), request.getLogMetadata());
// Set echod with not information about not valid password
managedAccounts.forEach(account -> {
createEchoForValidation(account.getId(), password, false);
});
// Throw error to caller
throw e;
}
}
// Set validate echos only for managed accounts
managedAccounts.forEach(account -> {
createEchoForValidation(account.getId(), password, true);
});
// Password valid
LOG.info("Validation request pass! For identity [{}] and system code [{}]. {}", identity.getUsername(), system.getCode(), request.getLogMetadata());
}
Aggregations