KEYCLOAK-1385 Introduce end-of-line normalization

This commit is contained in:
Stian Thorgersen committed 2015-07-17 13:46:51 +02:00
1 parent be8aa93cca
commit 1642ac2394
888 files changed
+110680 -110660

No files matched your search

+43 -43
View File
@@ -1,43 +1,43 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>launcher</artifactId>
<name>Keycloak Launcher</name>
<description/>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.keycloak.Launcher</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>launcher</artifactId>
<name>Keycloak Launcher</name>
<description/>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.keycloak.Launcher</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,66 +1,66 @@
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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<URL> jars = new ArrayList<URL>();
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);
}
}
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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<URL> jars = new ArrayList<URL>();
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);
}
}
+31 -31
View File
@@ -1,31 +1,31 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Model Parent</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-proxy-pom</artifactId>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<modules>
<module>launcher</module>
<module>proxy-server</module>
</modules>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Model Parent</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-proxy-pom</artifactId>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<modules>
<module>launcher</module>
<module>proxy-server</module>
</modules>
</project>
+80 -80
View File
@@ -1,80 +1,80 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-proxy-server</artifactId>
<name>Keycloak Proxy Server</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-undertow-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-proxy-server</artifactId>
<name>Keycloak Proxy Server</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-undertow-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,107 +1,107 @@
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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<String, HttpString> httpHeaderNames;
protected HttpHandler next;
protected String errorPage;
protected boolean sendAccessToken;
public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken, Map<String, String> 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_SUBJECT, 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<String, String> 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);
}
}
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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<String, HttpString> httpHeaderNames;
protected HttpHandler next;
protected String errorPage;
protected boolean sendAccessToken;
public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken, Map<String, String> 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_SUBJECT, 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<String, String> 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);
}
}
@@ -1,89 +1,89 @@
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ConstraintMatcherHandler implements HttpHandler {
protected static Logger log = Logger.getLogger(ConstraintMatcherHandler.class);
public static final AttachmentKey<SingleConstraintMatch> 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<AuthenticationMechanism> 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;
}
}
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ConstraintMatcherHandler implements HttpHandler {
protected static Logger log = Logger.getLogger(ConstraintMatcherHandler.class);
public static final AttachmentKey<SingleConstraintMatch> 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<AuthenticationMechanism> 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;
}
}
@@ -1,28 +1,28 @@
package org.keycloak.proxy;
import io.undertow.Undertow;
import java.io.File;
import java.io.FileInputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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();
}
}
package org.keycloak.proxy;
import io.undertow.Undertow;
import java.io.File;
import java.io.FileInputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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();
}
}
@@ -1,35 +1,35 @@
package org.keycloak.proxy;
import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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();
}
}
}
package org.keycloak.proxy;
import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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();
}
}
}
@@ -1,289 +1,289 @@
package org.keycloak.proxy;
import org.codehaus.jackson.annotate.JsonProperty;
import org.keycloak.representations.adapters.config.AdapterConfig;
import java.util.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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;
@JsonProperty("send-access-token")
protected boolean sendAccessToken;
@JsonProperty("applications")
protected List<Application> applications = new LinkedList<Application>();
@JsonProperty("header-names")
private Map<String,String> 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 List<Application> getApplications() {
return applications;
}
public void setApplications(List<Application> applications) {
this.applications = applications;
}
public boolean isSendAccessToken() {
return sendAccessToken;
}
public void setSendAccessToken(boolean sendAccessToken) {
this.sendAccessToken = sendAccessToken;
}
public void setHeaderNames(Map<String, String> headerNames) {
this.headerNames = headerNames;
}
public Map<String, String> 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("constraints")
protected List<Constraint> constraints = new LinkedList<Constraint>();
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 List<Constraint> getConstraints() {
return constraints;
}
public void setConstraints(List<Constraint> constraints) {
this.constraints = constraints;
}
}
public static class Constraint {
@JsonProperty("pattern")
protected String pattern;
@JsonProperty("roles-allowed")
protected Set<String> rolesAllowed = new HashSet<String>();
@JsonProperty("methods")
protected Set<String> methods = new HashSet<String>();
@JsonProperty("excluded-methods")
protected Set<String> excludedMethods = new HashSet<String>();
@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<String> getRolesAllowed() {
return rolesAllowed;
}
public void setRolesAllowed(Set<String> 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<String> getMethods() {
return methods;
}
public void setMethods(Set<String> methods) {
this.methods = methods;
}
public Set<String> getExcludedMethods() {
return excludedMethods;
}
public void setExcludedMethods(Set<String> excludedMethods) {
this.excludedMethods = excludedMethods;
}
}
}
package org.keycloak.proxy;
import org.codehaus.jackson.annotate.JsonProperty;
import org.keycloak.representations.adapters.config.AdapterConfig;
import java.util.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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;
@JsonProperty("send-access-token")
protected boolean sendAccessToken;
@JsonProperty("applications")
protected List<Application> applications = new LinkedList<Application>();
@JsonProperty("header-names")
private Map<String,String> 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 List<Application> getApplications() {
return applications;
}
public void setApplications(List<Application> applications) {
this.applications = applications;
}
public boolean isSendAccessToken() {
return sendAccessToken;
}
public void setSendAccessToken(boolean sendAccessToken) {
this.sendAccessToken = sendAccessToken;
}
public void setHeaderNames(Map<String, String> headerNames) {
this.headerNames = headerNames;
}
public Map<String, String> 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("constraints")
protected List<Constraint> constraints = new LinkedList<Constraint>();
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 List<Constraint> getConstraints() {
return constraints;
}
public void setConstraints(List<Constraint> constraints) {
this.constraints = constraints;
}
}
public static class Constraint {
@JsonProperty("pattern")
protected String pattern;
@JsonProperty("roles-allowed")
protected Set<String> rolesAllowed = new HashSet<String>();
@JsonProperty("methods")
protected Set<String> methods = new HashSet<String>();
@JsonProperty("excluded-methods")
protected Set<String> excludedMethods = new HashSet<String>();
@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<String> getRolesAllowed() {
return rolesAllowed;
}
public void setRolesAllowed(Set<String> 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<String> getMethods() {
return methods;
}
public void setMethods(Set<String> methods) {
this.methods = methods;
}
public Set<String> getExcludedMethods() {
return excludedMethods;
}
public void setExcludedMethods(Set<String> excludedMethods) {
this.excludedMethods = excludedMethods;
}
}
}
@@ -1,462 +1,462 @@
package org.keycloak.proxy;
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.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.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.jboss.logging.Logger;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.util.FindFile;
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.enums.SslRequired;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.util.CertificateUtils;
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.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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<String, String> headerNameConfig;
public ProxyServerBuilder target(String uri) {
SimpleProxyClientProvider provider = null;
try {
provider = new SimpleProxyClientProvider(new URI(uri));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
final HttpHandler handler = new ProxyHandler(provider, 30000, 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<String, String> 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;
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(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<String> rolesAllowed = new HashSet<String>();
protected Set<String> methods = new HashSet<String>();
protected Set<String> excludedMethods = new HashSet<String>();
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<String> excludedMethods) {
this.excludedMethods = excludedMethods;
return this;
}
public ConstraintBuilder methods(Set<String> 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<String> 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 = toWrap;
handler = new UndertowAuthenticatedActionsHandler(deploymentContext, toWrap);
if (errorPage != null) {
if (base.endsWith("/")) {
errorPage = base + errorPage;
} else {
errorPage = base + "/" + errorPage;
}
}
handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken, headerNameConfig);
handler = new ProxyAuthenticationCallHandler(handler);
handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
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);
return new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, 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 <T> ProxyServerBuilder setServerOption(Option<T> option, T value) {
builder.setServerOption(option, value);
return this;
}
public <T> ProxyServerBuilder setSocketOption(Option<T> option, T value) {
builder.setSocketOption(option, value);
return this;
}
public <T> ProxyServerBuilder setWorkerOption(Option<T> option, T value) {
builder.setWorkerOption(option, value);
return this;
}
public static ProxyConfig loadConfig(InputStream is) {
ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
mapper.setSerializationInclusion(JsonSerialize.Inclusion.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.getTargetUrl());
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());
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);
}
}
}
}
}
package org.keycloak.proxy;
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.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.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.jboss.logging.Logger;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.util.FindFile;
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.enums.SslRequired;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.util.CertificateUtils;
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.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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<String, String> headerNameConfig;
public ProxyServerBuilder target(String uri) {
SimpleProxyClientProvider provider = null;
try {
provider = new SimpleProxyClientProvider(new URI(uri));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
final HttpHandler handler = new ProxyHandler(provider, 30000, 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<String, String> 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;
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(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<String> rolesAllowed = new HashSet<String>();
protected Set<String> methods = new HashSet<String>();
protected Set<String> excludedMethods = new HashSet<String>();
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<String> excludedMethods) {
this.excludedMethods = excludedMethods;
return this;
}
public ConstraintBuilder methods(Set<String> 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<String> 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 = toWrap;
handler = new UndertowAuthenticatedActionsHandler(deploymentContext, toWrap);
if (errorPage != null) {
if (base.endsWith("/")) {
errorPage = base + errorPage;
} else {
errorPage = base + "/" + errorPage;
}
}
handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken, headerNameConfig);
handler = new ProxyAuthenticationCallHandler(handler);
handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
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);
return new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, 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 <T> ProxyServerBuilder setServerOption(Option<T> option, T value) {
builder.setServerOption(option, value);
return this;
}
public <T> ProxyServerBuilder setSocketOption(Option<T> option, T value) {
builder.setSocketOption(option, value);
return this;
}
public <T> ProxyServerBuilder setWorkerOption(Option<T> option, T value) {
builder.setWorkerOption(option, value);
return this;
}
public static ProxyConfig loadConfig(InputStream is) {
ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
mapper.setSerializationInclusion(JsonSerialize.Inclusion.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.getTargetUrl());
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());
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);
}
}
}
}
}
@@ -1,36 +1,36 @@
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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;
}
}
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @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;
}
}