You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/10/01 15:04:45 UTC
[4/6] syncope git commit: [SYNCOPE-1377] Added JAX-RS
ContainerRequestFilter to check X-Syncope-Domain provided value
[SYNCOPE-1377] Added JAX-RS ContainerRequestFilter to check X-Syncope-Domain provided value
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/54e528b8
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/54e528b8
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/54e528b8
Branch: refs/heads/2_1_X
Commit: 54e528b894873708b635e74a9410d1ca00e696b9
Parents: c2e8a20
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Oct 1 17:01:49 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Oct 1 17:04:09 2018 +0200
----------------------------------------------------------------------
.../syncope/core/rest/cxf/AddETagFilter.java | 2 +-
.../core/rest/cxf/CheckDomainFilter.java | 81 ++++++++++++++++++++
.../src/main/resources/restCXFContext.xml | 2 +
.../core/spring/security/AuthContextUtils.java | 15 ++--
.../src/main/resources/jboss/restCXFContext.xml | 2 +
.../syncope/fit/core/MultitenancyITCase.java | 17 ++++
6 files changed, 110 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/54e528b8/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AddETagFilter.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AddETagFilter.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AddETagFilter.java
index dc6f0e6..145bea2 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AddETagFilter.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AddETagFilter.java
@@ -31,7 +31,7 @@ import org.apache.syncope.common.lib.to.EntityTO;
import org.apache.syncope.common.lib.to.ProvisioningResult;
/**
- * Adds the <tt>ETag</tt> header to any response containing an instance of {@link AbstractAnnotatedBean} as entity.
+ * Adds the {@code ETag} header to any response containing an instance of {@link AbstractAnnotatedBean} as entity.
* The actual ETag value is computed on the basis of last change date (or creation date if not available).
*/
@Provider
http://git-wip-us.apache.org/repos/asf/syncope/blob/54e528b8/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java
new file mode 100644
index 0000000..f2aabad
--- /dev/null
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.rest.cxf;
+
+import java.io.IOException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.ErrorTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.core.persistence.api.dao.DomainDAO;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Checks that requested Domain exists.
+ */
+@Provider
+@PreMatching
+public class CheckDomainFilter implements ContainerRequestFilter {
+
+ @Autowired
+ private DomainDAO domainDAO;
+
+ @Override
+ public void filter(final ContainerRequestContext reqContext) throws IOException {
+ final String domain = reqContext.getHeaderString(RESTHeaders.DOMAIN);
+ if (domain != null && !SyncopeConstants.MASTER_DOMAIN.equals(domain)) {
+ AuthContextUtils.execWithAuthContext(
+ SyncopeConstants.MASTER_DOMAIN, new AuthContextUtils.Executable<Void>() {
+
+ @Override
+ public Void exec() {
+ if (domainDAO.find(domain) == null) {
+ String message = "Domain '" + domain + "' not available";
+
+ ErrorTO error = new ErrorTO();
+ error.setStatus(Response.Status.NOT_FOUND.getStatusCode());
+ error.setType(ClientExceptionType.NotFound);
+ error.getElements().add(message);
+
+ reqContext.abortWith(Response.status(Response.Status.NOT_FOUND).
+ entity(error).
+ header(HttpHeaders.CONTENT_TYPE,
+ reqContext.getAcceptableMediaTypes().isEmpty()
+ ? MediaType.APPLICATION_JSON
+ : reqContext.getAcceptableMediaTypes().get(0).toString()).
+ header(RESTHeaders.ERROR_CODE,
+ ClientExceptionType.NotFound.name()).
+ header(RESTHeaders.ERROR_INFO,
+ ClientExceptionType.NotFound.getInfoHeaderValue(message)).
+ build());
+ }
+ return null;
+ }
+ });
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/54e528b8/core/rest-cxf/src/main/resources/restCXFContext.xml
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/resources/restCXFContext.xml b/core/rest-cxf/src/main/resources/restCXFContext.xml
index dd3ff18..b68b33f 100644
--- a/core/rest-cxf/src/main/resources/restCXFContext.xml
+++ b/core/rest-cxf/src/main/resources/restCXFContext.xml
@@ -90,6 +90,7 @@ under the License.
<bean id="searchContextProvider" class="org.apache.cxf.jaxrs.ext.search.SearchContextProvider"/>
+ <bean id="checkDomainFilter" class="org.apache.syncope.core.rest.cxf.CheckDomainFilter"/>
<bean id="addDomainFilter" class="org.apache.syncope.core.rest.cxf.AddDomainFilter"/>
<bean id="addETagFilter" class="org.apache.syncope.core.rest.cxf.AddETagFilter"/>
@@ -165,6 +166,7 @@ under the License.
<ref bean="yamlProvider"/>
<ref bean="exceptionMapper"/>
<ref bean="searchContextProvider"/>
+ <ref bean="checkDomainFilter"/>
<ref bean="addDomainFilter"/>
<ref bean="addETagFilter"/>
<ref bean="wadlGenerator"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/54e528b8/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
----------------------------------------------------------------------
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
index 6bc5fdb..ee99056 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
@@ -98,7 +98,7 @@ public final class AuthContextUtils {
return domainKey;
}
- private static void setFakeAuth(final String domain) {
+ private static Authentication getFakeAuth(final String domain) {
List<GrantedAuthority> authorities = EntitlementsHolder.getInstance().getValues().stream().
map(entitlement -> new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM)).
collect(Collectors.toList());
@@ -107,20 +107,19 @@ public final class AuthContextUtils {
new User(ApplicationContextProvider.getBeanFactory().getBean("adminUser", String.class),
"FAKE_PASSWORD", authorities), "FAKE_PASSWORD", authorities);
auth.setDetails(new SyncopeAuthenticationDetails(domain));
- SecurityContextHolder.getContext().setAuthentication(auth);
+ return auth;
}
- public static <T> T execWithAuthContext(final String domainKey, final Executable<T> executable) {
- SecurityContext ctx = SecurityContextHolder.getContext();
- setFakeAuth(domainKey);
+ public static <T> T execWithAuthContext(final String domain, final Executable<T> executable) {
+ Authentication original = SecurityContextHolder.getContext().getAuthentication();
+ SecurityContextHolder.getContext().setAuthentication(getFakeAuth(domain));
try {
return executable.exec();
} catch (Throwable t) {
- LOG.debug("Error during execution with domain {} context", domainKey, t);
+ LOG.debug("Error during execution with domain {} context", domain, t);
throw t;
} finally {
- SecurityContextHolder.clearContext();
- SecurityContextHolder.setContext(ctx);
+ SecurityContextHolder.getContext().setAuthentication(original);
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/54e528b8/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/jboss/restCXFContext.xml b/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
index b06589b..7bb4b94 100644
--- a/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
+++ b/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
@@ -90,6 +90,7 @@ under the License.
<bean id="searchContextProvider" class="org.apache.cxf.jaxrs.ext.search.SearchContextProvider"/>
+ <bean id="checkDomainFilter" class="org.apache.syncope.core.rest.cxf.CheckDomainFilter"/>
<bean id="addDomainFilter" class="org.apache.syncope.core.rest.cxf.AddDomainFilter"/>
<bean id="addETagFilter" class="org.apache.syncope.core.rest.cxf.AddETagFilter"/>
@@ -179,6 +180,7 @@ under the License.
<ref bean="yamlProvider"/>
<ref bean="exceptionMapper"/>
<ref bean="searchContextProvider"/>
+ <ref bean="checkDomainFilter"/>
<ref bean="addDomainFilter"/>
<ref bean="addETagFilter"/>
<ref bean="wadlGenerator"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/54e528b8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
index e07c30f..c088bd6 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
@@ -21,6 +21,7 @@ package org.apache.syncope.fit.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
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 static org.junit.jupiter.api.Assertions.fail;
import java.util.List;
@@ -31,6 +32,7 @@ import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.ConnInstanceTO;
import org.apache.syncope.common.lib.to.ItemTO;
@@ -45,6 +47,7 @@ import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.PushTaskTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.LoggerType;
import org.apache.syncope.common.lib.types.MappingPurpose;
import org.apache.syncope.common.lib.types.ExecStatus;
@@ -63,6 +66,7 @@ import org.apache.syncope.common.rest.api.service.ReconciliationService;
import org.apache.syncope.common.rest.api.service.ResourceService;
import org.apache.syncope.common.rest.api.service.SchemaService;
import org.apache.syncope.common.rest.api.service.TaskService;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
import org.apache.syncope.common.rest.api.service.UserService;
import org.apache.syncope.fit.AbstractITCase;
import org.identityconnectors.framework.common.objects.ObjectClass;
@@ -241,4 +245,17 @@ public class MultitenancyITCase extends AbstractITCase {
adminClient.getService(ResourceService.class).delete(resource.getKey());
}
}
+
+ @Test
+ public void issueSYNCOPE1377() {
+ try {
+ new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("NotExisting").create().
+ getService(UserSelfService.class).
+ create(UserITCase.getUniqueSampleTO("syncope1377@syncope.apache.org"), true);
+ fail("This should not happen");
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.NotFound, e.getType());
+ assertTrue(e.getMessage().contains("NotExisting"));
+ }
+ }
}