Skip to content

Commit c2a9ed2

Browse files
committed
Ensure to check authorizations for Reconciliation methods
1 parent c2f9e26 commit c2a9ed2

4 files changed

Lines changed: 62 additions & 41 deletions

File tree

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

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import org.apache.syncope.common.rest.api.beans.AbstractCSVSpec;
4747
import org.apache.syncope.common.rest.api.beans.CSVPullSpec;
4848
import org.apache.syncope.common.rest.api.beans.CSVPushSpec;
49-
import org.apache.syncope.core.logic.AbstractTransactionalLogic.ProvisioningInfo;
5049
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
5150
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
5251
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
@@ -88,6 +87,7 @@
8887
import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
8988
import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
9089
import org.apache.syncope.core.spring.security.AuthContextUtils;
90+
import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
9191
import org.identityconnectors.framework.common.objects.Attribute;
9292
import org.identityconnectors.framework.common.objects.ConnectorObject;
9393
import org.identityconnectors.framework.common.objects.ObjectClass;
@@ -161,23 +161,6 @@ public ReconciliationLogic(
161161
this.ctx = ctx;
162162
}
163163

164-
protected ProvisioningInfo getProvisioningInfo(final String anyTypeKey, final String resourceKey) {
165-
AnyType anyType = anyTypeDAO.findById(anyTypeKey).
166-
orElseThrow(() -> new NotFoundException("AnyType " + anyTypeKey));
167-
168-
ExternalResource resource = resourceDAO.findById(resourceKey).
169-
orElseThrow(() -> new NotFoundException("Resource '" + resourceKey));
170-
171-
Provision provision = resource.getProvisionByAnyType(anyType.getKey()).
172-
orElseThrow(() -> new NotFoundException(
173-
"Provision for " + anyType + " on Resource '" + resourceKey + "'"));
174-
if (provision.getMapping() == null) {
175-
throw new NotFoundException("Mapping for " + anyType + " on Resource '" + resourceKey + "'");
176-
}
177-
178-
return new ProvisioningInfo(anyType, resource, provision);
179-
}
180-
181164
protected ConnObject getOnSyncope(
182165
final Item connObjectKeyItem,
183166
final String connObjectKeyValue,
@@ -244,6 +227,22 @@ protected Any getAny(final Provision provision, final AnyTypeKind anyTypeKind, f
244227
orElseThrow(() -> new NotFoundException(provision.getAnyType() + " '" + anyKey + "'"));
245228
}
246229

230+
protected ProvisioningInfo getProvisioningInfo(final String anyTypeKey, final String resourceKey) {
231+
AnyType anyType = anyTypeDAO.findById(anyTypeKey).
232+
orElseThrow(() -> new NotFoundException("AnyType " + anyTypeKey));
233+
234+
ExternalResource resource = Optional.ofNullable(resourceDAO.authFind(resourceKey)).
235+
orElseThrow(() -> new NotFoundException("Resource '" + resourceKey + '\''));
236+
Provision provision = resource.getProvisionByAnyType(anyType.getKey()).
237+
orElseThrow(() -> new NotFoundException(
238+
"Provision for " + anyType + " on Resource '" + resourceKey + "'"));
239+
if (provision.getMapping() == null) {
240+
throw new NotFoundException("Mapping for " + anyType + " on Resource '" + resourceKey + "'");
241+
}
242+
243+
return new ProvisioningInfo(anyType, resource, provision);
244+
}
245+
247246
@PreAuthorize("hasRole('" + IdMEntitlement.RESOURCE_GET_CONNOBJECT + "')")
248247
@Transactional(readOnly = true)
249248
public ReconStatus status(
@@ -407,6 +406,12 @@ public List<ProvisioningReport> push(
407406
return results;
408407
}
409408

409+
protected void securityChecks(final Set<String> realms, final String realm, final String resourceKey) {
410+
if (!RealmUtils.SubtreePredicate.of(realms).test(realm)) {
411+
throw new DelegatedAdministrationException(realm, ExternalResource.class.getSimpleName(), resourceKey);
412+
}
413+
}
414+
410415
@PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_EXECUTE + "')")
411416
@Transactional(readOnly = true)
412417
public List<ProvisioningReport> push(
@@ -418,6 +423,14 @@ public List<ProvisioningReport> push(
418423

419424
ProvisioningInfo info = getProvisioningInfo(anyTypeKey, resourceKey);
420425

426+
Realm sourceRealm = Optional.ofNullable(pushTask.getSourceRealm()).
427+
flatMap(realmSearchDAO::findByFullPath).
428+
orElseThrow(() -> new NotFoundException("Realm " + pushTask.getSourceRealm()));
429+
Set<String> effectiveRealms = RealmUtils.getEffective(
430+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
431+
sourceRealm.getFullPath());
432+
securityChecks(effectiveRealms, sourceRealm.getFullPath(), null);
433+
421434
SyncDeltaBuilder syncDeltaBuilder = syncDeltaBuilder(
422435
info.resource(), info.provision(), filter, moreAttrsToGet);
423436

@@ -478,11 +491,13 @@ protected List<ProvisioningReport> pull(
478491
final Set<String> moreAttrsToGet,
479492
final PullTaskTO pullTask) {
480493

481-
if (pullTask.getDestinationRealm() == null
482-
|| realmSearchDAO.findByFullPath(pullTask.getDestinationRealm()).isEmpty()) {
483-
484-
throw new NotFoundException("Realm " + pullTask.getDestinationRealm());
485-
}
494+
Realm destRealm = Optional.ofNullable(pullTask.getDestinationRealm()).
495+
flatMap(realmSearchDAO::findByFullPath).
496+
orElseThrow(() -> new NotFoundException("Realm " + pullTask.getDestinationRealm()));
497+
Set<String> effectiveRealms = RealmUtils.getEffective(
498+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
499+
destRealm.getFullPath());
500+
securityChecks(effectiveRealms, destRealm.getFullPath(), null);
486501

487502
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Reconciliation);
488503
List<ProvisioningReport> results = new ArrayList<>();
@@ -606,7 +621,8 @@ public List<ProvisioningReport> push(
606621
entitlement = IdRepoEntitlement.USER_SEARCH;
607622
}
608623

609-
Realm base = realmSearchDAO.findByFullPath(realm).
624+
Realm base = Optional.ofNullable(realm).
625+
flatMap(realmSearchDAO::findByFullPath).
610626
orElseThrow(() -> new NotFoundException("Realm " + realm));
611627

612628
Set<String> adminRealms = RealmUtils.getEffective(AuthContextUtils.getAuthorizations().get(entitlement), realm);
@@ -684,12 +700,16 @@ public List<ProvisioningReport> pull(final CSVPullSpec spec, final InputStream c
684700
AnyType anyType = anyTypeDAO.findById(spec.getAnyTypeKey()).
685701
orElseThrow(() -> new NotFoundException("AnyType " + spec.getAnyTypeKey()));
686702

687-
if (realmSearchDAO.findByFullPath(spec.getDestinationRealm()) == null) {
688-
throw new NotFoundException("Realm " + spec.getDestinationRealm());
689-
}
703+
Realm destRealm = Optional.ofNullable(spec.getDestinationRealm()).
704+
flatMap(realmSearchDAO::findByFullPath).
705+
orElseThrow(() -> new NotFoundException("Realm " + spec.getDestinationRealm()));
706+
Set<String> effectiveRealms = RealmUtils.getEffective(
707+
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.TASK_EXECUTE),
708+
destRealm.getFullPath());
709+
securityChecks(effectiveRealms, destRealm.getFullPath(), null);
690710

691711
PullTaskTO pullTask = new PullTaskTO();
692-
pullTask.setDestinationRealm(spec.getDestinationRealm());
712+
pullTask.setDestinationRealm(destRealm.getFullPath());
693713
pullTask.setRemediation(spec.getRemediation());
694714
pullTask.setMatchingRule(spec.getMatchingRule());
695715
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())) {
@@ -373,7 +373,7 @@ public Pair<SearchResult, List<ConnObject>> searchConnObjects(
373373
ObjectClass objectClass;
374374
OperationOptions options;
375375
if (SyncopeConstants.REALM_ANYTYPE.equals(anyTypeKey)) {
376-
resource = resourceDAO.findById(key).
376+
resource = Optional.ofNullable(resourceDAO.authFind(key)).
377377
orElseThrow(() -> new NotFoundException("Resource " + key));
378378
if (resource.getOrgUnit() == null) {
379379
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)