diff --git a/distribution/downloads/src/main/resources/files b/distribution/downloads/src/main/resources/files index 5158e863ab..eeaa4c539f 100644 --- a/distribution/downloads/src/main/resources/files +++ b/distribution/downloads/src/main/resources/files @@ -1,7 +1,6 @@ ./ keycloak-server-dist:keycloak keycloak-server-overlay:keycloak-overlay - keycloak-proxy-dist:keycloak-proxy keycloak-api-docs-dist:keycloak-api-docs keycloak-examples-dist:keycloak-examples diff --git a/distribution/pom.xml b/distribution/pom.xml index 85e77defd9..46f379ce0a 100755 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -51,7 +51,6 @@ api-docs-dist examples-dist - proxy-dist downloads diff --git a/distribution/proxy-dist/assembly.xml b/distribution/proxy-dist/assembly.xml deleted file mode 100755 index 1ed31b0924..0000000000 --- a/distribution/proxy-dist/assembly.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - proxy-dist - - - zip - - - true - - - - ../../ - - License.html - - - - - - - - false - true - true - - org.keycloak:launcher - - ${artifact.artifactId}.${artifact.extension} - bin - - - false - true - true - - org.keycloak:keycloak-proxy-server - - lib - - - diff --git a/distribution/proxy-dist/pom.xml b/distribution/proxy-dist/pom.xml deleted file mode 100755 index 8fbbb98c35..0000000000 --- a/distribution/proxy-dist/pom.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - 4.0.0 - - keycloak-distribution-parent - org.keycloak - 5.0.0-SNAPSHOT - - - keycloak-proxy-dist - pom - Proxy Distro - - - - - community - - - !product - - - - - org.keycloak - launcher - - - org.keycloak - keycloak-proxy-server - - - - - keycloak-proxy-${project.version} - - - maven-assembly-plugin - - - assemble - package - - single - - - - assembly.xml - - - target - - - target/assembly/work - - false - - - - - - - - - - diff --git a/pom.xml b/pom.xml index 969e190e78..641e943919 100755 --- a/pom.xml +++ b/pom.xml @@ -1081,11 +1081,6 @@ launcher ${project.version} - - org.keycloak - keycloak-proxy-server - ${project.version} - org.keycloak keycloak-saml-core @@ -1269,12 +1264,6 @@ ${project.version} zip - - org.keycloak - keycloak-proxy-dist - ${project.version} - zip - org.keycloak keycloak-examples-dist @@ -1666,9 +1655,6 @@ ${project.version} community - - proxy - diff --git a/proxy/launcher/pom.xml b/proxy/launcher/pom.xml deleted file mode 100755 index 5471b8e5e4..0000000000 --- a/proxy/launcher/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - keycloak-parent - org.keycloak - 5.0.0-SNAPSHOT - ../../pom.xml - - 4.0.0 - - launcher - Keycloak Launcher - - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - org.keycloak.Launcher - - - - - - - - diff --git a/proxy/launcher/src/main/java/org/keycloak/Launcher.java b/proxy/launcher/src/main/java/org/keycloak/Launcher.java deleted file mode 100755 index bf662eef8f..0000000000 --- a/proxy/launcher/src/main/java/org/keycloak/Launcher.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak; - -import java.io.File; -import java.lang.reflect.Method; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class Launcher { - - public static File getHome() { - String launcherPath = Launcher.class.getName().replace('.', '/') + ".class"; - URL jarfile = Launcher.class.getClassLoader().getResource(launcherPath); - if (jarfile != null) { - Matcher m = Pattern.compile("jar:(file:.*)!/" + launcherPath).matcher(jarfile.toString()); - if (m.matches()) { - try { - File jarPath = new File(new URI(m.group(1))); - File libPath = jarPath.getParentFile().getParentFile(); - System.out.println("Home directory: " + libPath.toString()); - if (!libPath.exists()) { - System.exit(1); - - } - return libPath; - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } - } else { - System.err.println("jar file null: " + launcherPath); - } - return null; - } - - public static void main(String[] args) throws Exception { - - File home = getHome(); - File lib = new File(home, "lib"); - if (!lib.exists()) { - System.err.println("Could not find lib directory: " + lib.toString()); - System.exit(1); - } - List jars = new ArrayList(); - for (File file : lib.listFiles()) { - jars.add(file.toURI().toURL()); - } - URL[] urls = jars.toArray(new URL[jars.size()]); - URLClassLoader loader = new URLClassLoader(urls, Launcher.class.getClassLoader()); - - Class mainClass = loader.loadClass("org.keycloak.proxy.Main"); - Method mainMethod = null; - for (Method m : mainClass.getMethods()) if (m.getName().equals("main")) { mainMethod = m; break; } - Object obj = args; - mainMethod.invoke(null, obj); - } -} diff --git a/proxy/pom.xml b/proxy/pom.xml deleted file mode 100755 index ab4464a9f2..0000000000 --- a/proxy/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - keycloak-parent - org.keycloak - 5.0.0-SNAPSHOT - ../pom.xml - - Keycloak Proxy - - 4.0.0 - - keycloak-proxy-pom - pom - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - - launcher - proxy-server - - diff --git a/proxy/proxy-server/pom.xml b/proxy/proxy-server/pom.xml deleted file mode 100755 index 2bc015a9f5..0000000000 --- a/proxy/proxy-server/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - keycloak-parent - org.keycloak - 5.0.0-SNAPSHOT - ../../pom.xml - - 4.0.0 - - keycloak-proxy-server - Keycloak Proxy Server - - - - - org.jboss.logging - jboss-logging - - - org.keycloak - keycloak-core - - - org.keycloak - keycloak-undertow-adapter - - - org.keycloak - keycloak-adapter-core - - - org.apache.httpcomponents - httpclient - - - org.bouncycastle - bcprov-jdk15on - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-annotations - - - io.undertow - undertow-core - - - junit - junit - test - - - - diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java deleted file mode 100755 index 311aaa1534..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import io.undertow.server.HttpHandler; -import io.undertow.server.HttpServerExchange; -import io.undertow.util.HttpString; -import org.keycloak.adapters.undertow.KeycloakUndertowAccount; -import org.keycloak.representations.IDToken; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ConstraintAuthorizationHandler implements HttpHandler { - - public static final String KEYCLOAK_SUBJECT = "KEYCLOAK_SUBJECT"; - public static final String KEYCLOAK_USERNAME = "KEYCLOAK_USERNAME"; - public static final String KEYCLOAK_EMAIL = "KEYCLOAK_EMAIL"; - public static final String KEYCLOAK_NAME = "KEYCLOAK_NAME"; - public static final String KEYCLOAK_ACCESS_TOKEN = "KEYCLOAK_ACCESS_TOKEN"; - private final Map httpHeaderNames; - - protected HttpHandler next; - protected String errorPage; - protected boolean sendAccessToken; - - public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken, Map headerNames) { - this.next = next; - this.errorPage = errorPage; - this.sendAccessToken = sendAccessToken; - - this.httpHeaderNames = new HashMap<>(); - this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-subject", KEYCLOAK_SUBJECT))); - this.httpHeaderNames.put(KEYCLOAK_USERNAME, new HttpString(getOrDefault(headerNames, "keycloak-username", KEYCLOAK_USERNAME))); - this.httpHeaderNames.put(KEYCLOAK_EMAIL, new HttpString(getOrDefault(headerNames, "keycloak-email", KEYCLOAK_EMAIL))); - this.httpHeaderNames.put(KEYCLOAK_NAME, new HttpString(getOrDefault(headerNames, "keycloak-name", KEYCLOAK_NAME))); - this.httpHeaderNames.put(KEYCLOAK_ACCESS_TOKEN, new HttpString(getOrDefault(headerNames, "keycloak-access-token", KEYCLOAK_ACCESS_TOKEN))); - } - - private String getOrDefault(Map map, String key, String defaultValue) { - return map.containsKey(key) ? map.get(key) : defaultValue; - } - - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - - KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount(); - - SingleConstraintMatch match = exchange.getAttachment(ConstraintMatcherHandler.CONSTRAINT_KEY); - if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.AUTHENTICATE)) { - authenticatedRequest(account, exchange); - return; - } - - if (match != null) { - if(SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED.equals(match.getEmptyRoleSemantic())) { - authenticatedRequest(account, exchange); - return; - } else { - for (String role : match.getRequiredRoles()) { - if (account.getRoles().contains(role)) { - authenticatedRequest(account, exchange); - return; - } - } - } - } - - if (errorPage != null) { - exchange.setRequestPath(errorPage); - exchange.setRelativePath(errorPage); - exchange.setResolvedPath(errorPage); - next.handleRequest(exchange); - return; - - } - exchange.setResponseCode(403); - exchange.endExchange(); - - } - - public void authenticatedRequest(KeycloakUndertowAccount account, HttpServerExchange exchange) throws Exception { - if (account != null) { - IDToken idToken = account.getKeycloakSecurityContext().getToken(); - if (idToken == null) return; - if (idToken.getSubject() != null) { - exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_SUBJECT), idToken.getSubject()); - } - - if (idToken.getPreferredUsername() != null) { - exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_USERNAME), idToken.getPreferredUsername()); - } - if (idToken.getEmail() != null) { - exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_EMAIL), idToken.getEmail()); - } - if (idToken.getName() != null) { - exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_NAME), idToken.getName()); - } - if (sendAccessToken) { - exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_ACCESS_TOKEN), account.getKeycloakSecurityContext().getTokenString()); - } - } - next.handleRequest(exchange); - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java deleted file mode 100755 index 1f077b8a58..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import io.undertow.security.api.AuthenticationMechanism; -import io.undertow.server.HttpHandler; -import io.undertow.server.HttpServerExchange; -import io.undertow.util.AttachmentKey; -import org.jboss.logging.Logger; - -import java.util.List; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ConstraintMatcherHandler implements HttpHandler { - protected static Logger log = Logger.getLogger(ConstraintMatcherHandler.class); - public static final AttachmentKey CONSTRAINT_KEY = AttachmentKey.create(SingleConstraintMatch.class); - protected SecurityPathMatches matcher; - protected HttpHandler securedHandler; - protected HttpHandler unsecuredHandler; - protected String errorPage; - - public ConstraintMatcherHandler(SecurityPathMatches matcher, HttpHandler securedHandler, HttpHandler unsecuredHandler, String errorPage) { - this.matcher = matcher; - this.securedHandler = securedHandler; - this.unsecuredHandler = unsecuredHandler; - this.errorPage = errorPage; - } - - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - log.debugv("ConstraintMatcherHandler: {0}", exchange.getRelativePath()); - SingleConstraintMatch match = matcher.getSecurityInfo(exchange.getRelativePath(), exchange.getRequestMethod().toString()); - if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT)) { - unsecuredHandler.handleRequest(exchange); - return; - } - - if (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.DENY) { - if (errorPage != null) { - exchange.setRequestPath(errorPage); - exchange.setRelativePath(errorPage); - exchange.setResolvedPath(errorPage); - unsecuredHandler.handleRequest(exchange); - } else { - exchange.setResponseCode(403); - exchange.endExchange(); - } - return; - } - - if (match.getRequiredRoles().isEmpty() - && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED) { - - boolean successfulAuthenticatedMethodFound = isSuccessfulAuthenticatedMethodFound(exchange); - - if(successfulAuthenticatedMethodFound) { - //in case of authenticated we go for injecting headers - exchange.putAttachment(CONSTRAINT_KEY, match); - securedHandler.handleRequest(exchange); - return; - } else { - //in case of not authenticated we just show the resource - unsecuredHandler.handleRequest(exchange); - return; - } - } - - log.debug("found constraint"); - exchange.getSecurityContext().setAuthenticationRequired(); - exchange.putAttachment(CONSTRAINT_KEY, match); - securedHandler.handleRequest(exchange); - - } - - private boolean isSuccessfulAuthenticatedMethodFound(HttpServerExchange exchange) { - boolean successfulAuthenticatedMethodFound = false; - List authenticationMechanisms = exchange.getSecurityContext().getAuthenticationMechanisms(); - - for (AuthenticationMechanism authenticationMechanism : authenticationMechanisms) { - AuthenticationMechanism.AuthenticationMechanismOutcome authenticationMechanismOutcome = - authenticationMechanism.authenticate(exchange, exchange.getSecurityContext()); - if(authenticationMechanismOutcome.equals(AuthenticationMechanism.AuthenticationMechanismOutcome.AUTHENTICATED)) { - successfulAuthenticatedMethodFound = true; - } - } - return successfulAuthenticatedMethodFound; - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java deleted file mode 100755 index 5117be2c30..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import io.undertow.Undertow; - -import java.io.File; -import java.io.FileInputStream; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class Main { - - public static void main(String[] args) throws Exception { - String jsonConfig = "proxy.json"; - if (args.length > 0) jsonConfig = args[0]; - File file = new File(jsonConfig); - if (!file.exists()) { - System.err.println("No proxy config argument and could not find default file proxy.json"); - System.exit(1); - return; - } - FileInputStream fis = new FileInputStream(file); - Undertow proxyServer = ProxyServerBuilder.build(fis); - proxyServer.start(); - - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java deleted file mode 100755 index 30de6ca16d..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import io.undertow.security.api.SecurityContext; -import io.undertow.server.HttpHandler; -import io.undertow.server.HttpServerExchange; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ProxyAuthenticationCallHandler implements HttpHandler { - - private final HttpHandler next; - - public ProxyAuthenticationCallHandler(final HttpHandler next) { - this.next = next; - } - - /** - * Only allow the request through if successfully authenticated or if authentication is not required. - * - * @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange) - */ - @Override - public void handleRequest(final HttpServerExchange exchange) throws Exception { - SecurityContext context = exchange.getSecurityContext(); - if (context.authenticate()) { - if(!exchange.isComplete()) { - next.handleRequest(exchange); - } - } else { - exchange.endExchange(); - } - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java deleted file mode 100755 index facdbb23e7..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import com.fasterxml.jackson.annotation.JsonProperty; -import org.keycloak.representations.adapters.config.AdapterConfig; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ProxyConfig { - @JsonProperty("bind-address") - protected String bindAddress = "localhost"; - @JsonProperty("http-port") - protected Integer httpPort; - @JsonProperty("https-port") - protected Integer httpsPort; - @JsonProperty("keystore") - protected String keystore; - @JsonProperty("keystore-password") - protected String keystorePassword; - @JsonProperty("key-password") - protected String keyPassword; - @JsonProperty("buffer-size") - protected Integer bufferSize; - @JsonProperty("buffers-per-region") - protected Integer buffersPerRegion; - @JsonProperty("io-threads") - protected Integer ioThreads; - @JsonProperty("worker-threads") - protected Integer workerThreads; - @JsonProperty("direct-buffers") - protected Boolean directBuffers; - @JsonProperty("target-url") - protected String targetUrl; - /** Defaults to 30 seconds */ - @JsonProperty("target-request-timeout") - protected Integer targetRequestTimeout = 30000; - @JsonProperty("send-access-token") - protected boolean sendAccessToken; - @JsonProperty("applications") - protected List applications = new LinkedList(); - @JsonProperty("header-names") - private Map headerNames = new HashMap<>(); - - public String getBindAddress() { - return bindAddress; - } - - public void setBindAddress(String bindAddress) { - this.bindAddress = bindAddress; - } - - public Integer getHttpPort() { - return httpPort; - } - - public void setHttpPort(Integer httpPort) { - this.httpPort = httpPort; - } - - public Integer getHttpsPort() { - return httpsPort; - } - - public void setHttpsPort(Integer httpsPort) { - this.httpsPort = httpsPort; - } - - public String getKeystore() { - return keystore; - } - - public void setKeystore(String keystore) { - this.keystore = keystore; - } - - public String getKeystorePassword() { - return keystorePassword; - } - - public void setKeystorePassword(String keystorePassword) { - this.keystorePassword = keystorePassword; - } - - public String getKeyPassword() { - return keyPassword; - } - - public void setKeyPassword(String keyPassword) { - this.keyPassword = keyPassword; - } - - public Integer getBufferSize() { - return bufferSize; - } - - public void setBufferSize(Integer bufferSize) { - this.bufferSize = bufferSize; - } - - public Integer getBuffersPerRegion() { - return buffersPerRegion; - } - - public void setBuffersPerRegion(Integer buffersPerRegion) { - this.buffersPerRegion = buffersPerRegion; - } - - public Integer getIoThreads() { - return ioThreads; - } - - public void setIoThreads(Integer ioThreads) { - this.ioThreads = ioThreads; - } - - public Integer getWorkerThreads() { - return workerThreads; - } - - public void setWorkerThreads(Integer workerThreads) { - this.workerThreads = workerThreads; - } - - public Boolean getDirectBuffers() { - return directBuffers; - } - - public void setDirectBuffers(Boolean directBuffers) { - this.directBuffers = directBuffers; - } - - public String getTargetUrl() { - return targetUrl; - } - - public void setTargetUrl(String targetUrl) { - this.targetUrl = targetUrl; - } - - public Integer getTargetRequestTimeout() { - return targetRequestTimeout; - } - - public void setTargetRequestTimeout(Integer targetRequestTimeout) { - this.targetRequestTimeout = targetRequestTimeout; - } - - public List getApplications() { - return applications; - } - - public void setApplications(List applications) { - this.applications = applications; - } - - public boolean isSendAccessToken() { - return sendAccessToken; - } - - public void setSendAccessToken(boolean sendAccessToken) { - this.sendAccessToken = sendAccessToken; - } - - public void setHeaderNames(Map headerNames) { - this.headerNames = headerNames; - } - - public Map getHeaderNames() { - return headerNames; - } - - public static class Application { - @JsonProperty("base-path") - protected String basePath; - @JsonProperty("adapter-config") - protected AdapterConfig adapterConfig; - @JsonProperty("error-page") - protected String errorPage; - @JsonProperty("proxy-address-forwarding") - protected boolean proxyAddressForwarding; - @JsonProperty("constraints") - protected List constraints = new LinkedList(); - - public String getBasePath() { - return basePath; - } - - public void setBasePath(String basePath) { - this.basePath = basePath; - } - - public AdapterConfig getAdapterConfig() { - return adapterConfig; - } - - public void setAdapterConfig(AdapterConfig adapterConfig) { - this.adapterConfig = adapterConfig; - } - - public String getErrorPage() { - return errorPage; - } - - public void setErrorPage(String errorPage) { - this.errorPage = errorPage; - } - - public boolean isProxyAddressForwarding() { - return proxyAddressForwarding; - } - - public void setProxyAddressForwarding(boolean proxyAddressForwarding) { - this.proxyAddressForwarding = proxyAddressForwarding; - } - - public List getConstraints() { - return constraints; - } - - public void setConstraints(List constraints) { - this.constraints = constraints; - } - } - - public static class Constraint { - @JsonProperty("pattern") - protected String pattern; - @JsonProperty("roles-allowed") - protected Set rolesAllowed = new HashSet(); - @JsonProperty("methods") - protected Set methods = new HashSet(); - @JsonProperty("excluded-methods") - protected Set excludedMethods = new HashSet(); - @JsonProperty("deny") - protected boolean deny; - @JsonProperty("permit") - protected boolean permit; - @JsonProperty("authenticate") - protected boolean authenticate; - @JsonProperty("permit-and-inject") - protected boolean permitAndInject; - - public String getPattern() { - return pattern; - } - - public void setPattern(String pattern) { - this.pattern = pattern; - } - - public Set getRolesAllowed() { - return rolesAllowed; - } - - public void setRolesAllowed(Set rolesAllowed) { - this.rolesAllowed = rolesAllowed; - } - - public boolean isDeny() { - return deny; - } - - public void setDeny(boolean deny) { - this.deny = deny; - } - - public boolean isPermit() { - return permit; - } - - public void setPermit(boolean permit) { - this.permit = permit; - } - - public boolean isAuthenticate() { - return authenticate; - } - - public void setAuthenticate(boolean authenticate) { - this.authenticate = authenticate; - } - - public boolean isPermitAndInject() { - return permitAndInject; - } - - public void setPermitAndInject(boolean permitAndInject) { - this.permitAndInject = permitAndInject; - } - - public Set getMethods() { - return methods; - } - - public void setMethods(Set methods) { - this.methods = methods; - } - - public Set getExcludedMethods() { - return excludedMethods; - } - - public void setExcludedMethods(Set excludedMethods) { - this.excludedMethods = excludedMethods; - } - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java deleted file mode 100755 index f909937752..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.undertow.Undertow; -import io.undertow.security.api.AuthenticationMechanism; -import io.undertow.security.api.AuthenticationMode; -import io.undertow.security.handlers.AuthenticationMechanismsHandler; -import io.undertow.security.handlers.SecurityInitialHandler; -import io.undertow.security.idm.Account; -import io.undertow.security.idm.Credential; -import io.undertow.security.idm.IdentityManager; -import io.undertow.security.impl.CachedAuthenticatedSessionMechanism; -import io.undertow.server.HttpHandler; -import io.undertow.server.HttpServerExchange; -import io.undertow.server.handlers.PathHandler; -import io.undertow.server.handlers.ProxyPeerAddressHandler; -import io.undertow.server.handlers.ResponseCodeHandler; -import io.undertow.server.handlers.proxy.ProxyHandler; -import io.undertow.server.handlers.proxy.SimpleProxyClientProvider; -import io.undertow.server.session.InMemorySessionManager; -import io.undertow.server.session.SessionAttachmentHandler; -import io.undertow.server.session.SessionCookieConfig; -import io.undertow.server.session.SessionManager; -import org.jboss.logging.Logger; -import org.keycloak.adapters.AdapterDeploymentContext; -import org.keycloak.adapters.KeycloakDeployment; -import org.keycloak.adapters.KeycloakDeploymentBuilder; -import org.keycloak.adapters.NodesRegistrationManagement; -import org.keycloak.adapters.undertow.UndertowAuthenticatedActionsHandler; -import org.keycloak.adapters.undertow.UndertowAuthenticationMechanism; -import org.keycloak.adapters.undertow.UndertowPreAuthActionsHandler; -import org.keycloak.adapters.undertow.UndertowUserSessionManagement; -import org.keycloak.common.enums.SslRequired; -import org.keycloak.common.util.CertificateUtils; -import org.keycloak.common.util.FindFile; -import org.keycloak.representations.adapters.config.AdapterConfig; -import org.keycloak.util.SystemPropertiesJsonParserFactory; -import org.xnio.Option; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ProxyServerBuilder { - protected static Logger log = Logger.getLogger(ProxyServerBuilder.class); - public static final HttpHandler NOT_FOUND = new HttpHandler() { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - exchange.setResponseCode(404); - exchange.endExchange(); - } - }; - - protected Undertow.Builder builder = Undertow.builder(); - - protected PathHandler root = new PathHandler(NOT_FOUND); - protected HttpHandler proxyHandler; - protected boolean sendAccessToken; - - protected Map headerNameConfig; - - public ProxyServerBuilder target(ProxyConfig config) { - SimpleProxyClientProvider provider = null; - try { - provider = new SimpleProxyClientProvider(new URI(config.getTargetUrl())); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - final HttpHandler handler = new ProxyHandler(provider, config.getTargetRequestTimeout(), ResponseCodeHandler.HANDLE_404); - proxyHandler = new HttpHandler() { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - exchange.setRelativePath(exchange.getRequestPath()); // need this otherwise proxy forwards to chopped off path - handler.handleRequest(exchange); - } - }; - return this; - } - - public ProxyServerBuilder sendAccessToken(boolean flag) { - this.sendAccessToken = flag; - return this; - } - - public ProxyServerBuilder headerNameConfig(Map headerNameConfig) { - this.headerNameConfig = headerNameConfig; - return this; - } - - public ApplicationBuilder application(AdapterConfig config) { - return new ApplicationBuilder(config); - } - - public class ApplicationBuilder { - protected NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement(); - protected UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement(); - protected AdapterDeploymentContext deploymentContext; - protected KeycloakDeployment deployment; - SessionManager sessionManager = new InMemorySessionManager( - "SESSION_MANAGER"); - protected String base; - protected SecurityPathMatches.Builder constraintBuilder = new SecurityPathMatches.Builder(); - protected SecurityPathMatches matches; - protected String errorPage; - protected boolean proxyAddressForwarding; - - public ApplicationBuilder base(String base) { - this.base = base; - return this; - } - - public ApplicationBuilder errorPage(String errorPage) { - if (errorPage != null && errorPage.startsWith("/")) { - errorPage = errorPage.substring(1); - } - this.errorPage = errorPage; - return this; - } - - public ApplicationBuilder proxyAddressForwarding(boolean proxyAddressForwarding) { - this.proxyAddressForwarding = proxyAddressForwarding; - return this; - } - - public ApplicationBuilder(AdapterConfig config) { - this.deployment = KeycloakDeploymentBuilder.build(config); - this.deploymentContext = new AdapterDeploymentContext(deployment); - } - - public ProxyServerBuilder add() { - matches = constraintBuilder.build(); - HttpHandler handler = sessionHandling(addSecurity(proxyHandler)); - root.addPrefixPath(base, handler); - return ProxyServerBuilder.this; - } - - public ConstraintBuilder constraint(String pattern) { - log.debugv("add constraint: {0}", pattern); - return new ConstraintBuilder(pattern); - } - - public class ConstraintBuilder { - protected String pattern; - protected Set rolesAllowed = new HashSet(); - protected Set methods = new HashSet(); - protected Set excludedMethods = new HashSet(); - protected SecurityInfo.EmptyRoleSemantic semantic = SecurityInfo.EmptyRoleSemantic.AUTHENTICATE; - - public ConstraintBuilder(String pattern) { - this.pattern = pattern; - - } - - public ConstraintBuilder deny() { - semantic = SecurityInfo.EmptyRoleSemantic.DENY; - return this; - } - public ConstraintBuilder permit() { - semantic = SecurityInfo.EmptyRoleSemantic.PERMIT; - return this; - } - public ConstraintBuilder authenticate() { - semantic = SecurityInfo.EmptyRoleSemantic.AUTHENTICATE; - return this; - } - - public ConstraintBuilder injectIfAuthenticated() { - semantic = SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED; - return this; - } - - public ConstraintBuilder excludedMethods(Set excludedMethods) { - this.excludedMethods = excludedMethods; - return this; - } - - public ConstraintBuilder methods(Set methods) { - this.methods = methods; - return this; - } - - public ConstraintBuilder method(String method) { - methods.add(method); - return this; - } - - public ConstraintBuilder excludeMethod(String method) { - excludedMethods.add(method); - return this; - } - - - public ConstraintBuilder roles(String... roles) { - for (String role : roles) role(role); - return this; - } - public ConstraintBuilder roles(Set roles) { - for (String role : roles) role(role); - return this; - } - - public ConstraintBuilder role(String role) { - rolesAllowed.add(role); - return this; - } - - public ApplicationBuilder add() { - constraintBuilder.addSecurityConstraint(rolesAllowed, semantic, pattern, methods, excludedMethods); - return ApplicationBuilder.this; - } - - - } - - private HttpHandler addSecurity(final HttpHandler toWrap) { - HttpHandler handler = new UndertowAuthenticatedActionsHandler(deploymentContext, toWrap); - if (errorPage != null) { - if (base.endsWith("/")) { - errorPage = base + errorPage; - } else { - errorPage = base + "/" + errorPage; - } - } - handler = new TokenRequestPreHandler(handler); - handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken, headerNameConfig); - handler = new ProxyAuthenticationCallHandler(handler); - handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage); - final List mechanisms = new LinkedList(); - mechanisms.add(new CachedAuthenticatedSessionMechanism()); - mechanisms.add(new UndertowAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, -1, null)); - handler = new AuthenticationMechanismsHandler(handler, mechanisms); - IdentityManager identityManager = new IdentityManager() { - @Override - public Account verify(Account account) { - return account; - } - - @Override - public Account verify(String id, Credential credential) { - throw new IllegalStateException("Should never be called in Keycloak flow"); - } - - @Override - public Account verify(Credential credential) { - throw new IllegalStateException("Should never be called in Keycloak flow"); - } - }; - handler = new UndertowPreAuthActionsHandler(deploymentContext, userSessionManagement, sessionManager, handler); - handler = new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler); - if (proxyAddressForwarding) handler = new ProxyPeerAddressHandler(handler); - return handler; - } - - private HttpHandler sessionHandling(HttpHandler toWrap) { - SessionCookieConfig sessionConfig = new SessionCookieConfig(); - sessionConfig.setCookieName("keycloak." + deployment.getResourceName() + ".session"); - sessionConfig.setPath(base); - if (deployment.getSslRequired() == SslRequired.ALL) sessionConfig.setSecure(true); - toWrap = new SessionAttachmentHandler( - toWrap, sessionManager, sessionConfig); - return toWrap; - } - - } - - - public Undertow build() { - builder.setHandler(root); - return builder.build(); - } - - public ProxyServerBuilder addHttpListener(int port, String host) { - builder.addHttpListener(port, host); - return this; - } - - public ProxyServerBuilder addHttpsListener(int port, String host, KeyManager[] keyManagers, TrustManager[] trustManagers) { - builder.addHttpsListener(port, host, keyManagers, trustManagers); - return this; - } - - public ProxyServerBuilder addHttpsListener(int port, String host, SSLContext sslContext) { - builder.addHttpsListener(port, host, sslContext); - return this; - } - - public ProxyServerBuilder setBufferSize(int bufferSize) { - builder.setBufferSize(bufferSize); - return this; - } - - public ProxyServerBuilder setBuffersPerRegion(int buffersPerRegion) { - builder.setBuffersPerRegion(buffersPerRegion); - return this; - } - - public ProxyServerBuilder setIoThreads(int ioThreads) { - builder.setIoThreads(ioThreads); - return this; - } - - public ProxyServerBuilder setWorkerThreads(int workerThreads) { - builder.setWorkerThreads(workerThreads); - return this; - } - - public ProxyServerBuilder setDirectBuffers(boolean directBuffers) { - builder.setDirectBuffers(directBuffers); - return this; - } - - public ProxyServerBuilder setServerOption(Option option, T value) { - builder.setServerOption(option, value); - return this; - } - - public ProxyServerBuilder setSocketOption(Option option, T value) { - builder.setSocketOption(option, value); - return this; - } - - public ProxyServerBuilder setWorkerOption(Option option, T value) { - builder.setWorkerOption(option, value); - return this; - } - - public static ProxyConfig loadConfig(InputStream is) { - ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory()); - mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); - ProxyConfig proxyConfig; - try { - proxyConfig = mapper.readValue(is, ProxyConfig.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - return proxyConfig; - } - public static Undertow build(InputStream configStream) { - ProxyConfig config = loadConfig(configStream); - return build(config); - - } - - public static Undertow build(ProxyConfig config) { - ProxyServerBuilder builder = new ProxyServerBuilder(); - if (config.getTargetUrl() == null) { - log.error("Must set Target URL"); - return null; - } - builder.target(config); - if (config.getApplications() == null || config.getApplications().size() == 0) { - log.error("No applications defined"); - return null; - } - initConnections(config, builder); - initOptions(config, builder); - - for (ProxyConfig.Application application : config.getApplications()) { - ApplicationBuilder applicationBuilder = builder.application(application.getAdapterConfig()) - .base(application.getBasePath()) - .errorPage(application.getErrorPage()) - .proxyAddressForwarding(application.isProxyAddressForwarding()); - - if (application.getConstraints() != null) { - for (ProxyConfig.Constraint constraint : application.getConstraints()) { - ApplicationBuilder.ConstraintBuilder constraintBuilder = applicationBuilder.constraint(constraint.getPattern()); - if (constraint.getRolesAllowed() != null) { - constraintBuilder.roles(constraint.getRolesAllowed()); - } - if (constraint.getMethods() != null) { - constraintBuilder.methods(constraint.getMethods()); - } - if (constraint.getExcludedMethods() != null) { - constraintBuilder.excludedMethods(constraint.getExcludedMethods()); - } - if (constraint.isDeny()) constraintBuilder.deny(); - if (constraint.isPermit()) constraintBuilder.permit(); - if (constraint.isAuthenticate()) constraintBuilder.authenticate(); - if (constraint.isPermitAndInject()) constraintBuilder.injectIfAuthenticated(); - constraintBuilder.add(); - } - } - applicationBuilder.add(); - } - return builder.build(); - } - - public static void initOptions(ProxyConfig config, ProxyServerBuilder builder) { - builder.sendAccessToken(config.isSendAccessToken()); - builder.headerNameConfig(config.getHeaderNames()); - if (config.getBufferSize() != null) builder.setBufferSize(config.getBufferSize()); - if (config.getBuffersPerRegion() != null) builder.setBuffersPerRegion(config.getBuffersPerRegion()); - if (config.getIoThreads() != null) builder.setIoThreads(config.getIoThreads()); - if (config.getWorkerThreads() != null) builder.setWorkerThreads(config.getWorkerThreads()); - if (config.getDirectBuffers() != null) builder.setDirectBuffers(config.getDirectBuffers()); - } - - public static void initConnections(ProxyConfig config, ProxyServerBuilder builder) { - if (config.getHttpPort() == null && config.getHttpsPort() == null) { - log.warn("You have not set up HTTP or HTTPS"); - } - if (config.getHttpPort() != null) { - String bindAddress = "localhost"; - if (config.getBindAddress() != null) bindAddress = config.getBindAddress(); - builder.addHttpListener(config.getHttpPort(), bindAddress); - } - if (config.getHttpsPort() != null) { - String bindAddress = "localhost"; - if (config.getBindAddress() != null) bindAddress = config.getBindAddress(); - if (config.getKeystore() != null) { - InputStream is = FindFile.findFile(config.getKeystore()); - SSLContext sslContext = null; - try { - KeyStore keystore = KeyStore.getInstance("jks"); - keystore.load(is, config.getKeystorePassword().toCharArray()); - sslContext = SslUtil.createSSLContext(keystore, config.getKeyPassword(), null); - } catch (Exception e) { - throw new RuntimeException(e); - } - builder.addHttpsListener(config.getHttpsPort().intValue(), bindAddress, sslContext); - } else { - log.warn("Generating temporary SSL cert"); - KeyPair keyPair = null; - try { - KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); - generator.initialize(2048); - keyPair = generator.generateKeyPair(); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - X509Certificate certificate = null; - try { - certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, bindAddress); - } catch (Exception e) { - throw new RuntimeException(e); - } - - try { - KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(null, null); - PrivateKey privateKey = keyPair.getPrivate(); - - - Certificate[] chain = {certificate}; - - keyStore.setKeyEntry(bindAddress, privateKey, "password".toCharArray(), chain); - SSLContext sslContext = SslUtil.createSSLContext(keyStore, "password", null); - builder.addHttpsListener(config.getHttpsPort().intValue(), bindAddress, sslContext); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SecurityInfo.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/SecurityInfo.java deleted file mode 100755 index 595e56d384..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SecurityInfo.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * @author Stuart Douglas - */ -public class SecurityInfo implements Cloneable { - - /** - * Equivalent to {@see ServletSecurity.EmptyRoleSemantic} but with an additional mode to require authentication but no role - * check. - */ - public enum EmptyRoleSemantic { - - /** - * Permit access to the resource without requiring authentication or role membership. - */ - PERMIT, - - /** - * Deny access to the resource regardless of the authentication state. - */ - DENY, - - /** - * Mandate authentication but authorize access as no roles to check against. - */ - AUTHENTICATE, - - /** - * Permit access in any case, but provide authorization info only if authorized. - */ - PERMIT_AND_INJECT_IF_AUTHENTICATED; - } - - private volatile EmptyRoleSemantic emptyRoleSemantic = EmptyRoleSemantic.DENY; - private final Set rolesAllowed = new HashSet(); - - public EmptyRoleSemantic getEmptyRoleSemantic() { - return emptyRoleSemantic; - } - - public T setEmptyRoleSemantic(final EmptyRoleSemantic emptyRoleSemantic) { - this.emptyRoleSemantic = emptyRoleSemantic; - return (T)this; - } - - public T addRoleAllowed(final String role) { - this.rolesAllowed.add(role); - return (T) this; - } - - public T addRolesAllowed(final String ... roles) { - this.rolesAllowed.addAll(Arrays.asList(roles)); - return (T) this; - } - public T addRolesAllowed(final Collection roles) { - this.rolesAllowed.addAll(roles); - return (T) this; - } - public Set getRolesAllowed() { - return new HashSet(rolesAllowed); - } - - @Override - public T clone() { - final SecurityInfo info = createInstance(); - info.emptyRoleSemantic = emptyRoleSemantic; - info.rolesAllowed.addAll(rolesAllowed); - return (T) info; - } - - protected T createInstance() { - return (T) new SecurityInfo(); - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SecurityPathMatches.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/SecurityPathMatches.java deleted file mode 100755 index b694041fa9..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SecurityPathMatches.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Stuart Douglas - */ -public class SecurityPathMatches { - - private final boolean denyUncoveredHttpMethods; - private final PathSecurityInformation defaultPathSecurityInformation; - private final Map exactPathRoleInformation; - private final Map prefixPathRoleInformation; - private final Map extensionRoleInformation; - - private SecurityPathMatches(final boolean denyUncoveredHttpMethods, final PathSecurityInformation defaultPathSecurityInformation, final Map exactPathRoleInformation, final Map prefixPathRoleInformation, final Map extensionRoleInformation) { - this.denyUncoveredHttpMethods = denyUncoveredHttpMethods; - this.defaultPathSecurityInformation = defaultPathSecurityInformation; - this.exactPathRoleInformation = exactPathRoleInformation; - this.prefixPathRoleInformation = prefixPathRoleInformation; - this.extensionRoleInformation = extensionRoleInformation; - } - - /** - * - * @return true If no security path information has been defined - */ - public boolean isEmpty() { - return defaultPathSecurityInformation.excludedMethodRoles.isEmpty() && - defaultPathSecurityInformation.perMethodRequiredRoles.isEmpty() && - defaultPathSecurityInformation.defaultRequiredRoles.isEmpty() && - exactPathRoleInformation.isEmpty() && - prefixPathRoleInformation.isEmpty() && - extensionRoleInformation.isEmpty(); - } - - public SingleConstraintMatch getSecurityInfo(final String path, final String method) { - RuntimeMatch currentMatch = new RuntimeMatch(); - handleMatch(method, defaultPathSecurityInformation, currentMatch); - PathSecurityInformation match = exactPathRoleInformation.get(path); - if (match != null) { - handleMatch(method, match, currentMatch); - return mergeConstraints(currentMatch); - } - - match = prefixPathRoleInformation.get(path); - if (match != null) { - handleMatch(method, match, currentMatch); - return mergeConstraints(currentMatch); - } - - int qsPos = -1; - boolean extension = false; - for (int i = path.length() - 1; i >= 0; --i) { - final char c = path.charAt(i); - if (c == '?') { - //there was a query string, check the exact matches again - final String part = path.substring(0, i); - match = exactPathRoleInformation.get(part); - if (match != null) { - handleMatch(method, match, currentMatch); - return mergeConstraints(currentMatch); - } - qsPos = i; - extension = false; - } else if (c == '/') { - extension = true; - final String part = path.substring(0, i); - match = prefixPathRoleInformation.get(part); - if (match != null) { - handleMatch(method, match, currentMatch); - return mergeConstraints(currentMatch); - } - } else if (c == '.') { - if (!extension) { - extension = true; - final String ext; - if (qsPos == -1) { - ext = path.substring(i + 1, path.length()); - } else { - ext = path.substring(i + 1, qsPos); - } - match = extensionRoleInformation.get(ext); - if (match != null) { - handleMatch(method, match, currentMatch); - return mergeConstraints(currentMatch); - } - } - } - } - return mergeConstraints(currentMatch); - } - - /** - * merge all constraints, as per 13.8.1 Combining Constraints - */ - private SingleConstraintMatch mergeConstraints(final RuntimeMatch currentMatch) { - if(currentMatch.uncovered && denyUncoveredHttpMethods) { - return new SingleConstraintMatch(SecurityInfo.EmptyRoleSemantic.DENY, Collections.emptySet()); - } - final Set allowedRoles = new HashSet(); - for(SingleConstraintMatch match : currentMatch.constraints) { - if(match.getRequiredRoles().isEmpty()) { - return new SingleConstraintMatch(match.getEmptyRoleSemantic(), Collections.emptySet()); - } else { - allowedRoles.addAll(match.getRequiredRoles()); - } - } - return new SingleConstraintMatch(SecurityInfo.EmptyRoleSemantic.PERMIT, allowedRoles); - } - - private void handleMatch(final String method, final PathSecurityInformation exact, RuntimeMatch currentMatch) { - List roles = exact.defaultRequiredRoles; - for (SecurityInformation role : roles) { - currentMatch.constraints.add(new SingleConstraintMatch(role.emptyRoleSemantic, role.roles)); - if(role.emptyRoleSemantic == SecurityInfo.EmptyRoleSemantic.DENY || !role.roles.isEmpty()) { - currentMatch.uncovered = false; - } - } - List methodInfo = exact.perMethodRequiredRoles.get(method); - if (methodInfo != null) { - currentMatch.uncovered = false; - for (SecurityInformation role : methodInfo) { - currentMatch.constraints.add(new SingleConstraintMatch(role.emptyRoleSemantic, role.roles)); - } - } - for (ExcludedMethodRoles excluded : exact.excludedMethodRoles) { - if (!excluded.methods.contains(method)) { - currentMatch.uncovered = false; - currentMatch.constraints.add(new SingleConstraintMatch(excluded.securityInformation.emptyRoleSemantic, excluded.securityInformation.roles)); - } - } - } - - public static class Builder { - private final PathSecurityInformation defaultPathSecurityInformation = new PathSecurityInformation(); - private final Map exactPathRoleInformation = new HashMap(); - private final Map prefixPathRoleInformation = new HashMap(); - private final Map extensionRoleInformation = new HashMap(); - - public void addSecurityConstraint(Set roles, SecurityInfo.EmptyRoleSemantic emptyRoleSemantic, String pattern, Set httpMethods, Set excludedMethods) { - final SecurityInformation securityInformation = new SecurityInformation(roles, emptyRoleSemantic); - if (pattern.endsWith("/*") || pattern.endsWith("/")) { - String part = pattern.substring(0, pattern.lastIndexOf('/')); - PathSecurityInformation info = prefixPathRoleInformation.get(part); - if (info == null) { - prefixPathRoleInformation.put(part, info = new PathSecurityInformation()); - } - setupPathSecurityInformation(info, securityInformation, httpMethods, excludedMethods); - } else if (pattern.startsWith("*.")) { - String part = pattern.substring(2, pattern.length()); - PathSecurityInformation info = extensionRoleInformation.get(part); - if (info == null) { - extensionRoleInformation.put(part, info = new PathSecurityInformation()); - } - setupPathSecurityInformation(info, securityInformation, httpMethods, excludedMethods); - } else { - PathSecurityInformation info = exactPathRoleInformation.get(pattern); - if (info == null) { - exactPathRoleInformation.put(pattern, info = new PathSecurityInformation()); - } - setupPathSecurityInformation(info, securityInformation, httpMethods, excludedMethods); - } - - } - - private Set expandRolesAllowed(final Set rolesAllowed) { - final Set roles = new HashSet(rolesAllowed); - return roles; - } - - private void setupPathSecurityInformation(final PathSecurityInformation info, final SecurityInformation securityConstraint, - Set httpMethods, Set excludedMethods) { - if (httpMethods.isEmpty() && - excludedMethods.isEmpty()) { - info.defaultRequiredRoles.add(securityConstraint); - } else if (!httpMethods.isEmpty()) { - for (String method : httpMethods) { - List securityInformations = info.perMethodRequiredRoles.get(method); - if (securityInformations == null) { - info.perMethodRequiredRoles.put(method, securityInformations = new ArrayList()); - } - securityInformations.add(securityConstraint); - } - } else if (!excludedMethods.isEmpty()) { - info.excludedMethodRoles.add(new ExcludedMethodRoles(excludedMethods, securityConstraint)); - } - } - - public SecurityPathMatches build() { - return new SecurityPathMatches(false, defaultPathSecurityInformation, exactPathRoleInformation, prefixPathRoleInformation, extensionRoleInformation); - } - } - - - private static class PathSecurityInformation { - final List defaultRequiredRoles = new ArrayList(); - final Map> perMethodRequiredRoles = new HashMap>(); - final List excludedMethodRoles = new ArrayList(); - } - - private static final class ExcludedMethodRoles { - final Set methods; - final SecurityInformation securityInformation; - - public ExcludedMethodRoles(final Set methods, final SecurityInformation securityInformation) { - this.methods = methods; - this.securityInformation = securityInformation; - } - } - - private static final class SecurityInformation { - final Set roles; - final SecurityInfo.EmptyRoleSemantic emptyRoleSemantic; - - private SecurityInformation(final Set roles, final SecurityInfo.EmptyRoleSemantic emptyRoleSemantic) { - this.emptyRoleSemantic = emptyRoleSemantic; - this.roles = new HashSet(roles); - } - } - - private static final class RuntimeMatch { - final List constraints = new ArrayList(); - boolean uncovered = true; - } -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SingleConstraintMatch.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/SingleConstraintMatch.java deleted file mode 100755 index ea48f2151f..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SingleConstraintMatch.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import java.util.Set; - -/** - * Representation of a single security constrain matched for a single request. - * - * When performing any authentication/authorization check every constraint MUST be satisfied for the request to be allowed to - * proceed. - * - * @author Darran Lofthouse - */ -public class SingleConstraintMatch { - - private final SecurityInfo.EmptyRoleSemantic emptyRoleSemantic; - private final Set requiredRoles; - - public SingleConstraintMatch(SecurityInfo.EmptyRoleSemantic emptyRoleSemantic, Set requiredRoles) { - this.emptyRoleSemantic = emptyRoleSemantic; - this.requiredRoles = requiredRoles; - } - - public SecurityInfo.EmptyRoleSemantic getEmptyRoleSemantic() { - return emptyRoleSemantic; - } - - public Set getRequiredRoles() { - return requiredRoles; - } - -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java deleted file mode 100755 index 40c271ec94..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.proxy; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import java.security.KeyStore; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class SslUtil { - public static SSLContext createSSLContext(final KeyStore keyStore, String password, final KeyStore trustStore) throws Exception { - KeyManager[] keyManagers; - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, password.toCharArray()); - keyManagers = keyManagerFactory.getKeyManagers(); - - TrustManager[] trustManagers = null; - if (trustStore != null) { - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(trustStore); - trustManagers = trustManagerFactory.getTrustManagers(); - } - - SSLContext sslContext; - sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyManagers, trustManagers, null); - - return sslContext; - } - - -} diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/TokenRequestPreHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/TokenRequestPreHandler.java deleted file mode 100644 index 312bd20023..0000000000 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/TokenRequestPreHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.keycloak.proxy; - -import io.undertow.server.HttpHandler; -import io.undertow.server.HttpServerExchange; -import org.keycloak.constants.AdapterConstants; - -/** - * Dispatches requests for k_query_bearer_token through a worker thread (handler for this - * resource performs blocking IO). - */ -public class TokenRequestPreHandler implements HttpHandler { - - private final HttpHandler next; - - public TokenRequestPreHandler(HttpHandler next) { - this.next = next; - } - - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - if (exchange.getRequestURI().endsWith(AdapterConstants.K_QUERY_BEARER_TOKEN)) { - exchange.dispatch(next); - } else { - next.handleRequest(exchange); - } - } -} diff --git a/testsuite/pom.xml b/testsuite/pom.xml index 6a74a707f5..4494f853c6 100755 --- a/testsuite/pom.xml +++ b/testsuite/pom.xml @@ -70,7 +70,6 @@ jetty - proxy tomcat7 diff --git a/testsuite/proxy/pom.xml b/testsuite/proxy/pom.xml deleted file mode 100755 index b6b2a8ef8f..0000000000 --- a/testsuite/proxy/pom.xml +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - keycloak-testsuite-pom - org.keycloak - 5.0.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - keycloak-testsuite-security-proxy - Keycloak Security Proxy TestSuite - - - 7.0.54 - - - - - - org.keycloak - keycloak-dependencies-server-all - pom - - - org.keycloak - keycloak-admin-client - - - org.keycloak - keycloak-proxy-server - - - log4j - log4j - - - org.jboss.spec.javax.servlet - jboss-servlet-api_3.0_spec - - - org.jboss.spec.javax.ws.rs - jboss-jaxrs-api_2.1_spec - - - org.jboss.resteasy - resteasy-jaxrs - - - org.jboss.resteasy - resteasy-client - - - org.jboss.resteasy - resteasy-multipart-provider - - - org.jboss.resteasy - resteasy-jackson2-provider - - - org.jboss.resteasy - resteasy-undertow - - - com.google.zxing - javase - - - org.bouncycastle - bcprov-jdk15on - - - org.apache.httpcomponents - httpclient - - - org.keycloak - keycloak-ldap-federation - - - org.keycloak - keycloak-kerberos-federation - - - org.keycloak - keycloak-undertow-adapter - - - org.keycloak - keycloak-tomcat7-adapter - - - org.jboss.logging - jboss-logging - - - io.undertow - undertow-servlet - - - io.undertow - undertow-core - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-annotations - - - junit - junit - - - org.hamcrest - hamcrest-all - - - com.h2database - h2 - - - com.icegreen - greenmail - - - org.slf4j - slf4j-api - - - - - org.infinispan - infinispan-core - - - org.seleniumhq.selenium - selenium-java - - - xml-apis - xml-apis - - - org.seleniumhq.selenium - selenium-chrome-driver - - - org.wildfly - wildfly-undertow - test - - - org.keycloak - keycloak-testsuite-integration-deprecated - test - - - org.keycloak - keycloak-testsuite-integration-deprecated - test-jar - test - - - - org.apache.tomcat - tomcat-catalina - ${tomcat.version} - - - org.apache.tomcat - tomcat-util - ${tomcat.version} - - - org.apache.tomcat.embed - tomcat-embed-core - ${tomcat.version} - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.2 - - - - test-jar - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.codehaus.mojo - exec-maven-plugin - - ${project.basedir} - - - - - - - - keycloak-server - - - - org.codehaus.mojo - exec-maven-plugin - - org.keycloak.testsuite.KeycloakServer - - - - - - - mail-server - - - - org.codehaus.mojo - exec-maven-plugin - - org.keycloak.testsuite.MailServer - - - - - - - totp - - - - org.codehaus.mojo - exec-maven-plugin - - org.keycloak.testsuite.TotpGenerator - - - - - - - - jpa - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - jpa - jpa - jpa - - - - - - - - - - - - keycloak.connectionsJpa.driver - com.mysql.jdbc.Driver - - - mysql - - - mysql - mysql-connector-java - ${mysql.version} - - - - - - - - - keycloak.connectionsJpa.driver - org.postgresql.Driver - - - postgresql - - - org.postgresql - postgresql - ${postgresql.version} - - - - - - clean-jpa - - - - org.liquibase - liquibase-maven-plugin - - META-INF/jpa-changelog-master.xml - - ${keycloak.connectionsJpa.url} - ${keycloak.connectionsJpa.driver} - ${keycloak.connectionsJpa.user} - ${keycloak.connectionsJpa.password} - - false - - - - clean-jpa - clean - - dropAll - - - - - - - - - diff --git a/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java b/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java deleted file mode 100755 index f7c2ecb8bb..0000000000 --- a/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed 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.keycloak.testsuite; - -import io.undertow.Undertow; -import org.apache.catalina.startup.Tomcat; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.keycloak.OAuth2Constants; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.protocol.oidc.OIDCLoginProtocolService; -import org.keycloak.proxy.ProxyServerBuilder; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.services.managers.RealmManager; -import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.rule.AbstractKeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.util.Enumeration; -import java.util.regex.Matcher; - -@Ignore -public class ProxyTest { - static String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth")) - .queryParam(OAuth2Constants.REDIRECT_URI, "http://localhost:8080/customer-portal").build("demo").toString(); - - @ClassRule - public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() { - @Override - protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) { - RealmRepresentation representation = KeycloakServer.loadJson(getClass().getResourceAsStream("/demorealm.json"), RealmRepresentation.class); - RealmModel realm = manager.importRealm(representation); - } - }; - - public static class SendUsernameServlet extends HttpServlet { - @Override - protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { - String requestURI = req.getRequestURI(); - resp.setContentType("text/plain"); - OutputStream stream = resp.getOutputStream(); - stream.write(req.getRequestURL().toString().getBytes()); - stream.write("\n".getBytes()); - Integer count = (Integer)req.getSession().getAttribute("counter"); - if (count == null) count = new Integer(0); - req.getSession().setAttribute("counter", new Integer(count.intValue() + 1)); - stream.write(("count:"+count).getBytes()); - - Enumeration headers = req.getHeaderNames(); - while (headers.hasMoreElements()) { - String name = headers.nextElement(); - System.out.println(name +": " + req.getHeader(name)); - } - - if (requestURI.contains("/bearer")) { - Client client = ClientBuilder.newClient(); - - try { - String appBase = "http://localhost:8080/customer-portal"; - WebTarget target = client.target(appBase + "/call-bearer"); - - Response response = null; - response = target.request() - .header(HttpHeaders.AUTHORIZATION, "Bearer CRAP") - .get(); - Assert.assertEquals(401, response.getStatus()); - response.close(); - response = target.request() - .header(HttpHeaders.AUTHORIZATION, "Bearer " + req.getHeader("KEYCLOAK_ACCESS_TOKEN")) - .get(); - Assert.assertEquals(200, response.getStatus()); - String data = response.readEntity(String.class); - response.close(); - stream.write(data.getBytes()); - } finally { - client.close(); - } - - } else if (requestURI.contains("/call-bearer")) { - stream.write("bearer called".getBytes()); - } - } - @Override - protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { - doGet(req, resp); - } - } - public static class SendError extends HttpServlet { - @Override - protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { - resp.setContentType("text/plain"); - OutputStream stream = resp.getOutputStream(); - stream.write("access error".getBytes()); - } - @Override - protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { - doGet(req, resp); - } - } - - static Tomcat tomcat = null; - - public static void initTomcat() throws Exception { - URL dir = ProxyTest.class.getResource("/tomcat-test/webapp/WEB-INF/web.xml"); - File webappDir = new File(dir.getFile()).getParentFile().getParentFile(); - tomcat = new Tomcat(); - String baseDir = getBaseDirectory(); - tomcat.setBaseDir(baseDir); - tomcat.setPort(8082); - - tomcat.addWebapp("/customer-portal", webappDir.toString()); - System.out.println("configuring app with basedir: " + webappDir.toString()); - - tomcat.start(); - //tomcat.getServer().await(); - } - - public static void shutdownTomcat() throws Exception { - tomcat.stop(); - tomcat.destroy(); - } - - static Undertow proxyServer = null; - - @BeforeClass - public static void initProxy() throws Exception { - initTomcat(); - InputStream is = ProxyTest.class.getResourceAsStream("/proxy-config.json"); - proxyServer = ProxyServerBuilder.build(is); - proxyServer.start(); - - } - - @AfterClass - public static void shutdownProxy() throws Exception { - shutdownTomcat(); - if (proxyServer != null) proxyServer.stop(); - } - - - @Rule - public WebRule webRule = new WebRule(this); - @WebResource - protected WebDriver driver; - @WebResource - protected LoginPage loginPage; - - public static final String LOGIN_URL = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString(); - - @Test - public void testHttp() throws Exception { - String baseUrl = "http://localhost:8080"; - testit(baseUrl); - - - } - - @Test - public void testHttps() throws Exception { - String baseUrl = "https://localhost:8443"; - testit(baseUrl); - - - } - - public void testit(String baseUrl) { - driver.navigate().to(baseUrl + "/customer-portal/users"); - System.out.println("Current url: " + driver.getCurrentUrl()); - Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL)); - String loginPageSource = driver.getPageSource(); - loginPage.login("bburke@redhat.com", "password"); - System.out.println("Current url: " + driver.getCurrentUrl()); - Assert.assertEquals(driver.getCurrentUrl(), baseUrl + "/customer-portal/users"); - String pageSource = driver.getPageSource(); - System.out.println(pageSource); - Assert.assertTrue(pageSource.contains("customer-portal/users")); - Assert.assertTrue(pageSource.contains("count:0")); - driver.navigate().to(baseUrl + "/customer-portal/users"); - Assert.assertEquals(driver.getCurrentUrl(), baseUrl + "/customer-portal/users"); - pageSource = driver.getPageSource(); - System.out.println(pageSource); - Assert.assertTrue(pageSource.contains("customer-portal/users")); - Assert.assertTrue(pageSource.contains("count:1")); // test http session - - driver.navigate().to(baseUrl + "/customer-portal/bearer"); - pageSource = driver.getPageSource(); - Assert.assertTrue(pageSource.contains("bearer called")); - - - driver.navigate().to(baseUrl + "/customer-portal/users/deny"); - Assert.assertEquals(driver.getCurrentUrl(), baseUrl + "/customer-portal/users/deny"); - pageSource = driver.getPageSource(); - System.out.println(pageSource); - Assert.assertTrue(pageSource.contains("access error")); - - driver.navigate().to(baseUrl + "/customer-portal/admins"); - Assert.assertEquals(driver.getCurrentUrl(), baseUrl + "/customer-portal/admins"); - pageSource = driver.getPageSource(); - System.out.println(pageSource); - Assert.assertTrue(pageSource.contains("access error")); - - - // test logout - - String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth")) - .queryParam(OAuth2Constants.REDIRECT_URI, baseUrl + "/customer-portal/users").build("demo").toString(); - driver.navigate().to(logoutUri); - Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL)); - driver.navigate().to(baseUrl + "/customer-portal/users"); - String currentUrl = driver.getCurrentUrl(); - Assert.assertTrue(currentUrl.startsWith(LOGIN_URL)); - - // test unsecured page - driver.navigate().to(baseUrl + "/customer-portal") ; - pageSource = driver.getPageSource(); - System.out.println(pageSource); - Assert.assertTrue(pageSource.contains("customer-portal")); - driver.navigate().to(baseUrl + "/customer-portal/users/permit") ; - pageSource = driver.getPageSource(); - System.out.println(pageSource); - Assert.assertTrue(pageSource.contains("customer-portal/users/permit")); - } - - private static String getBaseDirectory() { - String dirPath = null; - String relativeDirPath = "testsuite" + File.separator + "proxy" + File.separator + "target"; - - if (System.getProperties().containsKey("maven.home")) { - dirPath = System.getProperty("user.dir").replaceFirst("testsuite.proxy.*", Matcher.quoteReplacement(relativeDirPath)); - } else { - for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) { - if (c.contains(File.separator + "testsuite" + File.separator + "proxy")) { - dirPath = c.replaceFirst("testsuite.proxy.*", Matcher.quoteReplacement(relativeDirPath)); - break; - } - } - } - - String absolutePath = new File(dirPath).getAbsolutePath(); - return absolutePath; - } - - - - -} diff --git a/testsuite/proxy/src/test/resources/demorealm.json b/testsuite/proxy/src/test/resources/demorealm.json deleted file mode 100755 index 544bc1aaca..0000000000 --- a/testsuite/proxy/src/test/resources/demorealm.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "id": "demo", - "realm": "demo", - "enabled": true, - "accessTokenLifespan": 3000, - "accessCodeLifespan": 10, - "accessCodeLifespanUserAction": 6000, - "sslRequired": "external", - "registrationAllowed": false, - "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", - "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", - "requiredCredentials": [ "password" ], - "users" : [ - { - "username" : "bburke@redhat.com", - "enabled": true, - "email" : "bburke@redhat.com", - "firstName": "Bill", - "lastName": "Burke", - "credentials" : [ - { "type" : "password", - "value" : "password" } - ], - "realmRoles": [ "user" ], - "applicationRoles": { - "account": [ "manage-account" ] - } - }, - { - "username" : "admin", - "enabled": true, - "email" : "admin.burke@redhat.com", - "firstName": "Admin", - "lastName": "Burke", - "credentials" : [ - { "type" : "password", - "value" : "password" } - ], - "realmRoles": [ "user", "admin" ], - "applicationRoles": { - "account": [ "manage-account" ] - } - } - ], - "roles" : { - "realm" : [ - { - "name": "user", - "description": "User privileges" - }, - { - "name": "admin", - "description": "Administrator privileges" - } - ] - }, - "applications": [ - { - "name": "customer-portal", - "enabled": true, - "fullScopeAllowed": true, - "adminUrl": "http://localhost:8080/customer-portal", - "baseUrl": "http://localhost:8080/customer-portal", - "redirectUris": [ - "http://localhost:8080/customer-portal/*", - "https://localhost:8443/customer-portal/*" - ], - "secret": "password" - } - ] -} diff --git a/testsuite/proxy/src/test/resources/keycloak.json b/testsuite/proxy/src/test/resources/keycloak.json deleted file mode 100755 index b27fa4b983..0000000000 --- a/testsuite/proxy/src/test/resources/keycloak.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "realm": "demo", - "resource": "customer-portal", - "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", - "auth-server-url": "http://localhost:8081/auth", - "ssl-required" : "external", - "principal-attribute": "name", - "credentials": { - "secret": "password" - } -} diff --git a/testsuite/proxy/src/test/resources/proxy-config.json b/testsuite/proxy/src/test/resources/proxy-config.json deleted file mode 100755 index 1de7d6135c..0000000000 --- a/testsuite/proxy/src/test/resources/proxy-config.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "bind-address": "localhost", - "http-port": "8080", - "https-port": "8443", - "keystore": "classpath:ssl.jks", - "keystore-password": "password", - "key-password": "password", - "target-url": "http://localhost:8082", - "send-access-token": true, - "applications": [ - { - "base-path": "/customer-portal", - "error-page": "/error.html", - "adapter-config": { - "realm": "demo", - "resource": "customer-portal", - "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", - "auth-server-url": "http://localhost:8081/auth", - "ssl-required" : "external", - "principal-attribute": "name", - "credentials": { - "secret": "password" - } - } - , - "constraints": [ - { - "pattern": "/users/*", - "roles-allowed": [ - "user" - ] - }, - { - "pattern": "/call-bearer/*", - "roles-allowed": [ - "user" - ] - }, - { - "pattern": "/bearer/*", - "roles-allowed": [ - "user" - ] - }, - { - "pattern": "/admins/*", - "roles-allowed": [ - "admin" - ] - }, - { - "pattern": "/users/permit", - "permit": true - }, - { - "pattern": "/users/deny", - "deny": true - } - ] - } - ] - - -} \ No newline at end of file diff --git a/testsuite/proxy/src/test/resources/ssl.jks b/testsuite/proxy/src/test/resources/ssl.jks deleted file mode 100755 index 341ff486ac..0000000000 Binary files a/testsuite/proxy/src/test/resources/ssl.jks and /dev/null differ diff --git a/testsuite/proxy/src/test/resources/tomcat-test/webapp/WEB-INF/web.xml b/testsuite/proxy/src/test/resources/tomcat-test/webapp/WEB-INF/web.xml deleted file mode 100755 index b60b458794..0000000000 --- a/testsuite/proxy/src/test/resources/tomcat-test/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - adapter-test - - - SendUsername - org.keycloak.testsuite.ProxyTest$SendUsernameServlet - - - Error - org.keycloak.testsuite.ProxyTest$SendError - - - - Error - /error.html - - - SendUsername - /* - - - diff --git a/travis-run-tests.sh b/travis-run-tests.sh index b463bc6e0e..0b74db5485 100755 --- a/travis-run-tests.sh +++ b/travis-run-tests.sh @@ -53,7 +53,6 @@ if [ $1 == "old" ]; then cd testsuite mvn test -B -nsu -f integration-deprecated mvn test -B -nsu -f jetty - mvn test -B -nsu -f proxy mvn test -B -nsu -f tomcat7 mvn test -B -nsu -f tomcat8 fi @@ -102,4 +101,4 @@ if [ $1 == "crossdc-adapter" ]; then mvn clean test -B -nsu -Pcache-server-infinispan,auth-servers-crossdc-jboss,auth-server-wildfly,app-server-wildfly -Dtest=org.keycloak.testsuite.adapter.**.crossdc.**.* 2>&1 | java -cp ../../../utils/target/classes org.keycloak.testsuite.LogTrimmer exit ${PIPESTATUS[0]} -fi \ No newline at end of file +fi