blob: c9363bdecb2b7360687b55f979ba76ae1bc349b1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.syncope.core.provisioning.java;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.MappingManager;
import org.identityconnectors.common.security.SecurityUtil;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.identityconnectors.framework.common.objects.OperationalAttributes;
@Transactional("Master")
public class DefaultMappingManagerTest extends AbstractTest {
@Autowired
private MappingManager mappingManager;
@Autowired
private UserDAO userDAO;
@Autowired
private ExternalResourceDAO resourceDAO;
@Autowired
private RealmDAO realmDAO;
@Autowired
private GroupDAO groupDAO;
@Autowired
private AnyTypeClassDAO anyTypeClassDAO;
@Autowired
private PlainSchemaDAO plainSchemaDAO;
@Autowired
private AnyUtilsFactory anyUtilsFactory;
@Autowired
private EntityFactory entityFactory;
@Test
public void prepareAttrsForUser() {
User bellini = userDAO.findByUsername("bellini");
ExternalResource ldap = resourceDAO.find("resource-ldap");
Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).get();
assertNotEquals(CipherAlgorithm.AES, bellini.getCipherAlgorithm());
// 1. with clear-text password
Pair<String, Set<Attribute>> attrs = mappingManager.prepareAttrsFromAny(
bellini,
"Password123",
true,
Boolean.TRUE,
provision);
assertEquals("bellini", attrs.getLeft());
assertEquals(
"uid=bellini,ou=people,o=isp",
AttributeUtil.getNameFromAttributes(attrs.getRight()).getNameValue());
assertEquals("Password123", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs.getRight())));
// 2. with changePwd == false
attrs = mappingManager.prepareAttrsFromAny(
bellini,
"Password123",
false,
Boolean.TRUE,
provision);
assertNull(AttributeUtil.getPasswordValue(attrs.getRight()));
// 3. with no clear-text password but random password generation enabled
ldap.setRandomPwdIfNotProvided(true);
ldap = resourceDAO.save(ldap);
entityManager().flush();
String encPassword = bellini.getPassword();
attrs = mappingManager.prepareAttrsFromAny(
bellini,
null,
true,
Boolean.TRUE,
provision);
assertNotEquals(encPassword, SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs.getRight())));
// 4. with no clear-text password and random password generation disabled
ldap.setRandomPwdIfNotProvided(false);
resourceDAO.save(ldap);
entityManager().flush();
attrs = mappingManager.prepareAttrsFromAny(
bellini,
null,
true,
Boolean.TRUE,
provision);
assertNull(AttributeUtil.getPasswordValue(attrs.getRight()));
// 5. with no clear-text password, random password generation disabled but AES
bellini.setPassword("newPassword123", CipherAlgorithm.AES);
userDAO.save(bellini);
entityManager().flush();
assertEquals(CipherAlgorithm.AES, bellini.getCipherAlgorithm());
attrs = mappingManager.prepareAttrsFromAny(
bellini,
null,
true,
Boolean.TRUE,
provision);
assertEquals("newPassword123", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs.getRight())));
}
@Test
public void prepareAttrsForLinkedAccount() {
User vivaldi = userDAO.findByUsername("vivaldi");
ExternalResource ldap = resourceDAO.find("resource-ldap");
Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).get();
LinkedAccount account = entityFactory.newEntity(LinkedAccount.class);
account.setConnObjectKeyValue("admin");
account.setResource(ldap);
account.setOwner(vivaldi);
account.setSuspended(Boolean.FALSE);
account.setPassword("Password321", CipherAlgorithm.AES);
vivaldi.add(account);
vivaldi = userDAO.save(vivaldi);
entityManager().flush();
// 1. with account password and clear-text default password
Set<Attribute> attrs = mappingManager.prepareAttrsFromLinkedAccount(
vivaldi,
account,
"Password123",
true,
provision);
assertEquals("admin", AttributeUtil.getStringValue(AttributeUtil.find("cn", attrs)));
assertEquals("Password321", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs)));
assertTrue(AttributeUtil.getBooleanValue(AttributeUtil.find(OperationalAttributes.ENABLE_NAME, attrs)));
// 2. without account password and clear-text default password
account.setEncodedPassword(null, null);
attrs = mappingManager.prepareAttrsFromLinkedAccount(
vivaldi,
account,
"Password123",
true,
provision);
assertEquals("Password123", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs)));
// 3. with changePwd == false
attrs = mappingManager.prepareAttrsFromLinkedAccount(
vivaldi,
account,
"Password123",
false,
provision);
assertNull(AttributeUtil.getPasswordValue(attrs));
// 4. without account password, no clear-text password but random password generation enabled
ldap.setRandomPwdIfNotProvided(true);
ldap = resourceDAO.save(ldap);
entityManager().flush();
String encPassword = vivaldi.getPassword();
attrs = mappingManager.prepareAttrsFromLinkedAccount(
vivaldi,
account,
null,
true,
provision);
assertNotEquals(encPassword, SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs)));
// 5. without account password, no clear-text password and random password generation disabled
ldap.setRandomPwdIfNotProvided(false);
resourceDAO.save(ldap);
entityManager().flush();
attrs = mappingManager.prepareAttrsFromLinkedAccount(
vivaldi,
account,
null,
true,
provision);
assertNull(AttributeUtil.getPasswordValue(attrs));
}
@Test
public void issueSYNCOPE1583() {
// 0. create user matching the condition below
User user = entityFactory.newEntity(User.class);
user.setUsername("username");
user.setRealm(realmDAO.findByFullPath("/even/two"));
user.add(anyTypeClassDAO.find("other"));
UPlainAttr cool = entityFactory.newEntity(UPlainAttr.class);
cool.setOwner(user);
cool.setSchema(plainSchemaDAO.find("cool"));
cool.add("true", anyUtilsFactory.getInstance(AnyTypeKind.USER));
user.add(cool);
user = userDAO.save(user);
String newUserKey = user.getKey();
assertNotNull(newUserKey);
// 1. update group with dynamic membership
Group group = groupDAO.findByName("root");
assertNotNull(group);
UDynGroupMembership dynMembership = entityFactory.newEntity(UDynGroupMembership.class);
dynMembership.setFIQLCond("cool==true");
dynMembership.setGroup(group);
group.setUDynMembership(dynMembership);
group = groupDAO.saveAndRefreshDynMemberships(group);
assertNotNull(group);
entityManager().flush();
// 2. verify that dynamic membership is in place
assertTrue(userDAO.findAllGroupKeys(user).contains(group.getKey()));
// 3. check propagation attrs
ExternalResource csv = resourceDAO.find("resource-csv");
Provision provision = csv.getProvision(AnyTypeKind.USER.name()).get();
assertNotNull(provision);
Pair<String, Set<Attribute>> attrs = mappingManager.prepareAttrsFromAny(
user,
null,
false,
Boolean.TRUE,
provision);
assertTrue(attrs.getRight().stream().anyMatch(
attr -> "theirgroup".equals(attr.getName()) && List.of("sx-dx").equals(attr.getValue())));
}
}