From db0644505c1ed8936d57677412161f0d86bc2b58 Mon Sep 17 00:00:00 2001 From: Mykhailo Kuznietsov Date: Fri, 30 Mar 2018 06:45:55 +0000 Subject: [PATCH] Set correct response for non-working services in Multi User Che (#9237) --- .../UnavailableResourceInMultiUserFilter.java | 54 +++++++++++ .../server/deploy/KeycloakServletModule.java | 4 + ...vailableResourceInMultiUserFilterTest.java | 96 +++++++++++++++++++ .../src/test/resources/logback.xml | 35 +++++++ 4 files changed, 189 insertions(+) create mode 100644 multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilter.java create mode 100644 multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilterTest.java create mode 100644 multiuser/keycloak/che-multiuser-keycloak-server/src/test/resources/logback.xml diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilter.java b/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilter.java new file mode 100644 index 0000000000..2c40ff9077 --- /dev/null +++ b/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.multiuser.keycloak.server; + +import java.io.IOException; +import javax.inject.Singleton; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Filter that will return HTTP status 403. Used for resources, that are not meant to be available + * in multi-user Che. Filter omits GET requests. + */ +@Singleton +public class UnavailableResourceInMultiUserFilter implements Filter { + protected static final String ERROR_RESPONSE_JSON_MESSAGE = + "{\"error\" : \"This operation is not allowed since third-party user management service is configured\" }"; + + @Override + public void init(FilterConfig filterConfig) throws ServletException {} + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + String requestMethod = ((HttpServletRequest) request).getMethod(); + if (requestMethod.equals("GET")) { + // allow request to go through + chain.doFilter(request, response); + return; + } + + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setStatus(403); + httpResponse.setContentType("application/json"); + httpResponse.getWriter().println(ERROR_RESPONSE_JSON_MESSAGE); + } + + @Override + public void destroy() {} +} diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/deploy/KeycloakServletModule.java b/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/deploy/KeycloakServletModule.java index 60781e8c89..42cf1f6278 100644 --- a/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/deploy/KeycloakServletModule.java +++ b/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/deploy/KeycloakServletModule.java @@ -15,6 +15,7 @@ import javax.inject.Singleton; import org.eclipse.che.commons.logback.filter.IdentityIdLoggerFilter; import org.eclipse.che.multiuser.keycloak.server.KeycloakAuthenticationFilter; import org.eclipse.che.multiuser.keycloak.server.KeycloakEnvironmentInitalizationFilter; +import org.eclipse.che.multiuser.keycloak.server.UnavailableResourceInMultiUserFilter; public class KeycloakServletModule extends ServletModule { @Override @@ -29,5 +30,8 @@ public class KeycloakServletModule extends ServletModule { .through(KeycloakEnvironmentInitalizationFilter.class); filterRegex("^(?!.*(/docs/))(?!.*(/keycloak/settings/?|/api/oauth/callback/?)$).*") .through(IdentityIdLoggerFilter.class); + + filterRegex("/user/?.*").through(UnavailableResourceInMultiUserFilter.class); + filterRegex("/profile/.*/attributes").through(UnavailableResourceInMultiUserFilter.class); } } diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilterTest.java b/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilterTest.java new file mode 100644 index 0000000000..d47a244246 --- /dev/null +++ b/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/UnavailableResourceInMultiUserFilterTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.multiuser.keycloak.server; + +import static com.jayway.restassured.RestAssured.given; +import static org.eclipse.che.multiuser.keycloak.server.UnavailableResourceInMultiUserFilter.ERROR_RESPONSE_JSON_MESSAGE; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; + +import com.jayway.restassured.response.Response; +import org.everrest.assured.EverrestJetty; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +@Listeners(value = {EverrestJetty.class, MockitoTestNGListener.class}) +public class UnavailableResourceInMultiUserFilterTest { + @SuppressWarnings("unused") + private static final UnavailableResourceInMultiUserFilter FILTER = + new UnavailableResourceInMultiUserFilter(); + + @Test(dataProvider = "allowedRequests") + public void shouldAllowGetRequests(String url) { + final Response response = given().when().get(url); + + assertNotEquals(response.getStatusCode(), 403); + assertNotEquals(response.getBody().print().trim(), ERROR_RESPONSE_JSON_MESSAGE); + } + + @Test + public void shouldReturnForbiddenResponseForUserDeletion() { + + final Response response = given().when().delete("/user/123"); + + assertEquals(response.getStatusCode(), 403); + assertEquals(response.getBody().print().trim(), ERROR_RESPONSE_JSON_MESSAGE); + } + + @Test + public void shouldReturnForbiddenResponseForUserPasswordUpdate() { + + final Response response = given().when().post("/user/password"); + + assertEquals(response.getStatusCode(), 403); + assertEquals(response.getBody().print().trim(), ERROR_RESPONSE_JSON_MESSAGE); + } + + @Test + public void shouldReturnForbiddenResponseForCurrentUserProfileUpdate() { + + final Response response = given().when().post("/profile/attributes"); + + assertEquals(response.getStatusCode(), 403); + assertEquals(response.getBody().print().trim(), ERROR_RESPONSE_JSON_MESSAGE); + } + + @Test + public void shouldReturnForbiddenResponseFortUserProfileUpdate() { + + final Response response = given().when().post("/profile/profile123/attributes"); + + assertEquals(response.getStatusCode(), 403); + assertEquals(response.getBody().print().trim(), ERROR_RESPONSE_JSON_MESSAGE); + } + + @Test + public void shouldReturnForbiddenResponseForCurrentUserProfileDelete() { + + final Response response = given().when().delete("/profile/attributes"); + + assertEquals(response.getStatusCode(), 403); + assertEquals(response.getBody().print().trim(), ERROR_RESPONSE_JSON_MESSAGE); + } + + @DataProvider(name = "allowedRequests") + public Object[][] allowedRequests() { + return new Object[][] { + {"/user"}, + {"/user/"}, + {"/user/user123"}, + {"/user/find"}, + {"/user/settings"}, + {"/profile"}, + {"/profile/profile123"} + }; + } +} diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/src/test/resources/logback.xml b/multiuser/keycloak/che-multiuser-keycloak-server/src/test/resources/logback.xml new file mode 100644 index 0000000000..8d0bd11d3e --- /dev/null +++ b/multiuser/keycloak/che-multiuser-keycloak-server/src/test/resources/logback.xml @@ -0,0 +1,35 @@ + + + + + + + %-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n + + + + + target/log/log.log + + %-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n + + + + + + + + + +