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 8e85596582 Ensure to check authorizations for Reconciliation methods
8e85596582 is described below
commit 8e85596582cd5ce92f69dd6ddb700baf74474950
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Wed Aug 12 16:54:13 2026 +0200
Ensure to check authorizations for Reconciliation methods
---
.../syncope/core/logic/ReconciliationLogic.java | 74 ++++++++++++++--------
.../apache/syncope/core/logic/ResourceLogic.java | 14 ++--
.../apache/syncope/core/logic/AbstractLogic.java | 7 ++
.../core/logic/AbstractTransactionalLogic.java | 6 --
4 files changed, 62 insertions(+), 39 deletions(-)
diff --git
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
index 978b3ec316..ed19460b57 100644
---
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
+++
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
@@ -89,6 +89,7 @@ import
org.apache.syncope.core.provisioning.java.pushpull.stream.StreamPushJobDe
import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
import org.apache.syncope.core.spring.security.AuthContextUtils;
+import
org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.ObjectClass;
@@ -156,23 +157,6 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
this.connectorManager = connectorManager;
}
- protected ProvisioningInfo getProvisioningInfo(final String anyTypeKey,
final String resourceKey) {
- AnyType anyType = anyTypeDAO.findById(anyTypeKey).
- orElseThrow(() -> new NotFoundException("AnyType " +
anyTypeKey));
-
- ExternalResource resource = resourceDAO.findById(resourceKey).
- orElseThrow(() -> new NotFoundException("Resource '" +
resourceKey));
-
- Provision provision = resource.getProvisionByAnyType(anyType.getKey()).
- orElseThrow(() -> new NotFoundException(
- "Provision for " + anyType + " on Resource '" + resourceKey +
"'"));
- if (provision.getMapping() == null) {
- throw new NotFoundException("Mapping for " + anyType + " on
Resource '" + resourceKey + "'");
- }
-
- return new ProvisioningInfo(anyType, resource, provision);
- }
-
protected ConnObject getOnSyncope(
final Item connObjectKeyItem,
final String connObjectKeyValue,
@@ -239,6 +223,22 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
orElseThrow(() -> new NotFoundException(provision.getAnyType()
+ " '" + anyKey + "'"));
}
+ protected ProvisioningInfo getProvisioningInfo(final String anyTypeKey,
final String resourceKey) {
+ AnyType anyType = anyTypeDAO.findById(anyTypeKey).
+ orElseThrow(() -> new NotFoundException("AnyType " +
anyTypeKey));
+
+ ExternalResource resource =
Optional.ofNullable(resourceDAO.authFind(resourceKey)).
+ orElseThrow(() -> new NotFoundException("Resource '" +
resourceKey + '\''));
+ Provision provision = resource.getProvisionByAnyType(anyType.getKey()).
+ orElseThrow(() -> new NotFoundException(
+ "Provision for " + anyType + " on Resource '" + resourceKey +
"'"));
+ if (provision.getMapping() == null) {
+ throw new NotFoundException("Mapping for " + anyType + " on
Resource '" + resourceKey + "'");
+ }
+
+ return new ProvisioningInfo(anyType, resource, provision);
+ }
+
@PreAuthorize("hasRole('" + IdMEntitlement.RESOURCE_GET_CONNOBJECT + "')")
public ReconStatus status(
final String anyTypeKey,
@@ -398,6 +398,12 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
return results;
}
+ protected void securityChecks(final Set<String> realms, final String
realm, final String resourceKey) {
+ if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
+ throw new DelegatedAdministrationException(realm,
ExternalResource.class.getSimpleName(), resourceKey);
+ }
+ }
+
@PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_EXECUTE + "')")
public List<ProvisioningReport> push(
final String anyTypeKey,
@@ -408,6 +414,14 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
ProvisioningInfo info = getProvisioningInfo(anyTypeKey, resourceKey);
+ Realm sourceRealm = Optional.ofNullable(pushTask.getSourceRealm()).
+ flatMap(realmSearchDAO::findByFullPath).
+ orElseThrow(() -> new NotFoundException("Realm " +
pushTask.getSourceRealm()));
+ Set<String> effectiveRealms = RealmUtils.getEffective(
+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
+ sourceRealm.getFullPath());
+ securityChecks(effectiveRealms, sourceRealm.getFullPath(), null);
+
SyncDeltaBuilder syncDeltaBuilder = syncDeltaBuilder(
info.resource(), info.provision(), filter, moreAttrsToGet);
@@ -467,10 +481,13 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
final Set<String> moreAttrsToGet,
final PullTaskTO pullTask) {
- if (pullTask.getDestinationRealm() == null ||
realmSearchDAO.findByFullPath(pullTask.getDestinationRealm())
- == null) {
- throw new NotFoundException("Realm " +
pullTask.getDestinationRealm());
- }
+ Realm destRealm = Optional.ofNullable(pullTask.getDestinationRealm()).
+ flatMap(realmSearchDAO::findByFullPath).
+ orElseThrow(() -> new NotFoundException("Realm " +
pullTask.getDestinationRealm()));
+ Set<String> effectiveRealms = RealmUtils.getEffective(
+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
+ destRealm.getFullPath());
+ securityChecks(effectiveRealms, destRealm.getFullPath(), null);
SyncopeClientException sce =
SyncopeClientException.build(ClientExceptionType.Reconciliation);
List<ProvisioningReport> results = new ArrayList<>();
@@ -594,7 +611,8 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
entitlement = IdRepoEntitlement.USER_SEARCH;
}
- Realm base = realmSearchDAO.findByFullPath(realm).
+ Realm base = Optional.ofNullable(realm).
+ flatMap(realmSearchDAO::findByFullPath).
orElseThrow(() -> new NotFoundException("Realm " + realm));
Set<String> adminRealms =
RealmUtils.getEffective(AuthContextUtils.getAuthorizations().get(entitlement),
realm);
@@ -673,12 +691,16 @@ public class ReconciliationLogic extends
AbstractTransactionalLogic<EntityTO> {
AnyType anyType = anyTypeDAO.findById(spec.getAnyTypeKey()).
orElseThrow(() -> new NotFoundException("AnyType " +
spec.getAnyTypeKey()));
- if (realmSearchDAO.findByFullPath(spec.getDestinationRealm()) == null)
{
- throw new NotFoundException("Realm " + spec.getDestinationRealm());
- }
+ Realm destRealm = Optional.ofNullable(spec.getDestinationRealm()).
+ flatMap(realmSearchDAO::findByFullPath).
+ orElseThrow(() -> new NotFoundException("Realm " +
spec.getDestinationRealm()));
+ Set<String> effectiveRealms = RealmUtils.getEffective(
+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
+ destRealm.getFullPath());
+ securityChecks(effectiveRealms, destRealm.getFullPath(), null);
PullTaskTO pullTask = new PullTaskTO();
- pullTask.setDestinationRealm(spec.getDestinationRealm());
+ pullTask.setDestinationRealm(destRealm.getFullPath());
pullTask.setRemediation(spec.getRemediation());
pullTask.setMatchingRule(spec.getMatchingRule());
pullTask.setUnmatchingRule(spec.getUnmatchingRule());
diff --git
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index 0671cc44de..3ba12cb910 100644
---
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -107,12 +107,6 @@ public class ResourceLogic extends
AbstractTransactionalLogic<ResourceTO> {
this.anyUtilsFactory = anyUtilsFactory;
}
- protected void securityChecks(final Set<String> realms, final String
realm, final String key) {
- if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
- throw new DelegatedAdministrationException(realm,
ExternalResource.class.getSimpleName(), key);
- }
- }
-
protected ExternalResource doSave(final ExternalResource resource) {
ExternalResource merged = resourceDAO.save(resource);
try {
@@ -123,6 +117,12 @@ public class ResourceLogic extends
AbstractTransactionalLogic<ResourceTO> {
return merged;
}
+ protected void securityChecks(final Set<String> realms, final String
realm, final String resourceKey) {
+ if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
+ throw new DelegatedAdministrationException(realm,
ExternalResource.class.getSimpleName(), resourceKey);
+ }
+ }
+
@PreAuthorize("hasRole('" + IdMEntitlement.RESOURCE_CREATE + "')")
public ResourceTO create(final ResourceTO resourceTO) {
if (StringUtils.isBlank(resourceTO.getKey())) {
@@ -379,7 +379,7 @@ public class ResourceLogic extends
AbstractTransactionalLogic<ResourceTO> {
ObjectClass objectClass;
OperationOptions options;
if (SyncopeConstants.REALM_ANYTYPE.equals(anyTypeKey)) {
- resource = resourceDAO.findById(key).
+ resource = Optional.ofNullable(resourceDAO.authFind(key)).
orElseThrow(() -> new NotFoundException("Resource " +
key));
if (resource.getOrgUnit() == null) {
throw new NotFoundException("Realm provisioning for resource
'" + key + '\'');
diff --git
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
index 7452835f76..4120d56d9f 100644
---
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
+++
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
@@ -20,6 +20,9 @@ package org.apache.syncope.core.logic;
import java.lang.reflect.Method;
import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.to.Provision;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
@@ -33,6 +36,10 @@ public abstract class AbstractLogic<T extends EntityTO> {
protected static final Logger LOG =
LoggerFactory.getLogger(AbstractLogic.class);
+ protected record ProvisioningInfo(AnyType anyType, ExternalResource
resource, Provision provision) {
+
+ }
+
/**
* Resolves stored bean (if existing) referred by the given CUD method.
* Read-only methods will be unresolved for performance reasons.
diff --git
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractTransactionalLogic.java
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractTransactionalLogic.java
index 88cfb489fc..2208cc629e 100644
---
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractTransactionalLogic.java
+++
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractTransactionalLogic.java
@@ -19,9 +19,6 @@
package org.apache.syncope.core.logic;
import org.apache.syncope.common.lib.to.EntityTO;
-import org.apache.syncope.common.lib.to.Provision;
-import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.ExternalResource;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -32,7 +29,4 @@ import
org.springframework.transaction.annotation.Transactional;
@Transactional(rollbackFor = { Throwable.class })
public abstract class AbstractTransactionalLogic<T extends EntityTO> extends
AbstractLogic<T> {
- protected record ProvisioningInfo(AnyType anyType, ExternalResource
resource, Provision provision) {
-
- }
}