Merge pull request #2507 from mposolda/master

KEYCLOAK-2623 Remove auth-server-url-for-backend-requests from adapters
This commit is contained in:
Marek Posolda 2016-04-05 13:09:47 +02:00
commit 17b84df631
42 changed files with 45 additions and 1648 deletions

View file

@ -169,11 +169,7 @@ public class AdapterDeploymentContext {
public void setAuthServerBaseUrl(String authServerBaseUrl) { public void setAuthServerBaseUrl(String authServerBaseUrl) {
this.authServerBaseUrl = authServerBaseUrl; this.authServerBaseUrl = authServerBaseUrl;
KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl); KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
resolveBrowserUrls(serverBuilder); resolveUrls(serverBuilder);
if (delegate.getRelativeUrls() == RelativeUrlsUsed.ALL_REQUESTS) {
resolveNonBrowserUrls(serverBuilder);
}
} }
@Override @Override

View file

@ -38,37 +38,6 @@ public class AdapterUtils {
return UUID.randomUUID().toString(); return UUID.randomUUID().toString();
} }
/**
* Best effort to find origin for REST request calls from web UI application to REST application. In case of relative or absolute
* "auth-server-url" is returned the URL from request. In case of "auth-server-url-for-backend-request" used in configuration, it returns
* the origin of auth server.
*
* This may be the optimization in cluster, so if you have keycloak and applications on same host, the REST request doesn't need to
* go through loadbalancer, but can be sent directly to same host.
*
* @param browserRequestURL
* @param session
* @return
*/
public static String getOriginForRestCalls(String browserRequestURL, KeycloakSecurityContext session) {
if (session instanceof RefreshableKeycloakSecurityContext) {
KeycloakDeployment deployment = ((RefreshableKeycloakSecurityContext)session).getDeployment();
switch (deployment.getRelativeUrls()) {
case ALL_REQUESTS:
case NEVER:
// Resolve baseURI from the request
return UriUtils.getOrigin(browserRequestURL);
case BROWSER_ONLY:
// Resolve baseURI from the codeURL (This is already non-relative and based on our hostname)
return UriUtils.getOrigin(deployment.getTokenUrl());
default:
return "";
}
} else {
return UriUtils.getOrigin(browserRequestURL);
}
}
public static Set<String> getRolesFromSecurityContext(RefreshableKeycloakSecurityContext session) { public static Set<String> getRolesFromSecurityContext(RefreshableKeycloakSecurityContext session) {
Set<String> roles = null; Set<String> roles = null;
AccessToken accessToken = session.getToken(); AccessToken accessToken = session.getToken();

View file

@ -111,39 +111,17 @@ public class KeycloakDeployment {
public void setAuthServerBaseUrl(AdapterConfig config) { public void setAuthServerBaseUrl(AdapterConfig config) {
this.authServerBaseUrl = config.getAuthServerUrl(); this.authServerBaseUrl = config.getAuthServerUrl();
String authServerURLForBackendReqs = config.getAuthServerUrlForBackendRequests(); if (authServerBaseUrl == null) return;
if (authServerBaseUrl == null && authServerURLForBackendReqs == null) return;
URI authServerUri = null; URI authServerUri = URI.create(authServerBaseUrl);
if (authServerBaseUrl != null) {
authServerUri = URI.create(authServerBaseUrl);
}
if (authServerUri == null || authServerUri.getHost() == null) { if (authServerUri.getHost() == null) {
if (authServerURLForBackendReqs != null) { relativeUrls = RelativeUrlsUsed.ALWAYS;
relativeUrls = RelativeUrlsUsed.BROWSER_ONLY;
KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerURLForBackendReqs);
if (serverBuilder.getHost() == null || serverBuilder.getScheme() == null) {
throw new IllegalStateException("Relative URL not supported for auth-server-url-for-backend-requests option. URL used: "
+ authServerURLForBackendReqs + ", Client: " + config.getResource());
}
resolveNonBrowserUrls(serverBuilder);
} else {
relativeUrls = RelativeUrlsUsed.ALL_REQUESTS;
}
} else { } else {
// We have absolute URI in config // We have absolute URI in config
relativeUrls = RelativeUrlsUsed.NEVER; relativeUrls = RelativeUrlsUsed.NEVER;
KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl); KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
resolveBrowserUrls(serverBuilder); resolveUrls(serverBuilder);
if (authServerURLForBackendReqs == null) {
resolveNonBrowserUrls(serverBuilder);
} else {
serverBuilder = KeycloakUriBuilder.fromUri(authServerURLForBackendReqs);
resolveNonBrowserUrls(serverBuilder);
}
} }
} }
@ -152,23 +130,14 @@ public class KeycloakDeployment {
/** /**
* @param authUrlBuilder absolute URI * @param authUrlBuilder absolute URI
*/ */
protected void resolveBrowserUrls(KeycloakUriBuilder authUrlBuilder) { protected void resolveUrls(KeycloakUriBuilder authUrlBuilder) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("resolveBrowserUrls"); log.debug("resolveUrls");
} }
String login = authUrlBuilder.clone().path(ServiceUrlConstants.AUTH_PATH).build(getRealm()).toString(); String login = authUrlBuilder.clone().path(ServiceUrlConstants.AUTH_PATH).build(getRealm()).toString();
authUrl = KeycloakUriBuilder.fromUri(login); authUrl = KeycloakUriBuilder.fromUri(login);
realmInfoUrl = authUrlBuilder.clone().path(ServiceUrlConstants.REALM_INFO_PATH).build(getRealm()).toString(); realmInfoUrl = authUrlBuilder.clone().path(ServiceUrlConstants.REALM_INFO_PATH).build(getRealm()).toString();
}
/**
* @param authUrlBuilder absolute URI
*/
protected void resolveNonBrowserUrls(KeycloakUriBuilder authUrlBuilder) {
if (log.isDebugEnabled()) {
log.debug("resolveNonBrowserUrls");
}
tokenUrl = authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_PATH).build(getRealm()).toString(); tokenUrl = authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_PATH).build(getRealm()).toString();
logoutUrl = KeycloakUriBuilder.fromUri(authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).build(getRealm()).toString()); logoutUrl = KeycloakUriBuilder.fromUri(authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).build(getRealm()).toString());

View file

@ -54,7 +54,7 @@ public class KeycloakDeploymentBuilderTest {
assertEquals("234234-234234-234234", deployment.getResourceCredentials().get("secret")); assertEquals("234234-234234-234234", deployment.getResourceCredentials().get("secret"));
assertEquals(ClientIdAndSecretCredentialsProvider.PROVIDER_ID, deployment.getClientAuthenticator().getId()); assertEquals(ClientIdAndSecretCredentialsProvider.PROVIDER_ID, deployment.getClientAuthenticator().getId());
assertEquals(20, ((ThreadSafeClientConnManager) deployment.getClient().getConnectionManager()).getMaxTotal()); assertEquals(20, ((ThreadSafeClientConnManager) deployment.getClient().getConnectionManager()).getMaxTotal());
assertEquals("https://backend:8443/auth/realms/demo/protocol/openid-connect/token", deployment.getTokenUrl()); assertEquals("https://localhost:8443/auth/realms/demo/protocol/openid-connect/token", deployment.getTokenUrl());
assertEquals(RelativeUrlsUsed.NEVER, deployment.getRelativeUrls()); assertEquals(RelativeUrlsUsed.NEVER, deployment.getRelativeUrls());
assertTrue(deployment.isAlwaysRefreshToken()); assertTrue(deployment.isAlwaysRefreshToken());
assertTrue(deployment.isRegisterNodeAtStartup()); assertTrue(deployment.isRegisterNodeAtStartup());

View file

@ -24,7 +24,6 @@
"client-keystore": "classpath:/keystore.jks", "client-keystore": "classpath:/keystore.jks",
"client-keystore-password": "storepass", "client-keystore-password": "storepass",
"client-key-password": "keypass", "client-key-password": "keypass",
"auth-server-url-for-backend-requests": "https://backend:8443/auth",
"always-refresh-token": true, "always-refresh-token": true,
"register-node-at-startup": true, "register-node-at-startup": true,
"register-node-period": 1000, "register-node-period": 1000,

View file

@ -33,7 +33,7 @@ public class ServletOAuthClientBuilderTest {
public void testBuilder() { public void testBuilder() {
ServletOAuthClient oauthClient = ServletOAuthClientBuilder.build(getClass().getResourceAsStream("/keycloak.json")); ServletOAuthClient oauthClient = ServletOAuthClientBuilder.build(getClass().getResourceAsStream("/keycloak.json"));
Assert.assertEquals("https://localhost:8443/auth/realms/demo/protocol/openid-connect/auth", oauthClient.getDeployment().getAuthUrl().clone().build().toString()); Assert.assertEquals("https://localhost:8443/auth/realms/demo/protocol/openid-connect/auth", oauthClient.getDeployment().getAuthUrl().clone().build().toString());
Assert.assertEquals("https://backend:8443/auth/realms/demo/protocol/openid-connect/token", oauthClient.getDeployment().getTokenUrl()); Assert.assertEquals("https://localhost:8443/auth/realms/demo/protocol/openid-connect/token", oauthClient.getDeployment().getTokenUrl());
assertEquals(RelativeUrlsUsed.NEVER, oauthClient.getRelativeUrlsUsed()); assertEquals(RelativeUrlsUsed.NEVER, oauthClient.getRelativeUrlsUsed());
Assert.assertEquals("customer-portal", oauthClient.getClientId()); Assert.assertEquals("customer-portal", oauthClient.getClientId());
Assert.assertEquals("234234-234234-234234", oauthClient.getCredentials().get(CredentialRepresentation.SECRET)); Assert.assertEquals("234234-234234-234234", oauthClient.getCredentials().get(CredentialRepresentation.SECRET));

View file

@ -19,7 +19,6 @@
"connection-pool-size": 20, "connection-pool-size": 20,
"disable-trust-manager": true, "disable-trust-manager": true,
"allow-any-hostname": true, "allow-any-hostname": true,
"auth-server-url-for-backend-requests": "https://backend:8443/auth",
"always-refresh-token": true, "always-refresh-token": true,
"register-node-at-startup": true, "register-node-at-startup": true,
"register-node-period": 1000, "register-node-period": 1000,

View file

@ -25,29 +25,10 @@ public enum RelativeUrlsUsed {
/** /**
* Always use relative URI and resolve them later based on browser HTTP request * Always use relative URI and resolve them later based on browser HTTP request
*/ */
ALL_REQUESTS, ALWAYS,
/**
* Use relative Uris just for browser requests and resolve those based on browser HTTP requests.
* Backend request (like refresh token request, codeToToken request etc) will use the URI based on current hostname
*/
BROWSER_ONLY,
/** /**
* Relative Uri not used. Configuration contains absolute URI * Relative Uri not used. Configuration contains absolute URI
*/ */
NEVER; NEVER;
public boolean useRelative(boolean isBrowserReq) {
switch (this) {
case ALL_REQUESTS:
return true;
case NEVER:
return false;
case BROWSER_ONLY:
return isBrowserReq;
default:
return true;
}
}
} }

View file

@ -34,7 +34,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
"connection-pool-size", "connection-pool-size",
"allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password", "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
"client-keystore", "client-keystore-password", "client-key-password", "client-keystore", "client-keystore-password", "client-key-password",
"auth-server-url-for-backend-requests", "always-refresh-token", "always-refresh-token",
"register-node-at-startup", "register-node-period", "token-store", "principal-attribute" "register-node-at-startup", "register-node-period", "token-store", "principal-attribute"
}) })
public class AdapterConfig extends BaseAdapterConfig { public class AdapterConfig extends BaseAdapterConfig {
@ -55,8 +55,6 @@ public class AdapterConfig extends BaseAdapterConfig {
protected String clientKeyPassword; protected String clientKeyPassword;
@JsonProperty("connection-pool-size") @JsonProperty("connection-pool-size")
protected int connectionPoolSize = 20; protected int connectionPoolSize = 20;
@JsonProperty("auth-server-url-for-backend-requests")
protected String authServerUrlForBackendRequests;
@JsonProperty("always-refresh-token") @JsonProperty("always-refresh-token")
protected boolean alwaysRefreshToken = false; protected boolean alwaysRefreshToken = false;
@JsonProperty("register-node-at-startup") @JsonProperty("register-node-at-startup")
@ -134,14 +132,6 @@ public class AdapterConfig extends BaseAdapterConfig {
this.connectionPoolSize = connectionPoolSize; this.connectionPoolSize = connectionPoolSize;
} }
public String getAuthServerUrlForBackendRequests() {
return authServerUrlForBackendRequests;
}
public void setAuthServerUrlForBackendRequests(String authServerUrlForBackendRequests) {
this.authServerUrlForBackendRequests = authServerUrlForBackendRequests;
}
public boolean isAlwaysRefreshToken() { public boolean isAlwaysRefreshToken() {
return alwaysRefreshToken; return alwaysRefreshToken;
} }

View file

@ -96,6 +96,23 @@
<section> <section>
<title>Version specific migration</title> <title>Version specific migration</title>
<section>
<title>Migrating to 1.9.2</title>
<simplesect>
<title>Adapter option auth-server-url-for-backend-requests removed</title>
<para>
We've removed the option <literal>auth-server-url-for-backend-requests</literal> as there were issues in some scenarios when it was used.
In more details, it was possible to access the Keycloak server from 2 different contexts (internal and external), which was
causing issues in token validations etc.
</para>
<para>
If you still want to use the optimization of network, which this option provided (avoid the application to send backchannel requests
through loadbalancer but send them to local Keycloak server directly) you may need to handle it at hosts configuration (DNS) level.
</para>
</simplesect>
</section>
<section> <section>
<title>Migrating to 1.9.0</title> <title>Migrating to 1.9.0</title>
<simplesect> <simplesect>

View file

@ -102,39 +102,6 @@
</para> </para>
</section> </section>
<section id="relative-uri-optimization">
<title>Relative URI optimization</title>
<para>
In many deployment scenarios will be Keycloak and secured applications deployed on same cluster hosts. For this case Keycloak
already provides option to use relative URI as value of option <emphasis>auth-server-url</emphasis> in <literal>WEB-INF/keycloak.json</literal> .
In this case, the URI of Keycloak server is resolved from the URI of current request.
</para>
<para>
For example if your loadbalancer is on <emphasis>https://loadbalancer.com/myapp</emphasis> and auth-server-url is <emphasis>/auth</emphasis>,
then relative URI of Keycloak is resolved to be <emphasis>https://loadbalancer.com/auth</emphasis> .
</para>
<para>
For cluster setup, it may be even better to use option <emphasis>auth-server-url-for-backend-request</emphasis> . This allows to configure
that backend requests between Keycloak and your application will be sent directly to same cluster host without additional
round-trip through loadbalancer. So for this, it's good to configure values in <literal>WEB-INF/keycloak.json</literal> like this:
<programlisting>
<![CDATA[
"auth-server-url": "/auth",
"auth-server-url-for-backend-requests": "http://${jboss.host.name}:8080/auth"
]]>
</programlisting>
</para>
<para>
This would mean that browser requests (like redirecting to Keycloak login screen) will be still resolved relatively
to current request URI like <emphasis>https://loadbalancer.com/myapp</emphasis>, but backend (out-of-bound) requests between keycloak
and your app are sent always to same cluster host with application .
</para>
<para>
Note that additionally to network optimization,
you may not need "https" in this case as application and keycloak are communicating directly within same cluster host.
</para>
</section>
<section id="admin-url-configuration"> <section id="admin-url-configuration">
<title>Admin URL configuration</title> <title>Admin URL configuration</title>
<para> <para>

View file

@ -30,7 +30,6 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.constants.ServiceUrlConstants; import org.keycloak.constants.ServiceUrlConstants;
import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.common.util.HostUtils;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import org.keycloak.common.util.KeycloakUriBuilder; import org.keycloak.common.util.KeycloakUriBuilder;
import org.keycloak.common.util.UriUtils; import org.keycloak.common.util.UriUtils;
@ -91,7 +90,7 @@ public class AdminClient {
try { try {
HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth") HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getRequestOrigin(request) + "/auth")
.path(ServiceUrlConstants.TOKEN_PATH).build("demo")); .path(ServiceUrlConstants.TOKEN_PATH).build("demo"));
List <NameValuePair> formparams = new ArrayList <NameValuePair>(); List <NameValuePair> formparams = new ArrayList <NameValuePair>();
formparams.add(new BasicNameValuePair("username", "admin")); formparams.add(new BasicNameValuePair("username", "admin"));
@ -124,7 +123,7 @@ public class AdminClient {
try { try {
HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth") HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(UriUtils.getOrigin(request.getRequestURL().toString()) + "/auth")
.path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH) .path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
.build("demo")); .build("demo"));
List<NameValuePair> formparams = new ArrayList<NameValuePair>(); List<NameValuePair> formparams = new ArrayList<NameValuePair>();
@ -152,7 +151,7 @@ public class AdminClient {
HttpClient client = new DefaultHttpClient(); HttpClient client = new DefaultHttpClient();
try { try {
HttpGet get = new HttpGet(getBaseUrl(request) + "/auth/admin/realms/demo/roles"); HttpGet get = new HttpGet(UriUtils.getOrigin(request.getRequestURL().toString()) + "/auth/admin/realms/demo/roles");
get.addHeader("Authorization", "Bearer " + res.getToken()); get.addHeader("Authorization", "Bearer " + res.getToken());
try { try {
HttpResponse response = client.execute(get); HttpResponse response = client.execute(get);
@ -174,13 +173,8 @@ public class AdminClient {
} }
} }
public static String getBaseUrl(HttpServletRequest request) { public static String getRequestOrigin(HttpServletRequest request) {
String useHostname = request.getServletContext().getInitParameter("useHostname"); return UriUtils.getOrigin(request.getRequestURL().toString());
if (useHostname != null && "true".equalsIgnoreCase(useHostname)) {
return "http://" + HostUtils.getHostName() + ":8080";
} else {
return UriUtils.getOrigin(request.getRequestURL().toString());
}
} }
} }

View file

@ -23,9 +23,4 @@
<module-name>admin-access</module-name> <module-name>admin-access</module-name>
<context-param>
<param-name>useHostname</param-name>
<param-value>false</param-value>
</context-param>
</web-app> </web-app>

View file

@ -23,7 +23,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils; import org.keycloak.common.util.UriUtils;
import org.keycloak.representations.IDToken; import org.keycloak.representations.IDToken;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
@ -66,7 +66,7 @@ public class CustomerDatabaseClient {
HttpClient client = new DefaultHttpClient(); HttpClient client = new DefaultHttpClient();
try { try {
HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/customers"); HttpGet get = new HttpGet(UriUtils.getOrigin(req.getRequestURL().toString()) + "/database/customers");
get.addHeader("Authorization", "Bearer " + session.getTokenString()); get.addHeader("Authorization", "Bearer " + session.getTokenString());
try { try {
HttpResponse response = client.execute(get); HttpResponse response = client.execute(get);

View file

@ -23,7 +23,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils; import org.keycloak.common.util.UriUtils;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
@ -59,7 +59,7 @@ public class AdminClient {
HttpClient client = new DefaultHttpClient(); HttpClient client = new DefaultHttpClient();
try { try {
HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/auth/admin/realms/demo/roles"); HttpGet get = new HttpGet(UriUtils.getOrigin(req.getRequestURL().toString()) + "/auth/admin/realms/demo/roles");
get.addHeader("Authorization", "Bearer " + session.getTokenString()); get.addHeader("Authorization", "Bearer " + session.getTokenString());
try { try {
HttpResponse response = client.execute(get); HttpResponse response = client.execute(get);

View file

@ -23,7 +23,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils; import org.keycloak.common.util.UriUtils;
import org.keycloak.representations.IDToken; import org.keycloak.representations.IDToken;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
@ -66,7 +66,7 @@ public class CustomerDatabaseClient {
HttpClient client = new DefaultHttpClient(); HttpClient client = new DefaultHttpClient();
try { try {
HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/customers"); HttpGet get = new HttpGet(UriUtils.getOrigin(req.getRequestURL().toString()) + "/database/customers");
get.addHeader("Authorization", "Bearer " + session.getTokenString()); get.addHeader("Authorization", "Bearer " + session.getTokenString());
try { try {
HttpResponse response = client.execute(get); HttpResponse response = client.execute(get);

View file

@ -23,7 +23,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils; import org.keycloak.common.util.UriUtils;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -57,7 +57,7 @@ public class ProductDatabaseClient
HttpClient client = new DefaultHttpClient(); HttpClient client = new DefaultHttpClient();
try { try {
HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/products"); HttpGet get = new HttpGet(UriUtils.getOrigin(req.getRequestURL().toString()) + "/database/products");
get.addHeader("Authorization", "Bearer " + session.getTokenString()); get.addHeader("Authorization", "Bearer " + session.getTokenString());
try { try {
HttpResponse response = client.execute(get); HttpResponse response = client.execute(get);

View file

@ -24,7 +24,7 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils; import org.keycloak.common.util.UriUtils;
import org.keycloak.servlet.ServletOAuthClient; import org.keycloak.servlet.ServletOAuthClient;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
@ -123,7 +123,7 @@ public class DatabaseClient {
public String getBaseUrl() { public String getBaseUrl() {
KeycloakSecurityContext session = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); KeycloakSecurityContext session = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
return AdapterUtils.getOriginForRestCalls(request.getRequestURL().toString(), session); return UriUtils.getOrigin(request.getRequestURL().toString());
} }
} }

View file

@ -23,7 +23,6 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils;
import org.keycloak.adapters.ServerRequest; import org.keycloak.adapters.ServerRequest;
import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.servlet.ServletOAuthClient; import org.keycloak.servlet.ServletOAuthClient;
@ -100,7 +99,7 @@ public class ProductDatabaseClient {
ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName()); ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
HttpClient client = new DefaultHttpClient(); HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(request.getRequestURL().toString(), session) + "/database/products"); HttpGet get = new HttpGet(UriUtils.getOrigin(request.getRequestURL().toString()) + "/database/products");
get.addHeader("Authorization", "Bearer " + accessToken); get.addHeader("Authorization", "Bearer " + accessToken);
try { try {
HttpResponse response = client.execute(get); HttpResponse response = client.execute(get);
@ -119,19 +118,4 @@ public class ProductDatabaseClient {
} }
} }
public static String getBaseUrl(ServletOAuthClient oAuthClient, HttpServletRequest request) {
switch (oAuthClient.getRelativeUrlsUsed()) {
case ALL_REQUESTS:
// Resolve baseURI from the request
return UriUtils.getOrigin(request.getRequestURL().toString());
case BROWSER_ONLY:
// Resolve baseURI from the codeURL (This is already non-relative and based on our hostname)
return UriUtils.getOrigin(oAuthClient.getTokenUrl());
case NEVER:
return "";
default:
return "";
}
}
} }

View file

@ -1,157 +0,0 @@
How to test Keycloak cluster with Docker
========================================
Docker+Fig allows to easily setup and test the whole environment with:
* Apache HTTPD 2.4 + modcluster 1.3 as Load Balancer
* MySQL 5.6.1 as database
* Various number of Keycloak cluster nodes running on WildFly with "demo" examples deployed. (See below for EAP 6.4 and AS7)
You don't need to setup Apache with modcluster + MySQL on your laptop as Docker will do it for you and all will run in Docker containers.
Steps to setup
--------------
1) Download and install [Docker](https://docs.docker.com/installation) and [Fig](http://www.fig.sh/install.html)
2) Build Keycloak including distribution. This will be used by Docker+Fig. The point is that you can test clustering stuff from latest Keycloak master:
```shell
$ cd $KEYCLOAK_HOME
$ mvn clean install
$ cd distribution
$ mvn clean install
````
3) Build docker-cluster module with maven to ensure that needed data will be accessible to Docker+Fig volumes:
```shell
$ cd $KEYCLOAK_HOME/testsuite/docker-cluster
$ mvn clean install
````
4) Build fig and run the whole env. By default it will run Apache + MySQL + 1 Keycloak node:
```shell
$ fig build
$ fig up
````
First build will take long time as it need to download bunch of stuff and install into Docker container. Next builds will be much faster due to Docker cache.
After some time, WildFly server is started
Testing
-------
Apache is running in separate container and have 2 ports exposed locally: 10001 and 8000. Port 10001 is for modCluster - you should
be able to access Apache modCluster status page: [http://localhost:10001/mod_cluster_manager](http://localhost:10001/mod_cluster_manager) and see one node
with deployed "auth-server.war" and few other WARs (keycloak demo).
Also you can access Keycloak admin console via loadBalancer on [http://localhost:8000/auth/admin](http://localhost:8000/auth/admin) and similarly Account mgmt.
MySQL can be directly accessed from your machine (if you have MySQL client installed):
```shell
$ mysql -h127.0.0.1 -P33306 -uroot -pmysecretpassword
````
Used database is "keycloak_db"
Remote debugging
----------------
With command:
```shell
$ docker ps
````
You can see running ports. For the Keycloak node you may see output similar to this:
```shell
0.0.0.0:49153->8080/tcp, 0.0.0.0:49154->8787/tcp, 0.0.0.0:49155->9990/tcp
````
This means that you can directly access Keycloak (bypass loadbalancer) by going to [http://localhost:49153/auth/admin](http://localhost:49153/auth/admin) .
Also it means that debugger is mapped From Docker port 8787 to local port 49154 . So in your IDE you can connect with settings similar to:
```shell
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=49154
````
Scale / more cluster nodes
--------------------------
Run this in separate terminal to add more (in this case 2) cluster nodes:
```shell
$ fig scale wfnode=2
````
Now it should be visible on mod_cluster_manager page that they are 2 nodes.
Seeing logs
-----------
It's easiest to do:
```shell
$ fig logs
````
to see output of MySql and Keycloak server consoles.
To see Apache and debug logs of keycloak server:
```shell
$ fig run wfnode /bin/bash
````
Then you're in shell inside docker container, which has some mounted volumes with apache logs and keycloak nodes. Apache logs are at:
```shell
$ cd /apachelogs/
````
Keycloak nodes are at (debug logging enabled by default for "org.keycloak"):
```shell
$ cd /keycloak-docker/shared
````
Restart whole environment
-------------------------
Just run:
```shell
$ fig stop
$ fig start
````
This will restart apache + MySQL + all nodes, but won't clear data.
Changing configuration and clear data
-------------------------------------
Changing configuration (for example UserSession provider from 'mem' to 'jpa') is possible in
```shell
$KEYCLOAK_HOME/testsuite/docker-cluster/target/keycloak-docker-cluster/deployments/auth-server.war/WEB-INF/classes/META-INF/keycloak-server.json
````
then whole environment needs to be stopped, containers removed (in order to update configuration in nodes) and started again:
```shell
$ fig stop
$ fig rm
$ fig up
````
Rebuilding after changed sources
-------------------------------
In this case you might need to stop and remove existing containers. Then start from step 2 (Rebuild Keycloak or at least
changed jars, then rebuild distribution and testsuite/docker-cluster
(or just copy changed JAR into $KEYCLOAK_HOME/testsuite/docker-cluster/target/keycloak-docker-cluster/deployments/auth-server.war/WEB-INF/lib if it's not adapter stuff.
But 'fig rm' is safer to call anyway)
Test with Keycloak and examples on EAP 6.4
------------------------------------------
Steps are quite similar like for WildFly but we need to pass different file "fig-eap6.yml" instead of default "fig.yml" which is used for WildFly.
Also name of the node is "eapnode" instead of "wfnode".
So your commands will look like
```shell
$ fig -f fig-eap6.yml build
$ fig -f fig-eap6.yml up
$ fig -f fig-eap6.yml scale eapnode=2
````
and viceversa.
Test with Keycloak and examples on AS 7.1.1
-------------------------------------------
Also arguments need to be passed with different fig file and node name: TODO: AS7 cluster setup doesn't work correctly yet
```shell
$ fig -f fig-as7.yml build
$ fig -f fig-as7.yml up
$ fig -f fig-as7.yml scale asnode=2
````

View file

@ -1,32 +0,0 @@
FROM jboss/wildfly
USER root
# Update yum and install required programs
RUN yum install -y unzip && yum install -y wget && yum install -y mc && yum -y install nc
RUN yum clean all
# Download mysql driver
RUN cd /tmp
RUN wget http://search.maven.org/remotecontent?filepath=mysql/mysql-connector-java/5.1.32/mysql-connector-java-5.1.32.jar
RUN mv *.jar mysql-connector-java-5.1.32.jar
# Drop wildfly
RUN rm -rf /opt/wildfly*
ENV AS7_VERSION 7.1.1.Final
# Download and unpack AS7 distribution
RUN cd /opt
RUN wget http://download.jboss.org/jbossas/7.1/jboss-as-$AS7_VERSION/jboss-as-$AS7_VERSION.zip
RUN sleep 3
RUN unzip -q jboss-as-$AS7_VERSION.zip
# Make sure the distribution is available from a well-known place
RUN mv jboss-as-$AS7_VERSION /opt/as7
RUN rm -rf jboss-as-$AS7_VERSION.zip
EXPOSE 8787
CMD [ "/bin/bash" ]

View file

@ -1,13 +0,0 @@
FROM mposolda/as7
ADD keycloak-as7-trigger.sh /keycloak-as7-trigger.sh
RUN chmod u+x /keycloak-as7-trigger.sh
ENV JBOSS_HOME /opt/as7
ENV JBOSS_MODULES_HOME $JBOSS_HOME/modules
ENV JBOSS_TYPE as7
ENV NODE_PREFIX as
EXPOSE 8787
CMD [ "/keycloak-as7-trigger.sh" ]

View file

@ -1,8 +0,0 @@
#!/bin/bash
chmod u+x /keycloak-docker-cluster/shared-files/keycloak-run-node.sh
chmod u+x /keycloak-docker-cluster/shared-files/keycloak-base-prepare.sh
chmod u+x /keycloak-docker-cluster/shared-files/deploy-examples.sh
echo "Permissions changed. Triggering keycloak-run-node.sh"
/keycloak-docker-cluster/shared-files/keycloak-run-node.sh

View file

@ -1,66 +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.
-->
<assembly>
<id>docker-cluster</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>../../examples/demo-template</directory>
<outputDirectory>examples</outputDirectory>
<includes>
<include>**/target/*.war</include>
<include>**/testrealm.json</include>
</includes>
</fileSet>
<fileSet>
<directory>target/deployments</directory>
<outputDirectory>deployments</outputDirectory>
<excludes>
<exclude>**/keycloak-ds.xml</exclude>
</excludes>
</fileSet>
<fileSet>
<directory>target/wildfly-adapter</directory>
<outputDirectory>wildfly-adapter</outputDirectory>
</fileSet>
<fileSet>
<directory>target/as7-adapter</directory>
<outputDirectory>as7-adapter</outputDirectory>
</fileSet>
<fileSet>
<directory>target/eap63-adapter</directory>
<outputDirectory>eap63-adapter</outputDirectory>
</fileSet>
<fileSet>
<directory>target/server-overlay</directory>
<outputDirectory>server-overlay</outputDirectory>
<excludes>
<exclude>**/standalone-keycloak.xml</exclude>
</excludes>
</fileSet>
<fileSet>
<directory>shared-files</directory>
<outputDirectory>shared-files</outputDirectory>
</fileSet>
</fileSets>
</assembly>

View file

@ -1,30 +0,0 @@
FROM jboss/wildfly
USER root
# Update yum and install required programs
RUN yum install -y unzip && yum install -y wget && yum install -y mc && yum -y install nc
RUN yum clean all
# Drop wildfly
RUN rm -rf /opt/jboss/wildfly*
# Download mysql driver
RUN cd /tmp
RUN wget http://search.maven.org/remotecontent?filepath=mysql/mysql-connector-java/5.1.32/mysql-connector-java-5.1.32.jar
RUN mv *.jar /mysql-connector-java-5.1.32.jar
# Download and unpack EAP64 distribution TODO: Check if it's an issue for EAP 6.4
RUN cd /
RUN wget https://dl.dropboxusercontent.com/u/5525920/jboss-eap-6.4.0.zip
RUN sleep 3
RUN unzip -q jboss-eap-6.4.0.zip
# Make sure the distribution is available from a well-known place
RUN mv jboss-eap-6.4 /opt/eap6
RUN rm -rf jboss-eap-6.4.0.zip
EXPOSE 8787
CMD [ "/bin/bash" ]

View file

@ -1,18 +0,0 @@
FROM mposolda/eap64
ADD keycloak-eap6-trigger.sh /keycloak-eap6-trigger.sh
RUN chmod u+x /keycloak-eap6-trigger.sh
# TODO: REmove as it's in base EAP64 image already
RUN cd /tmp
RUN wget http://search.maven.org/remotecontent?filepath=mysql/mysql-connector-java/5.1.32/mysql-connector-java-5.1.32.jar
RUN mv mysql-connector-*.jar /
ENV JBOSS_HOME /opt/eap6
ENV JBOSS_MODULES_HOME $JBOSS_HOME/modules/system/layers/base
ENV JBOSS_TYPE eap6
ENV NODE_PREFIX eap
EXPOSE 8787
CMD [ "/keycloak-eap6-trigger.sh" ]

View file

@ -1,8 +0,0 @@
#!/bin/bash
chmod u+x /keycloak-docker-cluster/shared-files/keycloak-run-node.sh
chmod u+x /keycloak-docker-cluster/shared-files/keycloak-base-prepare.sh
chmod u+x /keycloak-docker-cluster/shared-files/deploy-examples.sh
echo "Permissions changed. Triggering keycloak-run-node.sh"
/keycloak-docker-cluster/shared-files/keycloak-run-node.sh

View file

@ -1,31 +0,0 @@
httpd:
build: httpd
ports:
- "8000:80"
- "10001:10001"
volumes_from:
- mysql
mysql:
image: mysql:5.6.20
environment:
- MYSQL_ROOT_PASSWORD=mysecretpassword
- MYSQL_DATABASE=keycloak_db
volumes:
- /keycloak-docker-shared
- /apachelogs
ports:
- "33306:3306"
asnode:
build: as7
command: /keycloak-as7-trigger.sh
volumes:
- target/keycloak-docker-cluster:/keycloak-docker-cluster
volumes_from:
- mysql
links:
- httpd:httpd
- mysql:mysql
ports:
- "8787"
- "8080"
- "9990"

View file

@ -1,31 +0,0 @@
httpd:
build: httpd
ports:
- "8000:80"
- "10001:10001"
volumes_from:
- mysql
mysql:
image: mysql:5.6.20
environment:
- MYSQL_ROOT_PASSWORD=mysecretpassword
- MYSQL_DATABASE=keycloak_db
volumes:
- /keycloak-docker-shared
- /apachelogs
ports:
- "33306:3306"
eapnode:
build: eap6
command: /keycloak-eap6-trigger.sh
volumes:
- target/keycloak-docker-cluster:/keycloak-docker-cluster
volumes_from:
- mysql
links:
- httpd:httpd
- mysql:mysql
ports:
- "8787"
- "8080"
- "9990"

View file

@ -1,31 +0,0 @@
httpd:
build: httpd
ports:
- "8000:80"
- "10001:10001"
volumes_from:
- mysql
mysql:
image: mysql:5.6.20
environment:
- MYSQL_ROOT_PASSWORD=mysecretpassword
- MYSQL_DATABASE=keycloak_db
volumes:
- /keycloak-docker-shared
- /apachelogs
ports:
- "33306:3306"
wfnode:
build: wildfly
command: /keycloak-wildfly-trigger.sh
volumes:
- target/keycloak-docker-cluster:/keycloak-docker-cluster
volumes_from:
- mysql
links:
- httpd:httpd
- mysql:mysql
ports:
- "8787"
- "8080"
- "9990"

View file

@ -1,16 +0,0 @@
FROM fedora:20
RUN cd /
RUN yum -y install wget && yum -y install unzip
RUN yum clean all
RUN wget https://dl.dropboxusercontent.com/u/5525920/apache24-modcluster131.zip
RUN unzip -q apache24-modcluster131.zip
ADD httpd-run /bin/httpd-run
RUN chmod u+x /bin/httpd-run
ADD httpd.conf /opt/jboss/httpd/httpd/conf/httpd.conf
EXPOSE 80 10001
CMD ["/bin/httpd-run"]

View file

@ -1,8 +0,0 @@
#!/bin/bash
# Make sure we're not confused by old, incompletely-shutdown httpd
# context after restarting the container. httpd won't start correctly
# if it thinks it is already running.
rm -rf /opt/jboss/httpd/httpd/logs/httpd.pid
exec /opt/jboss/httpd/sbin/apachectl -D FOREGROUND

View file

@ -1,550 +0,0 @@
#
# This is the main Apache HTTP server configuration file. It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
# In particular, see
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
# for a discussion of each configuration directive.
#
# Do NOT simply read the instructions in here without understanding
# what they do. They're here only as hints or reminders. If you are unsure
# consult the online docs. You have been warned.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path. If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
# will be interpreted as '/logs/access_log'.
#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path. If you point
# ServerRoot at a non-local disk, be sure to specify a local disk on the
# Mutex directive, if file-based mutexes are used. If you wish to share the
# same ServerRoot for multiple httpd daemons, you will need to change at
# least PidFile.
#
ServerRoot "/opt/jboss/httpd/httpd"
#
# Mutex: Allows you to set the mutex mechanism and mutex file directory
# for individual mutexes, or change the global defaults
#
# Uncomment and change the directory if mutexes are file-based and the default
# mutex file directory is not on a local disk or is not appropriate for some
# other reason.
#
# Mutex default:logs
#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule authn_file_module /opt/jboss/httpd/lib/httpd/modules/mod_authn_file.so
#LoadModule authn_dbm_module /opt/jboss/httpd/lib/httpd/modules/mod_authn_dbm.so
#LoadModule authn_anon_module /opt/jboss/httpd/lib/httpd/modules/mod_authn_anon.so
#LoadModule authn_dbd_module /opt/jboss/httpd/lib/httpd/modules/mod_authn_dbd.so
#LoadModule authn_socache_module /opt/jboss/httpd/lib/httpd/modules/mod_authn_socache.so
LoadModule authn_core_module /opt/jboss/httpd/lib/httpd/modules/mod_authn_core.so
LoadModule authz_host_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_host.so
LoadModule authz_groupfile_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_groupfile.so
LoadModule authz_user_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_user.so
#LoadModule authz_dbm_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_dbm.so
#LoadModule authz_owner_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_owner.so
#LoadModule authz_dbd_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_dbd.so
LoadModule authz_core_module /opt/jboss/httpd/lib/httpd/modules/mod_authz_core.so
LoadModule access_compat_module /opt/jboss/httpd/lib/httpd/modules/mod_access_compat.so
LoadModule auth_basic_module /opt/jboss/httpd/lib/httpd/modules/mod_auth_basic.so
#LoadModule auth_form_module /opt/jboss/httpd/lib/httpd/modules/mod_auth_form.so
#LoadModule auth_digest_module /opt/jboss/httpd/lib/httpd/modules/mod_auth_digest.so
#LoadModule allowmethods_module /opt/jboss/httpd/lib/httpd/modules/mod_allowmethods.so
LoadModule advertise_module /opt/jboss/httpd/lib/httpd/modules/mod_advertise.so
#LoadModule file_cache_module /opt/jboss/httpd/lib/httpd/modules/mod_file_cache.so
#LoadModule cache_module /opt/jboss/httpd/lib/httpd/modules/mod_cache.so
#LoadModule cache_disk_module /opt/jboss/httpd/lib/httpd/modules/mod_cache_disk.so
#LoadModule cache_socache_module /opt/jboss/httpd/lib/httpd/modules/mod_cache_socache.so
#LoadModule socache_shmcb_module /opt/jboss/httpd/lib/httpd/modules/mod_socache_shmcb.so
#LoadModule socache_dbm_module /opt/jboss/httpd/lib/httpd/modules/mod_socache_dbm.so
#LoadModule socache_memcache_module /opt/jboss/httpd/lib/httpd/modules/mod_socache_memcache.so
#LoadModule watchdog_module /opt/jboss/httpd/lib/httpd/modules/mod_watchdog.so
#LoadModule macro_module /opt/jboss/httpd/lib/httpd/modules/mod_macro.so
#LoadModule dbd_module /opt/jboss/httpd/lib/httpd/modules/mod_dbd.so
#LoadModule dumpio_module /opt/jboss/httpd/lib/httpd/modules/mod_dumpio.so
#LoadModule echo_module /opt/jboss/httpd/lib/httpd/modules/mod_echo.so
#LoadModule buffer_module /opt/jboss/httpd/lib/httpd/modules/mod_buffer.so
#LoadModule data_module /opt/jboss/httpd/lib/httpd/modules/mod_data.so
#LoadModule ratelimit_module /opt/jboss/httpd/lib/httpd/modules/mod_ratelimit.so
LoadModule reqtimeout_module /opt/jboss/httpd/lib/httpd/modules/mod_reqtimeout.so
#LoadModule ext_filter_module /opt/jboss/httpd/lib/httpd/modules/mod_ext_filter.so
#LoadModule request_module /opt/jboss/httpd/lib/httpd/modules/mod_request.so
#LoadModule include_module /opt/jboss/httpd/lib/httpd/modules/mod_include.so
LoadModule filter_module /opt/jboss/httpd/lib/httpd/modules/mod_filter.so
#LoadModule reflector_module /opt/jboss/httpd/lib/httpd/modules/mod_reflector.so
#LoadModule substitute_module /opt/jboss/httpd/lib/httpd/modules/mod_substitute.so
#LoadModule sed_module /opt/jboss/httpd/lib/httpd/modules/mod_sed.so
#LoadModule charset_lite_module /opt/jboss/httpd/lib/httpd/modules/mod_charset_lite.so
#LoadModule deflate_module /opt/jboss/httpd/lib/httpd/modules/mod_deflate.so
#LoadModule xml2enc_module /opt/jboss/httpd/lib/httpd/modules/mod_xml2enc.so
#LoadModule proxy_html_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_html.so
LoadModule mime_module /opt/jboss/httpd/lib/httpd/modules/mod_mime.so
LoadModule log_config_module /opt/jboss/httpd/lib/httpd/modules/mod_log_config.so
#LoadModule log_debug_module /opt/jboss/httpd/lib/httpd/modules/mod_log_debug.so
#LoadModule log_forensic_module /opt/jboss/httpd/lib/httpd/modules/mod_log_forensic.so
#LoadModule logio_module /opt/jboss/httpd/lib/httpd/modules/mod_logio.so
LoadModule env_module /opt/jboss/httpd/lib/httpd/modules/mod_env.so
#LoadModule mime_magic_module /opt/jboss/httpd/lib/httpd/modules/mod_mime_magic.so
#LoadModule expires_module /opt/jboss/httpd/lib/httpd/modules/mod_expires.so
LoadModule headers_module /opt/jboss/httpd/lib/httpd/modules/mod_headers.so
#LoadModule usertrack_module /opt/jboss/httpd/lib/httpd/modules/mod_usertrack.so
#LoadModule unique_id_module /opt/jboss/httpd/lib/httpd/modules/mod_unique_id.so
LoadModule setenvif_module /opt/jboss/httpd/lib/httpd/modules/mod_setenvif.so
LoadModule version_module /opt/jboss/httpd/lib/httpd/modules/mod_version.so
#LoadModule remoteip_module /opt/jboss/httpd/lib/httpd/modules/mod_remoteip.so
LoadModule proxy_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy.so
LoadModule proxy_connect_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_connect.so
LoadModule proxy_ftp_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_ftp.so
LoadModule proxy_http_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_http.so
LoadModule proxy_fcgi_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_fcgi.so
LoadModule proxy_scgi_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_scgi.so
#LoadModule proxy_fdpass_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_fdpass.so
LoadModule proxy_wstunnel_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_wstunnel.so
LoadModule proxy_ajp_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_ajp.so
LoadModule proxy_cluster_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_cluster.so
LoadModule proxy_express_module /opt/jboss/httpd/lib/httpd/modules/mod_proxy_express.so
#LoadModule session_module /opt/jboss/httpd/lib/httpd/modules/mod_session.so
#LoadModule session_cookie_module /opt/jboss/httpd/lib/httpd/modules/mod_session_cookie.so
#LoadModule session_dbd_module /opt/jboss/httpd/lib/httpd/modules/mod_session_dbd.so
#LoadModule slotmem_shm_module /opt/jboss/httpd/lib/httpd/modules/mod_slotmem_shm.so
#LoadModule slotmem_plain_module /opt/jboss/httpd/lib/httpd/modules/mod_slotmem_plain.so
#LoadModule ssl_module /opt/jboss/httpd/lib/httpd/modules/mod_ssl.so
#LoadModule dialup_module /opt/jboss/httpd/lib/httpd/modules/mod_dialup.so
LoadModule lbmethod_byrequests_module /opt/jboss/httpd/lib/httpd/modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module /opt/jboss/httpd/lib/httpd/modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_bybusyness_module /opt/jboss/httpd/lib/httpd/modules/mod_lbmethod_bybusyness.so
LoadModule lbmethod_heartbeat_module /opt/jboss/httpd/lib/httpd/modules/mod_lbmethod_heartbeat.so
LoadModule unixd_module /opt/jboss/httpd/lib/httpd/modules/mod_unixd.so
#LoadModule heartbeat_module /opt/jboss/httpd/lib/httpd/modules/mod_heartbeat.so
#LoadModule heartmonitor_module /opt/jboss/httpd/lib/httpd/modules/mod_heartmonitor.so
#LoadModule dav_module /opt/jboss/httpd/lib/httpd/modules/mod_dav.so
LoadModule status_module /opt/jboss/httpd/lib/httpd/modules/mod_status.so
LoadModule autoindex_module /opt/jboss/httpd/lib/httpd/modules/mod_autoindex.so
#LoadModule asis_module /opt/jboss/httpd/lib/httpd/modules/mod_asis.so
#LoadModule info_module /opt/jboss/httpd/lib/httpd/modules/mod_info.so
#LoadModule suexec_module /opt/jboss/httpd/lib/httpd/modules/mod_suexec.so
#LoadModule cgi_module /opt/jboss/httpd/lib/httpd/modules/mod_cgi.so
#LoadModule cgid_module /opt/jboss/httpd/lib/httpd/modules/mod_cgid.so
LoadModule cluster_slotmem_module /opt/jboss/httpd/lib/httpd/modules/mod_cluster_slotmem.so
LoadModule manager_module /opt/jboss/httpd/lib/httpd/modules/mod_manager.so
#LoadModule dav_fs_module /opt/jboss/httpd/lib/httpd/modules/mod_dav_fs.so
#LoadModule dav_lock_module /opt/jboss/httpd/lib/httpd/modules/mod_dav_lock.so
#LoadModule vhost_alias_module /opt/jboss/httpd/lib/httpd/modules/mod_vhost_alias.so
#LoadModule negotiation_module /opt/jboss/httpd/lib/httpd/modules/mod_negotiation.so
LoadModule dir_module /opt/jboss/httpd/lib/httpd/modules/mod_dir.so
#LoadModule actions_module /opt/jboss/httpd/lib/httpd/modules/mod_actions.so
#LoadModule speling_module /opt/jboss/httpd/lib/httpd/modules/mod_speling.so
#LoadModule userdir_module /opt/jboss/httpd/lib/httpd/modules/mod_userdir.so
LoadModule alias_module /opt/jboss/httpd/lib/httpd/modules/mod_alias.so
#LoadModule rewrite_module /opt/jboss/httpd/lib/httpd/modules/mod_rewrite.so
<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User daemon
Group daemon
</IfModule>
# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition. These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed. This address appears on some server-generated pages, such
# as error documents. e.g. admin@your-domain.com
#
ServerAdmin you@example.com
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80
#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# <Directory> blocks below.
#
<Directory />
AllowOverride none
Require all denied
</Directory>
#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#
#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/opt/jboss/httpd/htdocs/htdocs"
<Directory "/opt/jboss/httpd/htdocs/htdocs">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.4/mod/core.html#options
# for more information.
#
Options Indexes FollowSymLinks
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# AllowOverride FileInfo AuthConfig Limit
#
AllowOverride None
#
# Controls who can get stuff from this server.
#
Require all granted
</Directory>
#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ".ht*">
Require all denied
</Files>
#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
# Note: Actually it's custom location mounted to docker volume
ErrorLog "/apachelogs/error_log"
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel info
<IfModule log_config_module>
#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
# You need to enable mod_logio.c to use %I and %O
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
#
# The location and format of the access logfile (Common Logfile Format).
# If you do not define any access logfiles within a <VirtualHost>
# container, they will be logged here. Contrariwise, if you *do*
# define per-<VirtualHost> access logfiles, transactions will be
# logged therein and *not* in this file.
#
CustomLog "/apachelogs/access_log" common
#
# If you prefer a logfile with access, agent, and referer information
# (Combined Logfile Format) you can use the following directive.
#
#CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
#
# Redirect: Allows you to tell clients about documents that used to
# exist in your server's namespace, but do not anymore. The client
# will make a new request for the document at its new location.
# Example:
# Redirect permanent /foo http://www.example.com/bar
#
# Alias: Maps web paths into filesystem paths and is used to
# access content that does not live under the DocumentRoot.
# Example:
# Alias /webpath /full/filesystem/path
#
# If you include a trailing / on /webpath then the server will
# require it to be present in the URL. You will also likely
# need to provide a <Directory> section to allow access to
# the filesystem path.
#
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the target directory are treated as applications and
# run by the server when requested rather than as documents sent to the
# client. The same rules about trailing "/" apply to ScriptAlias
# directives as to Alias.
#
ScriptAlias /cgi-bin/ "/opt/jboss/httpd/htdocs/cgi-bin/"
</IfModule>
<IfModule cgid_module>
#
# ScriptSock: On threaded servers, designate the path to the UNIX
# socket used to communicate with the CGI daemon of mod_cgid.
#
#Scriptsock cgisock
</IfModule>
#
# "/opt/jboss/httpd/htdocs/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/opt/jboss/httpd/htdocs/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule mime_module>
#
# TypesConfig points to the file containing the list of mappings from
# filename extension to MIME-type.
#
TypesConfig conf/mime.types
#
# AddType allows you to add to or override the MIME configuration
# file specified in TypesConfig for specific file types.
#
#AddType application/x-gzip .tgz
#
# AddEncoding allows you to have certain browsers uncompress
# information on the fly. Note: Not all browsers support this.
#
#AddEncoding x-compress .Z
#AddEncoding x-gzip .gz .tgz
#
# If the AddEncoding directives above are commented-out, then you
# probably should define those extensions to indicate media types:
#
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
#
# AddHandler allows you to map certain file extensions to "handlers":
# actions unrelated to filetype. These can be either built into the server
# or added with the Action directive (see below)
#
# To use CGI scripts outside of ScriptAliased directories:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
#AddHandler cgi-script .cgi
# For type maps (negotiated resources):
#AddHandler type-map var
#
# Filters allow you to process content before it is sent to the client.
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
#AddType text/html .shtml
#AddOutputFilter INCLUDES .shtml
</IfModule>
#
# The mod_mime_magic module allows the server to use various hints from the
# contents of the file itself to determine its type. The MIMEMagicFile
# directive tells the module where the hint definitions are located.
#
#MIMEMagicFile conf/magic
#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
#
# MaxRanges: Maximum number of Ranges in a request before
# returning the entire resource, or one of the special
# values 'default', 'none' or 'unlimited'.
# Default setting is to accept 200 Ranges.
#MaxRanges unlimited
#
# EnableMMAP and EnableSendfile: On systems that support it,
# memory-mapping or the sendfile syscall may be used to deliver
# files. This usually improves server performance, but must
# be turned off when serving from networked-mounted
# filesystems or if support for these functions is otherwise
# broken on your system.
# Defaults: EnableMMAP On, EnableSendfile Off
#
#EnableMMAP off
#EnableSendfile on
# Supplemental configuration
#
# The configuration files in the conf/extra/ directory can be
# included to add extra features or to modify the default configuration of
# the server, or you may simply copy their contents here and change as
# necessary.
# Server-pool management (MPM specific)
#Include conf/extra/httpd-mpm.conf
# Multi-language error messages
#Include conf/extra/httpd-multilang-errordoc.conf
# Fancy directory listings
#Include conf/extra/httpd-autoindex.conf
# Language settings
#Include conf/extra/httpd-languages.conf
# User home directories
#Include conf/extra/httpd-userdir.conf
# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf
# Virtual hosts
#Include conf/extra/httpd-vhosts.conf
# Local access to the Apache HTTP Server Manual
#Include conf/extra/httpd-manual.conf
# Distributed authoring and versioning (WebDAV)
#Include conf/extra/httpd-dav.conf
# Various default settings
#Include conf/extra/httpd-default.conf
# Configure mod_proxy_html to understand HTML4/XHTML1
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>
# Secure (SSL/TLS) connections
#Include conf/extra/httpd-ssl.conf
#
# Note: The following must must be present to support
# starting without SSL on platforms with no /dev/random equivalent
# but a statically compiled-in mod_ssl.
#
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>
#
# uncomment out the below to deal with user agents that deliberately
# violate open standards by misusing DNT (DNT *must* be a specific
# end-user choice)
#
#<IfModule setenvif_module>
#BrowserMatch "MSIE 10.0;" bad_DNT
#</IfModule>
#<IfModule headers_module>
#RequestHeader unset DNT env=bad_DNT
#</IfModule>
# MOD_CLUSTER_ADDS
# Adjust to you hostname and subnet.
<IfModule manager_module>
Listen *:10001
ManagerBalancerName mycluster
<VirtualHost *:10001>
<Location />
Require all granted
</Location>
KeepAliveTimeout 300
MaxKeepAliveRequests 0
#ServerAdvertise on http://@IP@:6666
AdvertiseFrequency 5
#AdvertiseSecurityKey secret
#AdvertiseGroup @ADVIP@:23364
EnableMCPMReceive
<Location /mod_cluster_manager>
SetHandler mod_cluster-manager
Require all granted
</Location>
</VirtualHost>
</IfModule>

View file

@ -1,141 +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.
-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>keycloak-testsuite-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.0.0.CR1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>keycloak-testsuite-docker-cluster</artifactId>
<packaging>pom</packaging>
<name>Keycloak Docker Cluster</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-overlay</artifactId>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-wildfly-adapter-dist</artifactId>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-adapter-dist</artifactId>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-eap6-adapter-dist</artifactId>
<type>zip</type>
</dependency>
</dependencies>
<build>
<finalName>keycloak-docker-cluster</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<!--<version>2.7</version> -->
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-overlay</artifactId>
<type>zip</type>
<version>${project.version}</version>
<outputDirectory>${project.build.directory}/server-overlay</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-wildfly-adapter-dist</artifactId>
<type>zip</type>
<version>${project.version}</version>
<outputDirectory>${project.build.directory}/wildfly-adapter</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-adapter-dist</artifactId>
<type>zip</type>
<version>${project.version}</version>
<outputDirectory>${project.build.directory}/as7-adapter</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-eap6-adapter-dist</artifactId>
<type>zip</type>
<version>${project.version}</version>
<outputDirectory>${project.build.directory}/eap63-adapter</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,50 +0,0 @@
#!/bin/bash
## Deploy and configure all examples
# Deploy examples
cd /keycloak-docker-cluster/examples
for I in $(find . | grep .war$); do cp $I $JBOSS_HOME/standalone/deployments/; done;
# Explode wars
cd $JBOSS_HOME/standalone/deployments/
for I in $(ls -d *.war | grep -v auth-server.war); do
echo "Configuring $I";
mkdir $I.tmp;
cd $I.tmp;
unzip -q ../$I;
cd ..
rm $I;
mv $I.tmp $I;
touch $I.dodeploy;
done;
# Configure admin-access.war
sed -i -e 's/false/true/' admin-access.war/WEB-INF/web.xml
# Enforce refreshing token for product-portal and customer-portal war
# sed -i -e 's/\"\/auth\",/&\n \"always-refresh-token\": true,/' customer-portal.war/WEB-INF/keycloak.json;
# sed -i -e 's/\"\/auth\",/&\n \"always-refresh-token\": true,/' product-portal.war/WEB-INF/keycloak.json;
# Configure other examples
for I in *.war/WEB-INF/keycloak.json; do
sed -i -e 's/\"resource\".*: \".*\",/&\n \"auth-server-url-for-backend-requests\": \"http:\/\/\$\{jboss.host.name\}:8080\/auth\",\n \"register-node-at-startup\": true,\n \"register-node-period\": 150,/' $I;
sed -i -e 's/\"bearer-only\" : true,/&\n \"credentials\" : \{ \"secret\": \"password\" \},/' $I;
done;
# Configure database.war
sed -i -e 's/\"auth-server-url\": \"\/auth\",/\"auth-server-url\": \"http:\/\/localhost:8000\/auth\",/' database.war/WEB-INF/keycloak.json;
# Enable distributable for customer-portal
sed -i -e 's/<\/module-name>/&\n <distributable \/>/' customer-portal.war/WEB-INF/web.xml
# Configure testrealm.json - Enable adminUrl to access adapters on local machine, add jboss-logging listener and add secret for database-service application
TEST_REALM=/keycloak-docker-cluster/examples/testrealm.json
sed -i -e 's/\"adminUrl\": \"\/customer-portal/\"adminUrl\": \"http:\/\/\$\{jboss.host.name\}:8080\/customer-portal/' $TEST_REALM
sed -i -e 's/\"adminUrl\": \"\/product-portal/\"adminUrl\": \"http:\/\/\$\{application.session.host\}:8080\/product-portal/' $TEST_REALM
sed -i -e 's/\"adminUrl\": \"\/database/\"adminUrl\": \"http:\/\/\$\{jboss.host.name\}:8080\/database/' $TEST_REALM
sed -i -e 's/\"bearerOnly\": true/&,\n \"secret\": \"password\"/' $TEST_REALM
sed -i -e 's/\"sslRequired\": \"external\",/&\n \"eventsListeners\": \[ \"jboss-logging\" \],/' $TEST_REALM

View file

@ -1,24 +0,0 @@
#!/bin/bash
# Copy Overlay
cp -r /keycloak-docker-cluster/server-overlay/* $JBOSS_HOME/
# Deploy and configure examples
/keycloak-docker-cluster/shared-files/deploy-examples.sh
# Copy MySQL driver
cd /tmp
mkdir -p mysql/main && mv /mysql-connector-java-5.1.32.jar mysql/main/
cp /keycloak-docker-cluster/shared-files/mysql-module.xml mysql/main/module.xml
mv mysql $JBOSS_MODULES_HOME/com/
# Transform standalone-keycloak-ha.xml
java -jar /usr/share/java/saxon.jar -s:$JBOSS_HOME/standalone/configuration/standalone-keycloak-ha.xml -xsl:/keycloak-docker-cluster/shared-files/standaloneXmlChanges.xsl -o:$JBOSS_HOME/standalone/configuration/standalone-keycloak-ha.xml
sed -i "s|#JAVA_OPTS=\"\$JAVA_OPTS -agentlib:jdwp=transport=dt_socket|JAVA_OPTS=\"\$JAVA_OPTS -agentlib:jdwp=transport=dt_socket|" $JBOSS_HOME/bin/standalone.conf
cp /keycloak-docker-cluster/shared-files/mysql-keycloak-ds.xml $JBOSS_HOME/standalone/deployments/
# Enable Infinispan provider
#sed -i "s|\"provider\".*: \"mem\"|\"provider\": \"infinispan\"|" $JBOSS_HOME/standalone/configuration/keycloak-server.json
#sed -i -e "s/\"connectionsJpa\"/\n \"connectionsInfinispan\": \{\n \"default\" : \{\n \"cacheContainer\" : \"java:jboss\/infinispan\/Keycloak\"\n \}\n \},\n &/" $JBOSS_HOME/standalone/configuration/keycloak-server.json

View file

@ -1,78 +0,0 @@
#!/bin/bash
export MYHOST="$NODE_PREFIX"node$(echo $MYSQL_NAME | awk -F"/dockercluster[^0-9]*|\/mysql" '{print $2 }');
echo "MYHOST is $MYHOST. MYSQL_NAME is $MYSQL_NAME";
function prepareHost
{
if [ -d /keycloak-docker-shared/keycloak-$JBOSS_TYPE-$MYHOST ]; then
echo "Node $MYHOST already prepared. Skiping";
return;
fi
echo "Creating keycloak-$JBOSS_TYPE-$MYHOST";
/keycloak-docker-cluster/shared-files/keycloak-base-prepare.sh
echo "Base prepare finished";
# Deploy to volume
rm -rf /keycloak-docker-shared/keycloak-$JBOSS_TYPE-$MYHOST
cp -r $JBOSS_HOME /keycloak-docker-shared/keycloak-$JBOSS_TYPE-$MYHOST
chmod -R 777 /keycloak-docker-shared/keycloak-$JBOSS_TYPE-$MYHOST
echo "keycloak-$JBOSS_TYPE-$MYHOST prepared and copyied to volume";
}
function waitForPreviousNodeStart
{
myHostNumber=$(echo $MYHOST | awk -F"node" '{ print $2 }');
if [ $myHostNumber -eq 1 ]; then
echo "Our host is $MYHOST. No need to wait for previous server";
else
previous="$NODE_PREFIX"node$(($myHostNumber-1));
echo "Waiting for host $previous to start";
for I in $(seq 1 10); do
cat /keycloak-docker-shared/keycloak-$JBOSS_TYPE-$previous/standalone/log/server.log | grep "\(INFO\|ERROR\).*\(WildFly\|JBoss AS\|JBoss EAP\).*started";
if [ 0 -eq $? ]; then
echo "Host $previous started. Going to start $MYHOST";
return;
fi;
echo "Host $previous not started yet. Still waiting...";
sleep 5;
done;
echo "Host $previous not started yet within timeout.";
fi;
}
function waitForMySQLStart
{
for I in $(seq 1 10); do
nc $MYSQL_PORT_3306_TCP_ADDR 3306 < /dev/null;
mysqlRunning=$(echo $?);
if [ $mysqlRunning -eq 0 ]; then
echo "MySQL is running. Starting our server";
return;
else
echo "MySQL not yet available. Still waiting...";
sleep 5;
fi;
done;
}
prepareHost;
waitForPreviousNodeStart;
waitForMySQLStart;
echo "Running keycloak node $MYHOST. Additional arguments: $@";
cd /keycloak-docker-shared
export JBOSS_HOME=/keycloak-docker-shared/keycloak-$JBOSS_TYPE-$MYHOST;
cd $JBOSS_HOME/bin/
./standalone.sh -c standalone-keycloak-ha.xml -Djboss.node.name=$MYHOST -b `hostname -i` -Djboss.mod_cluster.jvmRoute=$MYHOST \
-Dmysql.host=$MYSQL_PORT_3306_TCP_ADDR -Dhttpd.proxyHost=$HTTPD_1_PORT_10001_TCP_ADDR -Dhttpd.proxyPort=$HTTPD_PORT_10001_TCP_PORT \
-Dkeycloak.import=/keycloak-docker-cluster/examples/testrealm.json "$@"

View file

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
<resources>
<resource-root path="mysql-connector-java-5.1.32.jar"/>
</resources>
<dependencies>
<module name="javax.api" />
<module name="javax.transaction.api" />
</dependencies>
</module>

View file

@ -1,100 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:ds="urn:jboss:domain:datasources:4.0"
xmlns:logging="urn:jboss:domain:logging:3.0"
xmlns:ispn="urn:jboss:domain:infinispan:4.0"
xmlns:mcluster="urn:jboss:domain:modcluster:2.0"
xmlns:server="urn:jboss:domain:3.0"
exclude-result-prefixes='ds logging ispn mcluster xalan server'
>
<xsl:output method="xml" indent="yes" xalan:indent-amount="4" standalone="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="//ds:subsystem/ds:datasources/ds:datasource[@jndi-name='java:jboss/datasources/KeycloakDS']" >
<ds:datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
<ds:connection-url>jdbc:mysql://${mysql.host}/keycloak_db</ds:connection-url>
<ds:driver>mysql</ds:driver>
<ds:security>
<ds:user-name>root</ds:user-name>
<ds:password>mysecretpassword</ds:password>
</ds:security>
</ds:datasource>
</xsl:template>
<xsl:template match="//ds:subsystem/ds:datasources/ds:drivers">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<ds:driver name="mysql" module="com.mysql">
<ds:xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</ds:xa-datasource-class>
</ds:driver>
</xsl:copy>
</xsl:template>
<xsl:template match="//logging:subsystem/logging:periodic-rotating-file-handler">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<logging:logger category="org.keycloak">
<logging:level name="DEBUG" />
</logging:logger>
<logging:logger category="org.jboss.resteasy.core.ResourceLocator">
<logging:level name="ERROR" />
</logging:logger>
</xsl:template>
<xsl:template match="//ispn:subsystem/ispn:cache-container[@name='keycloak']">
<ispn:cache-container name="keycloak" jndi-name="infinispan/Keycloak">
<ispn:transport lock-timeout="60000"/>
<ispn:invalidation-cache name="realms" mode="SYNC"/>
<ispn:invalidation-cache name="users" mode="SYNC"/>
<ispn:distributed-cache name="sessions" mode="SYNC" owners="2"/>
<ispn:distributed-cache name="offlineSessions" mode="SYNC" owners="2"/>
<ispn:distributed-cache name="loginFailures" mode="SYNC" owners="2"/>
</ispn:cache-container>
</xsl:template>
<xsl:template match="//mcluster:subsystem/mcluster:mod-cluster-config">
<mcluster:mod-cluster-config advertise-socket="modcluster" proxies='myproxy' proxy-url="/" balancer="mycluster" advertise="false" connector="ajp" sticky-session="true">
<mcluster:dynamic-load-provider>
<mcluster:load-metric type="cpu"/>
</mcluster:dynamic-load-provider>
</mcluster:mod-cluster-config>
</xsl:template>
<xsl:template match="//server:socket-binding-group">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<server:outbound-socket-binding name="myproxy">
<server:remote-destination host="${{httpd.proxyHost}}" port="${{httpd.proxyPort}}"/>
</server:outbound-socket-binding>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,25 +0,0 @@
FROM jboss/wildfly:9.0.1.Final
USER root
# Update yum and install required programs
RUN yum install -y unzip && yum install -y wget && yum install -y mc && yum -y install nc
RUN yum clean all
# Download mysql driver
RUN cd /tmp
RUN wget http://search.maven.org/remotecontent?filepath=mysql/mysql-connector-java/5.1.32/mysql-connector-java-5.1.32.jar
RUN mv *.jar /mysql-connector-java-5.1.32.jar
ADD keycloak-wildfly-trigger.sh /keycloak-wildfly-trigger.sh
RUN chmod u+x /keycloak-wildfly-trigger.sh
ENV JBOSS_HOME /opt/jboss/wildfly
ENV JBOSS_MODULES_HOME $JBOSS_HOME/modules/system/layers/base
ENV JBOSS_TYPE wildfly
ENV NODE_PREFIX wf
EXPOSE 8787
CMD [ "/keycloak-wildfly-trigger.sh" ]

View file

@ -1,8 +0,0 @@
#!/bin/bash
chmod u+x /keycloak-docker-cluster/shared-files/keycloak-run-node.sh
chmod u+x /keycloak-docker-cluster/shared-files/keycloak-base-prepare.sh
chmod u+x /keycloak-docker-cluster/shared-files/deploy-examples.sh
echo "Permissions changed. Triggering keycloak-run-node.sh"
/keycloak-docker-cluster/shared-files/keycloak-run-node.sh

View file

@ -60,14 +60,5 @@
<module>stress</module> <module>stress</module>
<module>integration-arquillian</module> <module>integration-arquillian</module>
</modules> </modules>
<profiles>
<profile>
<id>jboss-release</id>
<modules>
<module>docker-cluster</module>
</modules>
</profile>
</profiles>
</project> </project>