This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 4_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/4_0_X by this push:
new 12c6b35c67 Permission check on Delegations
12c6b35c67 is described below
commit 12c6b35c673cd436d38cf3f7b9ab2dc70ddd41e6
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Wed Aug 12 18:40:23 2026 +0200
Permission check on Delegations
---
.../syncope/core/logic/AuthProfileLogic.java | 6 ++-
.../apache/syncope/core/logic/DelegationLogic.java | 22 +++++----
.../java/data/DelegationDataBinderImpl.java | 56 ++++++++++++++--------
.../java/data/ResourceDataBinderImpl.java | 8 +---
.../security/DelegatedAdministrationException.java | 5 --
5 files changed, 54 insertions(+), 43 deletions(-)
diff --git
a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AuthProfileLogic.java
b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AuthProfileLogic.java
index a14c3eec84..712ffe012e 100644
---
a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AuthProfileLogic.java
+++
b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AuthProfileLogic.java
@@ -19,6 +19,7 @@
package org.apache.syncope.core.logic;
import java.util.List;
+import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.AuthProfileTO;
import org.apache.syncope.common.lib.types.AMEntitlement;
import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -89,7 +90,8 @@ public class AuthProfileLogic extends
AbstractAuthProfileLogic {
authProfileDAO.findByOwner(AuthContextUtils.getUsername()).
filter(authProfile ->
authProfile.getKey().equals(authProfileTO.getKey())
&& authProfile.getOwner().equals(authProfileTO.getOwner())).
- orElseThrow(() -> new
DelegatedAdministrationException(AnyTypeKind.USER, authProfileTO.getOwner()));
+ orElseThrow(() -> new DelegatedAdministrationException(
+ SyncopeConstants.ROOT_REALM, AnyTypeKind.USER.name(),
authProfileTO.getOwner()));
update(authProfileTO);
}
@@ -103,6 +105,6 @@ public class AuthProfileLogic extends
AbstractAuthProfileLogic {
public void selfDelete() {
authProfileDAO.deleteById(authProfileDAO.findByOwner(AuthContextUtils.getUsername()).
orElseThrow(() -> new DelegatedAdministrationException(
- AnyTypeKind.USER, AuthContextUtils.getUsername())).getKey());
+ SyncopeConstants.ROOT_REALM, AnyTypeKind.USER.name(),
AuthContextUtils.getUsername())).getKey());
}
}
diff --git
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/DelegationLogic.java
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/DelegationLogic.java
index 0b3593a70a..3eaa6156fd 100644
---
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/DelegationLogic.java
+++
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/DelegationLogic.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.logic;
import java.lang.reflect.Method;
import java.util.List;
-import java.util.stream.Stream;
+import java.util.Set;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.DelegationTO;
@@ -30,6 +30,7 @@ import
org.apache.syncope.core.persistence.api.dao.DelegationDAO;
import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.Delegation;
+import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.data.DelegationDataBinder;
import org.apache.syncope.core.spring.security.AuthContextUtils;
import
org.apache.syncope.core.spring.security.DelegatedAdministrationException;
@@ -55,12 +56,13 @@ public class DelegationLogic extends
AbstractTransactionalLogic<DelegationTO> {
}
protected void securityChecks(final String delegating, final String
entitlement) {
- if (!AuthContextUtils.getAuthorizations().containsKey(entitlement)
+ Set<String> realms =
AuthContextUtils.getAuthorizations().getOrDefault(entitlement, Set.of());
+
+ if (realms.isEmpty()
&& (delegating == null ||
!delegating.equals(userDAO.findKey(AuthContextUtils.getUsername()).
orElseThrow(() -> new NotFoundException("Could not
find authenticated user"))))) {
- throw new DelegatedAdministrationException(
- SyncopeConstants.ROOT_REALM, AnyTypeKind.USER.name(),
delegating);
+ throw new DelegatedAdministrationException(realms.toString(),
AnyTypeKind.USER.name(), delegating);
}
}
@@ -78,14 +80,14 @@ public class DelegationLogic extends
AbstractTransactionalLogic<DelegationTO> {
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
public List<DelegationTO> list() {
- Stream<DelegationTO> delegations =
delegationDAO.findAll().stream().map(binder::getDelegationTO);
-
- if
(!AuthContextUtils.getAuthorizations().containsKey(IdRepoEntitlement.DELEGATION_LIST))
{
- String authUserKey =
userDAO.findKey(AuthContextUtils.getUsername()).orElse(null);
- delegations = delegations.filter(delegation ->
delegation.getDelegating().equals(authUserKey));
+ if
(AuthContextUtils.getAuthorizations().containsKey(IdRepoEntitlement.DELEGATION_LIST))
{
+ return
delegationDAO.findAll().stream().map(binder::getDelegationTO).toList();
}
- return delegations.toList();
+ User delegating =
userDAO.findByUsername(AuthContextUtils.getUsername()).
+ orElseThrow(() -> new NotFoundException("User " +
AuthContextUtils.getUsername()));
+
+ return
delegationDAO.findByDelegating(delegating).stream().map(binder::getDelegationTO).toList();
}
@PreAuthorize("isAuthenticated()")
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DelegationDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DelegationDataBinderImpl.java
index 8a0ce23e34..6b204553b1 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DelegationDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DelegationDataBinderImpl.java
@@ -18,20 +18,24 @@
*/
package org.apache.syncope.core.provisioning.java.data;
-import java.util.Iterator;
-import java.util.stream.Collectors;
+import java.util.Set;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.to.DelegationTO;
import org.apache.syncope.common.lib.to.RoleTO;
import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IdRepoEntitlement;
import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.dao.RoleDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.Delegation;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.Role;
import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.api.utils.RealmUtils;
import org.apache.syncope.core.provisioning.api.data.DelegationDataBinder;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import
org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -75,29 +79,43 @@ public class DelegationDataBinderImpl implements
DelegationDataBinder {
delegation.setStart(delegationTO.getStart());
delegation.setEnd(delegationTO.getEnd());
+ String entitlement = delegation.getKey() == null
+ ? IdRepoEntitlement.DELEGATION_CREATE
+ : IdRepoEntitlement.DELEGATION_UPDATE;
+ Set<String> allowedRealms =
AuthContextUtils.getAuthorizations().get(entitlement);
+
// 1. add or update all (valid) roles from TO
- delegationTO.getRoles().forEach(roleTO -> {
- if (roleTO == null) {
+ delegationTO.getRoles().forEach(roleKey -> {
+ if (roleKey == null) {
LOG.error("Null {}", RoleTO.class.getSimpleName());
} else {
- Role role = roleDAO.findById(roleTO).
- orElseThrow(() -> {
- SyncopeClientException sce =
SyncopeClientException.build(ClientExceptionType.InvalidRole);
- sce.getElements().add("Role " + roleTO + " not
found");
- return sce;
- });
-
- delegation.add(role);
+ Role role = roleDAO.findById(roleKey).orElseThrow(() -> {
+ SyncopeClientException sce =
SyncopeClientException.build(ClientExceptionType.InvalidRole);
+ sce.getElements().add("Role " + roleKey + " not found");
+ return sce;
+ });
+
+ if (delegation.getDelegating().getRoles().contains(role)) {
+ if (role.getRealms().stream().
+ anyMatch(realm ->
!RealmUtils.getEffective(allowedRealms, realm.getFullPath()).isEmpty())) {
+
+ delegation.add(role);
+ } else {
+ throw new DelegatedAdministrationException(
+
role.getRealms().stream().map(Realm::getKey).toList().toString(),
+ Role.class.getSimpleName(),
+ role.getKey());
+ }
+ } else {
+ SyncopeClientException sce =
SyncopeClientException.build(ClientExceptionType.InvalidRole);
+ sce.getElements().add("Role " + roleKey + " not owned by
delegating User");
+ throw sce;
+ }
}
});
// 2. remove all roles not contained in the TO
- for (Iterator<? extends Role> itor = delegation.getRoles().iterator();
itor.hasNext();) {
- Role role = itor.next();
- if (delegationTO.getRoles().stream().noneMatch(roleKey ->
roleKey.equals(role.getKey()))) {
- itor.remove();
- }
- }
+ delegation.getRoles().removeIf(role ->
!delegationTO.getRoles().contains(role.getKey()));
return delegation;
}
@@ -111,7 +129,7 @@ public class DelegationDataBinderImpl implements
DelegationDataBinder {
delegationTO.setDelegated(delegation.getDelegated().getKey());
delegationTO.setStart(delegation.getStart());
delegationTO.setEnd(delegation.getEnd());
-
delegationTO.getRoles().addAll(delegation.getRoles().stream().map(Role::getKey).collect(Collectors.toSet()));
+
delegationTO.getRoles().addAll(delegation.getRoles().stream().map(Role::getKey).toList());
return delegationTO;
}
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 9bc5f3ace2..d40a9f2c2e 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -19,7 +19,6 @@
package org.apache.syncope.core.provisioning.java.data;
import java.text.ParseException;
-import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
@@ -219,12 +218,7 @@ public class ResourceDataBinderImpl implements
ResourceDataBinder {
});
// 2. remove all provisions not contained in the TO
- for (Iterator<Provision> itor = resource.getProvisions().iterator();
itor.hasNext();) {
- Provision provision = itor.next();
- if (resourceTO.getProvision(provision.getAnyType()).isEmpty()) {
- itor.remove();
- }
- }
+ resource.getProvisions().removeIf(provision ->
resourceTO.getProvision(provision.getAnyType()).isEmpty());
// 3. orgUnit
if (resourceTO.getOrgUnit() == null && resource.getOrgUnit() != null) {
diff --git
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
index 779f89e2f4..fc1eb31a73 100644
---
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
+++
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
@@ -19,7 +19,6 @@
package org.apache.syncope.core.spring.security;
import java.util.Optional;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
public class DelegatedAdministrationException extends RuntimeException {
@@ -29,8 +28,4 @@ public class DelegatedAdministrationException extends
RuntimeException {
super("Missing entitlement or realm administration under " + realm + "
for "
+ Optional.ofNullable(key).map(s -> type + ' ' +
s).orElseGet(() -> "new " + type));
}
-
- public DelegatedAdministrationException(final AnyTypeKind type, final
String key) {
- super("The requested UPDATE would alter the set of dynamic realms for
" + type + ' ' + key);
- }
}