Skip to content

Commit 8e85596

Browse files
committed
Ensure to check authorizations for Reconciliation methods
1 parent 5074b57 commit 8e85596

4 files changed

Lines changed: 62 additions & 39 deletions

File tree

‎core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java‎

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
9090
import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
9191
import org.apache.syncope.core.spring.security.AuthContextUtils;
92+
import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
9293
import org.identityconnectors.framework.common.objects.Attribute;
9394
import org.identityconnectors.framework.common.objects.ConnectorObject;
9495
import org.identityconnectors.framework.common.objects.ObjectClass;
@@ -156,23 +157,6 @@ public ReconciliationLogic(
156157
this.connectorManager = connectorManager;
157158
}
158159

159-
protected ProvisioningInfo getProvisioningInfo(final String anyTypeKey, final String resourceKey) {
160-
AnyType anyType = anyTypeDAO.findById(anyTypeKey).
161-
orElseThrow(() -> new NotFoundException("AnyType " + anyTypeKey));
162-
163-
ExternalResource resource = resourceDAO.findById(resourceKey).
164-
orElseThrow(() -> new NotFoundException("Resource '" + resourceKey));
165-
166-
Provision provision = resource.getProvisionByAnyType(anyType.getKey()).
167-
orElseThrow(() -> new NotFoundException(
168-
"Provision for " + anyType + " on Resource '" + resourceKey + "'"));
169-
if (provision.getMapping() == null) {
170-
throw new NotFoundException("Mapping for " + anyType + " on Resource '" + resourceKey + "'");
171-
}
172-
173-
return new ProvisioningInfo(anyType, resource, provision);
174-
}
175-
176160
protected ConnObject getOnSyncope(
177161
final Item connObjectKeyItem,
178162
final String connObjectKeyValue,
@@ -239,6 +223,22 @@ protected Any getAny(final Provision provision, final AnyTypeKind anyTypeKind, f
239223
orElseThrow(() -> new NotFoundException(provision.getAnyType() + " '" + anyKey + "'"));
240224
}
241225

226+
protected ProvisioningInfo getProvisioningInfo(final String anyTypeKey, final String resourceKey) {
227+
AnyType anyType = anyTypeDAO.findById(anyTypeKey).
228+
orElseThrow(() -> new NotFoundException("AnyType " + anyTypeKey));
229+
230+
ExternalResource resource = Optional.ofNullable(resourceDAO.authFind(resourceKey)).
231+
orElseThrow(() -> new NotFoundException("Resource '" + resourceKey + '\''));
232+
Provision provision = resource.getProvisionByAnyType(anyType.getKey()).
233+
orElseThrow(() -> new NotFoundException(
234+
"Provision for " + anyType + " on Resource '" + resourceKey + "'"));
235+
if (provision.getMapping() == null) {
236+
throw new NotFoundException("Mapping for " + anyType + " on Resource '" + resourceKey + "'");
237+
}
238+
239+
return new ProvisioningInfo(anyType, resource, provision);
240+
}
241+
242242
@PreAuthorize("hasRole('" + IdMEntitlement.RESOURCE_GET_CONNOBJECT + "')")
243243
public ReconStatus status(
244244
final String anyTypeKey,
@@ -398,6 +398,12 @@ public List<ProvisioningReport> push(
398398
return results;
399399
}
400400

401+
protected void securityChecks(final Set<String> realms, final String realm, final String resourceKey) {
402+
if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
403+
throw new DelegatedAdministrationException(realm, ExternalResource.class.getSimpleName(), resourceKey);
404+
}
405+
}
406+
401407
@PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_EXECUTE + "')")
402408
public List<ProvisioningReport> push(
403409
final String anyTypeKey,
@@ -408,6 +414,14 @@ public List<ProvisioningReport> push(
408414

409415
ProvisioningInfo info = getProvisioningInfo(anyTypeKey, resourceKey);
410416

417+
Realm sourceRealm = Optional.ofNullable(pushTask.getSourceRealm()).
418+
flatMap(realmSearchDAO::findByFullPath).
419+
orElseThrow(() -> new NotFoundException("Realm " + pushTask.getSourceRealm()));
420+
Set<String> effectiveRealms = RealmUtils.getEffective(
421+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
422+
sourceRealm.getFullPath());
423+
securityChecks(effectiveRealms, sourceRealm.getFullPath(), null);
424+
411425
SyncDeltaBuilder syncDeltaBuilder = syncDeltaBuilder(
412426
info.resource(), info.provision(), filter, moreAttrsToGet);
413427

@@ -467,10 +481,13 @@ protected List<ProvisioningReport> pull(
467481
final Set<String> moreAttrsToGet,
468482
final PullTaskTO pullTask) {
469483

470-
if (pullTask.getDestinationRealm() == null || realmSearchDAO.findByFullPath(pullTask.getDestinationRealm())
471-
== null) {
472-
throw new NotFoundException("Realm " + pullTask.getDestinationRealm());
473-
}
484+
Realm destRealm = Optional.ofNullable(pullTask.getDestinationRealm()).
485+
flatMap(realmSearchDAO::findByFullPath).
486+
orElseThrow(() -> new NotFoundException("Realm " + pullTask.getDestinationRealm()));
487+
Set<String> effectiveRealms = RealmUtils.getEffective(
488+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
489+
destRealm.getFullPath());
490+
securityChecks(effectiveRealms, destRealm.getFullPath(), null);
474491

475492
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Reconciliation);
476493
List<ProvisioningReport> results = new ArrayList<>();
@@ -594,7 +611,8 @@ public List<ProvisioningReport> push(
594611
entitlement = IdRepoEntitlement.USER_SEARCH;
595612
}
596613

597-
Realm base = realmSearchDAO.findByFullPath(realm).
614+
Realm base = Optional.ofNullable(realm).
615+
flatMap(realmSearchDAO::findByFullPath).
598616
orElseThrow(() -> new NotFoundException("Realm " + realm));
599617

600618
Set<String> adminRealms = RealmUtils.getEffective(AuthContextUtils.getAuthorizations().get(entitlement), realm);
@@ -673,12 +691,16 @@ public List<ProvisioningReport> pull(final CSVPullSpec spec, final InputStream c
673691
AnyType anyType = anyTypeDAO.findById(spec.getAnyTypeKey()).
674692
orElseThrow(() -> new NotFoundException("AnyType " + spec.getAnyTypeKey()));
675693

676-
if (realmSearchDAO.findByFullPath(spec.getDestinationRealm()) == null) {
677-
throw new NotFoundException("Realm " + spec.getDestinationRealm());
678-
}
694+
Realm destRealm = Optional.ofNullable(spec.getDestinationRealm()).
695+
flatMap(realmSearchDAO::findByFullPath).
696+
orElseThrow(() -> new NotFoundException("Realm " + spec.getDestinationRealm()));
697+
Set<String> effectiveRealms = RealmUtils.getEffective(
698+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
699+
destRealm.getFullPath());
700+
securityChecks(effectiveRealms, destRealm.getFullPath(), null);
679701

680702
PullTaskTO pullTask = new PullTaskTO();
681-
pullTask.setDestinationRealm(spec.getDestinationRealm());
703+
pullTask.setDestinationRealm(destRealm.getFullPath());
682704
pullTask.setRemediation(spec.getRemediation());
683705
pullTask.setMatchingRule(spec.getMatchingRule());
684706
pullTask.setUnmatchingRule(spec.getUnmatchingRule());

‎core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,6 @@ public ResourceLogic(
107107
this.anyUtilsFactory = anyUtilsFactory;
108108
}
109109

110-
protected void securityChecks(final Set<String> realms, final String realm, final String key) {
111-
if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
112-
throw new DelegatedAdministrationException(realm, ExternalResource.class.getSimpleName(), key);
113-
}
114-
}
115-
116110
protected ExternalResource doSave(final ExternalResource resource) {
117111
ExternalResource merged = resourceDAO.save(resource);
118112
try {
@@ -123,6 +117,12 @@ protected ExternalResource doSave(final ExternalResource resource) {
123117
return merged;
124118
}
125119

120+
protected void securityChecks(final Set<String> realms, final String realm, final String resourceKey) {
121+
if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
122+
throw new DelegatedAdministrationException(realm, ExternalResource.class.getSimpleName(), resourceKey);
123+
}
124+
}
125+
126126
@PreAuthorize("hasRole('" + IdMEntitlement.RESOURCE_CREATE + "')")
127127
public ResourceTO create(final ResourceTO resourceTO) {
128128
if (StringUtils.isBlank(resourceTO.getKey())) {
@@ -379,7 +379,7 @@ public Pair<SearchResult, List<ConnObject>> searchConnObjects(
379379
ObjectClass objectClass;
380380
OperationOptions options;
381381
if (SyncopeConstants.REALM_ANYTYPE.equals(anyTypeKey)) {
382-
resource = resourceDAO.findById(key).
382+
resource = Optional.ofNullable(resourceDAO.authFind(key)).
383383
orElseThrow(() -> new NotFoundException("Resource " + key));
384384
if (resource.getOrgUnit() == null) {
385385
throw new NotFoundException("Realm provisioning for resource '" + key + '\'');

‎core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
import java.lang.reflect.Method;
2222
import org.apache.syncope.common.lib.to.EntityTO;
23+
import org.apache.syncope.common.lib.to.Provision;
24+
import org.apache.syncope.core.persistence.api.entity.AnyType;
25+
import org.apache.syncope.core.persistence.api.entity.ExternalResource;
2326
import org.slf4j.Logger;
2427
import org.slf4j.LoggerFactory;
2528
import org.springframework.transaction.annotation.Transactional;
@@ -33,6 +36,10 @@ public abstract class AbstractLogic<T extends EntityTO> {
3336

3437
protected static final Logger LOG = LoggerFactory.getLogger(AbstractLogic.class);
3538

39+
protected record ProvisioningInfo(AnyType anyType, ExternalResource resource, Provision provision) {
40+
41+
}
42+
3643
/**
3744
* Resolves stored bean (if existing) referred by the given CUD method.
3845
* Read-only methods will be unresolved for performance reasons.

‎core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractTransactionalLogic.java‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
package org.apache.syncope.core.logic;
2020

2121
import org.apache.syncope.common.lib.to.EntityTO;
22-
import org.apache.syncope.common.lib.to.Provision;
23-
import org.apache.syncope.core.persistence.api.entity.AnyType;
24-
import org.apache.syncope.core.persistence.api.entity.ExternalResource;
2522
import org.springframework.transaction.annotation.Transactional;
2623

2724
/**
@@ -32,7 +29,4 @@
3229
@Transactional(rollbackFor = { Throwable.class })
3330
public abstract class AbstractTransactionalLogic<T extends EntityTO> extends AbstractLogic<T> {
3431

35-
protected record ProvisioningInfo(AnyType anyType, ExternalResource resource, Provision provision) {
36-
37-
}
3832
}

0 commit comments

Comments
 (0)