Remove Wildfly and EAP OIDC adapters
Closes #23381 Signed-off-by: Douglas Palmer <dpalmer@redhat.com>
This commit is contained in:
parent
8a5fb8337b
commit
e0176a7e31
101 changed files with 0 additions and 7431 deletions
|
@ -34,7 +34,5 @@
|
|||
<module>adapter-core</module>
|
||||
<module>js</module>
|
||||
<module>undertow</module>
|
||||
<module>wildfly</module>
|
||||
<module>wildfly-elytron</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
|
||||
<name>Keycloak Wildfly Elytron OIDC Adapter</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.common</groupId>
|
||||
<artifactId>wildfly-common</artifactId>
|
||||
<version>${wildfly.common.wildfly.aligned.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.security</groupId>
|
||||
<artifactId>wildfly-elytron</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.security.elytron-web</groupId>
|
||||
<artifactId>undertow-server</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</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>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.Principal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ElytronAccount implements Serializable, OidcKeycloakAccount {
|
||||
|
||||
private static final long serialVersionUID = -6775274346765339292L;
|
||||
protected static Logger log = Logger.getLogger(ElytronAccount.class);
|
||||
|
||||
private final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
|
||||
|
||||
public ElytronAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
|
||||
return principal.getKeycloakSecurityContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRoles() {
|
||||
Set<String> roles = new HashSet<>();
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
||||
principal.getKeycloakSecurityContext().setCurrentRequestInfo(deployment, tokenStore);
|
||||
}
|
||||
|
||||
public boolean checkActive() {
|
||||
RefreshableKeycloakSecurityContext session = getKeycloakSecurityContext();
|
||||
|
||||
if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) {
|
||||
log.debug("session is active");
|
||||
return true;
|
||||
}
|
||||
|
||||
log.debug("session not active");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean tryRefresh() {
|
||||
log.debug("Trying to refresh");
|
||||
|
||||
RefreshableKeycloakSecurityContext securityContext = getKeycloakSecurityContext();
|
||||
|
||||
if (securityContext == null) {
|
||||
log.debug("No security context. Aborting refresh.");
|
||||
}
|
||||
|
||||
if (securityContext.refreshExpiredToken(false)) {
|
||||
log.debug("refresh succeeded");
|
||||
return true;
|
||||
}
|
||||
|
||||
return checkActive();
|
||||
}
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.CookieTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.UserSessionManagement;
|
||||
import org.wildfly.security.http.HttpScope;
|
||||
import org.wildfly.security.http.Scope;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ElytronCookieTokenStore implements ElytronTokeStore, UserSessionManagement {
|
||||
|
||||
protected static Logger log = Logger.getLogger(ElytronCookieTokenStore.class);
|
||||
|
||||
private final ElytronHttpFacade httpFacade;
|
||||
private final CallbackHandler callbackHandler;
|
||||
|
||||
public ElytronCookieTokenStore(ElytronHttpFacade httpFacade, CallbackHandler callbackHandler) {
|
||||
this.httpFacade = httpFacade;
|
||||
this.callbackHandler = callbackHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCurrentToken() {
|
||||
KeycloakDeployment deployment = httpFacade.getDeployment();
|
||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(deployment, httpFacade, this);
|
||||
|
||||
if (principal == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
|
||||
|
||||
if (securityContext.isActive() && !securityContext.getDeployment().isAlwaysRefreshToken()) return;
|
||||
|
||||
// FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will
|
||||
// not be updated
|
||||
boolean success = securityContext.refreshExpiredToken(false);
|
||||
if (success && securityContext.isActive()) return;
|
||||
|
||||
saveAccountInfo(new ElytronAccount(principal));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCached(RequestAuthenticator authenticator) {
|
||||
KeycloakDeployment deployment = httpFacade.getDeployment();
|
||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(deployment, httpFacade, this);
|
||||
if (principal == null) {
|
||||
log.debug("Account was not in cookie or was invalid, returning null");
|
||||
return false;
|
||||
}
|
||||
ElytronAccount account = new ElytronAccount(principal);
|
||||
|
||||
if (!deployment.getRealm().equals(account.getKeycloakSecurityContext().getRealm())) {
|
||||
log.debug("Account in session belongs to a different realm than for this request.");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean active = account.checkActive();
|
||||
|
||||
if (!active) {
|
||||
active = account.tryRefresh();
|
||||
}
|
||||
|
||||
if (active) {
|
||||
log.debug("Cached account found");
|
||||
restoreRequest();
|
||||
httpFacade.authenticationComplete(account, true);
|
||||
return true;
|
||||
} else {
|
||||
log.debug("Account was not active, removing cookie and returning false");
|
||||
CookieTokenStore.removeCookie(deployment, httpFacade);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||
RefreshableKeycloakSecurityContext secContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
||||
CookieTokenStore.setTokenCookie(this.httpFacade.getDeployment(), this.httpFacade, secContext);
|
||||
HttpScope exchange = this.httpFacade.getScope(Scope.EXCHANGE);
|
||||
|
||||
exchange.registerForNotification(httpServerScopes -> logout());
|
||||
|
||||
exchange.setAttachment(ElytronAccount.class.getName(), account);
|
||||
exchange.setAttachment(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
|
||||
|
||||
restoreRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() {
|
||||
logout(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
|
||||
CookieTokenStore.setTokenCookie(this.httpFacade.getDeployment(), httpFacade, securityContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRequest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(boolean glo) {
|
||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(this.httpFacade.getDeployment(), this.httpFacade, this);
|
||||
|
||||
if (principal == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CookieTokenStore.removeCookie(this.httpFacade.getDeployment(), this.httpFacade);
|
||||
|
||||
if (glo) {
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) principal.getKeycloakSecurityContext();
|
||||
|
||||
if (ksc == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeycloakDeployment deployment = httpFacade.getDeployment();
|
||||
|
||||
if (!deployment.isBearerOnly() && ksc != null && ksc instanceof RefreshableKeycloakSecurityContext) {
|
||||
((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logoutAll() {
|
||||
//no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logoutHttpSessions(List<String> ids) {
|
||||
//no-op
|
||||
}
|
||||
}
|
|
@ -1,550 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.server.handlers.CookieImpl;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.spi.AuthChallenge;
|
||||
import org.keycloak.adapters.spi.AuthenticationError;
|
||||
import org.keycloak.adapters.spi.LogoutError;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
import org.keycloak.enums.TokenStore;
|
||||
import org.wildfly.security.auth.server.SecurityIdentity;
|
||||
import org.wildfly.security.http.HttpScope;
|
||||
import org.wildfly.security.http.HttpServerCookie;
|
||||
import org.wildfly.security.http.HttpServerRequest;
|
||||
import org.wildfly.security.http.HttpServerResponse;
|
||||
import org.wildfly.security.http.Scope;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.cert.X509Certificate;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class ElytronHttpFacade implements OIDCHttpFacade {
|
||||
|
||||
static final String UNDERTOW_EXCHANGE = ElytronHttpFacade.class.getName() + ".undertow.exchange";
|
||||
private static final boolean elyweb163Workaround;
|
||||
private static final Logger log = Logger.getLogger(ElytronHttpFacade.class);
|
||||
|
||||
private final HttpServerRequest request;
|
||||
private final CallbackHandler callbackHandler;
|
||||
private final AdapterTokenStore tokenStore;
|
||||
private final AdapterDeploymentContext deploymentContext;
|
||||
private Consumer<HttpServerResponse> responseConsumer;
|
||||
private ElytronAccount account;
|
||||
private SecurityIdentity securityIdentity;
|
||||
private boolean restored;
|
||||
private final Map<String, String> headers = new HashMap<>();
|
||||
protected MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
static {
|
||||
// Issue #10894: ELYWEB-163 workaround should be applied for previous versions of wildfly/EAP
|
||||
boolean tmpElyweb163Workaround = false;
|
||||
String prop = System.getProperty("org.keycloak.adapters.elytronweb.ELYWEB-163.workaround");
|
||||
if (prop != null) {
|
||||
tmpElyweb163Workaround = Boolean.parseBoolean(prop);
|
||||
log.tracef("Forcing workaround for issue ELYWEB-163 in elytron-web %b", tmpElyweb163Workaround);
|
||||
} else {
|
||||
try {
|
||||
Class clazz = ElytronHttpFacade.class.getClassLoader().loadClass("org.wildfly.elytron.web.undertow.server.ElytronHttpExchange");
|
||||
String version = clazz.getPackage().getImplementationVersion();
|
||||
Integer[] array = parseVersion(version);
|
||||
// bug is fixed in 1.9.2 and 1.10.1
|
||||
tmpElyweb163Workaround = array != null
|
||||
&& (versionIsLessThan(array, new Integer[]{1, 9, 2})
|
||||
|| (versionIsLessThan(array, new Integer[]{1, 10, 1}) && versionIsGreaterOrEqualThan(array, new Integer[]{1, 10, 0})));
|
||||
log.tracef("Version detected for elytron-web %s workaround for ELYWEB-163 %b", version, tmpElyweb163Workaround);
|
||||
} catch (Exception e) {
|
||||
log.tracef(e, "Cannot detect version of elytron-web workaround for ELYWEB-163 %b", tmpElyweb163Workaround);
|
||||
}
|
||||
}
|
||||
elyweb163Workaround = tmpElyweb163Workaround;
|
||||
}
|
||||
|
||||
private static Integer[] parseVersion(String version) {
|
||||
if (version != null) {
|
||||
String[] versionArray = version.split(Pattern.quote("."));
|
||||
List<Integer> versionList = new ArrayList<>();
|
||||
for (int i = 0; i < versionArray.length; i++) {
|
||||
if (versionArray[i].matches("[0-9]+")) {
|
||||
versionList.add(Integer.parseInt(versionArray[i]));
|
||||
}
|
||||
}
|
||||
if (!versionList.isEmpty()) {
|
||||
return versionList.toArray(new Integer[0]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean versionIsLessThan(Integer[] array1, Integer[] array2) {
|
||||
if (array1 == null || array2 == null || array1.length == 0 || array2.length == 0) {
|
||||
throw new IllegalArgumentException("Arrays cannot be null or empty");
|
||||
}
|
||||
for (int i = 0; i < array1.length && i < array2.length; i++) {
|
||||
if (array1[i] < array2[i]) {
|
||||
return true;
|
||||
} else if (array1[i] > array2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// all the numbers are equal til now, 1.1 < 1.1.1
|
||||
return array1.length < array2.length;
|
||||
}
|
||||
|
||||
private static boolean versionIsGreaterOrEqualThan(Integer[] array1, Integer[] array2) {
|
||||
return !versionIsLessThan(array1, array2);
|
||||
}
|
||||
|
||||
public ElytronHttpFacade(HttpServerRequest request, AdapterDeploymentContext deploymentContext, CallbackHandler handler) {
|
||||
this.request = request;
|
||||
this.deploymentContext = deploymentContext;
|
||||
this.callbackHandler = handler;
|
||||
this.tokenStore = createTokenStore();
|
||||
this.responseConsumer = response -> {};
|
||||
}
|
||||
|
||||
void authenticationComplete(ElytronAccount account, boolean storeToken) {
|
||||
this.securityIdentity = SecurityIdentityUtil.authorize(this.callbackHandler, account.getPrincipal());
|
||||
|
||||
if (securityIdentity != null) {
|
||||
this.account = account;
|
||||
RefreshableKeycloakSecurityContext keycloakSecurityContext = account.getKeycloakSecurityContext();
|
||||
account.setCurrentRequestInfo(keycloakSecurityContext.getDeployment(), this.tokenStore);
|
||||
if (storeToken) {
|
||||
this.tokenStore.saveAccountInfo(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void authenticationComplete() {
|
||||
if (securityIdentity != null) {
|
||||
HttpScope requestScope = request.getScope(Scope.EXCHANGE);
|
||||
RefreshableKeycloakSecurityContext keycloakSecurityContext = account.getKeycloakSecurityContext();
|
||||
|
||||
requestScope.setAttachment(KeycloakSecurityContext.class.getName(), keycloakSecurityContext);
|
||||
|
||||
this.request.authenticationComplete(response -> {
|
||||
if (!restored) {
|
||||
responseConsumer.accept(response);
|
||||
}
|
||||
}, () -> ((ElytronTokeStore) tokenStore).logout(true));
|
||||
}
|
||||
}
|
||||
|
||||
void authenticationFailed() {
|
||||
this.request.authenticationFailed("Authentication Failed", response -> responseConsumer.accept(response));
|
||||
}
|
||||
|
||||
void noAuthenticationInProgress() {
|
||||
this.request.noAuthenticationInProgress();
|
||||
}
|
||||
|
||||
void noAuthenticationInProgress(AuthChallenge challenge) {
|
||||
if (challenge != null) {
|
||||
challenge.challenge(this);
|
||||
}
|
||||
this.request.noAuthenticationInProgress(response -> responseConsumer.accept(response));
|
||||
}
|
||||
|
||||
void authenticationInProgress() {
|
||||
this.request.authenticationInProgress(response -> responseConsumer.accept(response));
|
||||
}
|
||||
|
||||
HttpScope getScope(Scope scope) {
|
||||
return request.getScope(scope);
|
||||
}
|
||||
|
||||
HttpScope getScope(Scope scope, String id) {
|
||||
return request.getScope(scope, id);
|
||||
}
|
||||
|
||||
Collection<String> getScopeIds(Scope scope) {
|
||||
return request.getScopeIds(scope);
|
||||
}
|
||||
|
||||
AdapterTokenStore getTokenStore() {
|
||||
return this.tokenStore;
|
||||
}
|
||||
|
||||
KeycloakDeployment getDeployment() {
|
||||
return deploymentContext.resolveDeployment(this);
|
||||
}
|
||||
|
||||
private AdapterTokenStore createTokenStore() {
|
||||
KeycloakDeployment deployment = getDeployment();
|
||||
|
||||
if (TokenStore.SESSION.equals(deployment.getTokenStore())) {
|
||||
return new ElytronSessionTokenStore(this, this.callbackHandler);
|
||||
} else {
|
||||
return new ElytronCookieTokenStore(this, this.callbackHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return new Request() {
|
||||
private InputStream inputStream;
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return request.getRequestMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getURI() {
|
||||
if (elyweb163Workaround) {
|
||||
try {
|
||||
return URLDecoder.decode(request.getRequestURI().toString(), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Failed to decode request URI", e);
|
||||
}
|
||||
} else {
|
||||
return request.getRequestURI().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
return request.getRequestPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return request.getRequestURI().getScheme().equals("https");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getFirstParameterValue(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParamValue(String param) {
|
||||
if (elyweb163Workaround) {
|
||||
URI requestURI = request.getRequestURI();
|
||||
String query = requestURI.getQuery();
|
||||
if (query != null) {
|
||||
String[] parameters = query.split("&");
|
||||
for (String parameter : parameters) {
|
||||
String[] keyValue = parameter.split("=", 2);
|
||||
if (keyValue[0].equals(param)) {
|
||||
try {
|
||||
return URLDecoder.decode(keyValue[1], "UTF-8");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to decode request URI", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
if (queryParameters == null) {
|
||||
queryParameters = UriUtils.decodeQueryString(request.getRequestURI().getRawQuery());
|
||||
}
|
||||
return queryParameters.getFirst(param);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cookie getCookie(final String cookieName) {
|
||||
List<HttpServerCookie> cookies = request.getCookies();
|
||||
|
||||
if (cookies != null) {
|
||||
for (HttpServerCookie cookie : cookies) {
|
||||
if (cookie.getName().equals(cookieName)) {
|
||||
return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
return request.getFirstRequestHeaderValue(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getHeaders(String name) {
|
||||
return request.getRequestHeaderValues(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return getInputStream(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(boolean buffered) {
|
||||
if (inputStream != null) {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
if (buffered) {
|
||||
HttpScope exchangeScope = getScope(Scope.EXCHANGE);
|
||||
HttpServerExchange exchange = ProtectedHttpServerExchange.class.cast(exchangeScope.getAttachment(UNDERTOW_EXCHANGE)).getExchange();
|
||||
ServletRequestContext context = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
|
||||
ServletRequest servletRequest = context.getServletRequest();
|
||||
|
||||
inputStream = new BufferedInputStream(exchange.getInputStream());
|
||||
|
||||
context.setServletRequest(new HttpServletRequestWrapper((HttpServletRequest) servletRequest) {
|
||||
@Override
|
||||
public ServletInputStream getInputStream() {
|
||||
inputStream.mark(0);
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
return request.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddr() {
|
||||
InetSocketAddress sourceAddress = request.getSourceAddress();
|
||||
if (sourceAddress == null) {
|
||||
return "";
|
||||
}
|
||||
InetAddress address = sourceAddress.getAddress();
|
||||
if (address == null) {
|
||||
// this is unresolved, so we just return the host name not exactly spec, but if the name should be
|
||||
// resolved then a PeerNameResolvingHandler should be used and this is probably better than just
|
||||
// returning null
|
||||
return sourceAddress.getHostString();
|
||||
}
|
||||
return address.getHostAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setError(AuthenticationError error) {
|
||||
request.getScope(Scope.EXCHANGE).setAttachment(AuthenticationError.class.getName(), error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setError(LogoutError error) {
|
||||
request.getScope(Scope.EXCHANGE).setAttachment(LogoutError.class.getName(), error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return new Response() {
|
||||
|
||||
@Override
|
||||
public void setStatus(final int status) {
|
||||
if (status < 200 || status > 300) {
|
||||
responseConsumer = responseConsumer.andThen(response -> response.setStatusCode(status));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(final String name, final String value) {
|
||||
headers.put(name, value);
|
||||
responseConsumer = responseConsumer.andThen(new Consumer<HttpServerResponse>() {
|
||||
@Override
|
||||
public void accept(HttpServerResponse response) {
|
||||
String latestValue = headers.get(name);
|
||||
|
||||
if (latestValue.equals(value)) {
|
||||
response.addResponseHeader(name, latestValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value) {
|
||||
addHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCookie(final String name, final String path) {
|
||||
responseConsumer = responseConsumer.andThen(response -> setCookie(name, "", path, null, 0, false, false, response));
|
||||
HttpScope exchangeScope = getScope(Scope.EXCHANGE);
|
||||
ProtectedHttpServerExchange undertowExchange = ProtectedHttpServerExchange.class.cast(exchangeScope.getAttachment(UNDERTOW_EXCHANGE));
|
||||
|
||||
if (undertowExchange != null) {
|
||||
CookieImpl cookie = new CookieImpl(name, "");
|
||||
|
||||
cookie.setMaxAge(0);
|
||||
cookie.setPath(path);
|
||||
|
||||
undertowExchange.getExchange().setResponseCookie(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCookie(final String name, final String value, final String path, final String domain, final int maxAge, final boolean secure, final boolean httpOnly) {
|
||||
responseConsumer = responseConsumer.andThen(response -> setCookie(name, value, path, domain, maxAge, secure, httpOnly, response));
|
||||
}
|
||||
|
||||
private void setCookie(final String name, final String value, final String path, final String domain, final int maxAge, final boolean secure, final boolean httpOnly, HttpServerResponse response) {
|
||||
response.setResponseCookie(new HttpServerCookie() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHttpOnly() {
|
||||
return httpOnly;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
responseConsumer = responseConsumer.andThen(new Consumer<HttpServerResponse>() {
|
||||
@Override
|
||||
public void accept(HttpServerResponse httpServerResponse) {
|
||||
try {
|
||||
httpServerResponse.getOutputStream().write(stream.toByteArray());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to write to response output stream", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int code) {
|
||||
setStatus(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(final int code, final String message) {
|
||||
responseConsumer = responseConsumer.andThen(response -> {
|
||||
response.setStatusCode(code);
|
||||
response.addResponseHeader("Content-Type", "text/html");
|
||||
try {
|
||||
response.getOutputStream().write(message.getBytes());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSecurityContext getSecurityContext() {
|
||||
if (account == null) {
|
||||
return null;
|
||||
}
|
||||
return this.account.getKeycloakSecurityContext();
|
||||
}
|
||||
|
||||
public boolean restoreRequest() {
|
||||
restored = this.request.resumeRequest();
|
||||
return restored;
|
||||
}
|
||||
|
||||
public void suspendRequest() {
|
||||
responseConsumer = responseConsumer.andThen(httpServerResponse -> request.suspendRequest());
|
||||
}
|
||||
|
||||
public boolean isAuthorized() {
|
||||
return this.securityIdentity != null;
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.adapters.BearerTokenRequestAuthenticator;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
import org.wildfly.security.http.HttpScope;
|
||||
import org.wildfly.security.http.Scope;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ElytronRequestAuthenticator extends RequestAuthenticator {
|
||||
|
||||
public ElytronRequestAuthenticator(CallbackHandler callbackHandler, ElytronHttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort) {
|
||||
super(facade, deployment, facade.getTokenStore(), sslRedirectPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthOutcome authenticate() {
|
||||
AuthOutcome authenticate = super.authenticate();
|
||||
|
||||
if (AuthOutcome.AUTHENTICATED.equals(authenticate)) {
|
||||
if (!getElytronHttpFacade().isAuthorized()) {
|
||||
return AuthOutcome.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return authenticate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuthRequestAuthenticator createOAuthAuthenticator() {
|
||||
return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
|
||||
getElytronHttpFacade().authenticationComplete(new ElytronAccount(principal), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
|
||||
getElytronHttpFacade().authenticationComplete(new ElytronAccount(principal), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String changeHttpSessionId(boolean create) {
|
||||
HttpScope session = getElytronHttpFacade().getScope(Scope.SESSION);
|
||||
|
||||
if (create) {
|
||||
if (!session.exists()) {
|
||||
session.create();
|
||||
}
|
||||
}
|
||||
|
||||
return session != null ? session.getID() : null;
|
||||
}
|
||||
|
||||
private ElytronHttpFacade getElytronHttpFacade() {
|
||||
return (ElytronHttpFacade) facade;
|
||||
}
|
||||
}
|
|
@ -1,265 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import static org.keycloak.adapters.elytron.ElytronHttpFacade.UNDERTOW_EXCHANGE;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.server.session.Session;
|
||||
import io.undertow.server.session.SessionConfig;
|
||||
import io.undertow.server.session.SessionManager;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterUtils;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.UserSessionManagement;
|
||||
import org.wildfly.security.http.HttpScope;
|
||||
import org.wildfly.security.http.HttpScopeNotification;
|
||||
import org.wildfly.security.http.Scope;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ElytronSessionTokenStore implements ElytronTokeStore, UserSessionManagement {
|
||||
|
||||
private static Logger log = Logger.getLogger(ElytronSessionTokenStore.class);
|
||||
|
||||
private final ElytronHttpFacade httpFacade;
|
||||
private final CallbackHandler callbackHandler;
|
||||
|
||||
public ElytronSessionTokenStore(ElytronHttpFacade httpFacade, CallbackHandler callbackHandler) {
|
||||
this.httpFacade = httpFacade;
|
||||
this.callbackHandler = callbackHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCurrentToken() {
|
||||
HttpScope session = httpFacade.getScope(Scope.SESSION);
|
||||
if (session == null || !session.exists()) return;
|
||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
|
||||
if (securityContext == null) return;
|
||||
|
||||
// just in case session got serialized
|
||||
if (securityContext.getDeployment() == null) securityContext.setCurrentRequestInfo(httpFacade.getDeployment(), this);
|
||||
|
||||
if (securityContext.isActive() && !securityContext.getDeployment().isAlwaysRefreshToken()) return;
|
||||
|
||||
// FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will
|
||||
// not be updated
|
||||
boolean success = securityContext.refreshExpiredToken(false);
|
||||
if (success && securityContext.isActive()) return;
|
||||
|
||||
// Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
|
||||
session.setAttachment(KeycloakSecurityContext.class.getName(), null);
|
||||
session.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCached(RequestAuthenticator authenticator) {
|
||||
HttpScope session = this.httpFacade.getScope(Scope.SESSION);
|
||||
|
||||
if (session == null || !session.supportsAttachments()) {
|
||||
log.debug("session was null, returning null");
|
||||
return false;
|
||||
}
|
||||
|
||||
ElytronAccount account;
|
||||
|
||||
try {
|
||||
account = (ElytronAccount) session.getAttachment(ElytronAccount.class.getName());
|
||||
} catch (IllegalStateException e) {
|
||||
log.debug("session was invalidated. Return false.");
|
||||
return false;
|
||||
}
|
||||
if (account == null) {
|
||||
log.debug("Account was not in session, returning null");
|
||||
return false;
|
||||
}
|
||||
|
||||
KeycloakDeployment deployment = httpFacade.getDeployment();
|
||||
|
||||
if (!deployment.getRealm().equals(account.getKeycloakSecurityContext().getRealm())) {
|
||||
log.debug("Account in session belongs to a different realm than for this request.");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean active = account.checkActive();
|
||||
|
||||
if (!active) {
|
||||
active = account.tryRefresh();
|
||||
}
|
||||
|
||||
if (active) {
|
||||
log.debug("Cached account found");
|
||||
restoreRequest();
|
||||
httpFacade.authenticationComplete(account, true);
|
||||
return true;
|
||||
} else {
|
||||
log.debug("Refresh failed. Account was not active. Returning null and invalidating Http session");
|
||||
try {
|
||||
session.setAttachment(KeycloakSecurityContext.class.getName(), null);
|
||||
session.setAttachment(ElytronAccount.class.getName(), null);
|
||||
session.invalidate();
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to invalidate session, might already be invalidated");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||
HttpScope session = this.httpFacade.getScope(Scope.SESSION);
|
||||
|
||||
if (!session.exists()) {
|
||||
session.create();
|
||||
session.registerForNotification(httpScopeNotification -> {
|
||||
if (!httpScopeNotification.isOfType(HttpScopeNotification.SessionNotificationType.UNDEPLOY)) {
|
||||
HttpScope invalidated = httpScopeNotification.getScope(Scope.SESSION);
|
||||
|
||||
if (invalidated != null) {
|
||||
invalidated.setAttachment(ElytronAccount.class.getName(), null);
|
||||
invalidated.setAttachment(KeycloakSecurityContext.class.getName(), null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
session.setAttachment(ElytronAccount.class.getName(), account);
|
||||
session.setAttachment(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
|
||||
|
||||
HttpScope scope = this.httpFacade.getScope(Scope.EXCHANGE);
|
||||
|
||||
scope.setAttachment(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() {
|
||||
logout(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
|
||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(this.httpFacade.getDeployment(), securityContext.getToken()), securityContext);
|
||||
saveAccountInfo(new ElytronAccount(principal));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest() {
|
||||
this.httpFacade.suspendRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRequest() {
|
||||
return this.httpFacade.restoreRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(boolean glo) {
|
||||
HttpScope session = this.httpFacade.getScope(Scope.SESSION);
|
||||
|
||||
if (!session.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
|
||||
|
||||
try {
|
||||
if (glo && ksc != null) {
|
||||
KeycloakDeployment deployment = httpFacade.getDeployment();
|
||||
|
||||
session.invalidate();
|
||||
|
||||
if (!deployment.isBearerOnly() && ksc != null && ksc instanceof RefreshableKeycloakSecurityContext) {
|
||||
((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
|
||||
}
|
||||
} else {
|
||||
session.setAttachment(ElytronAccount.class.getName(), null);
|
||||
session.setAttachment(KeycloakSecurityContext.class.getName(), null);
|
||||
}
|
||||
} catch (IllegalStateException ise) {
|
||||
// Session may be already logged-out in case that app has adminUrl
|
||||
log.debugf("Session %s logged-out already", session.getID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logoutAll() {
|
||||
Collection<String> sessions = httpFacade.getScopeIds(Scope.SESSION);
|
||||
logoutHttpSessions(new ArrayList<>(sessions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logoutHttpSessions(List<String> ids) {
|
||||
HttpServerExchange exchange = ProtectedHttpServerExchange.class.cast(httpFacade.getScope(Scope.EXCHANGE).getAttachment(UNDERTOW_EXCHANGE)).getExchange();
|
||||
ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
|
||||
SessionManager sessionManager = servletRequestContext.getDeployment().getSessionManager();
|
||||
final boolean isDistributableSessionManager = sessionManager.getClass().getName().equals("org.wildfly.clustering.web.undertow.session.DistributableSessionManager");
|
||||
|
||||
for (String id : ids) {
|
||||
// TODO: Workaround for WFLY-3345. Remove this once we fix KEYCLOAK-733. Same applies to legacy wildfly adapter.
|
||||
Session session;
|
||||
if (isDistributableSessionManager) {
|
||||
session = sessionManager.getSession(exchange, new SessionConfig() {
|
||||
|
||||
@Override
|
||||
public void setSessionId(HttpServerExchange exchange, String sessionId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSession(HttpServerExchange exchange, String sessionId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findSessionId(HttpServerExchange exchange) {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rewriteUrl(String originalUrl, String sessionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
session = sessionManager.getSession(id);
|
||||
}
|
||||
|
||||
if (session != null) {
|
||||
session.invalidate(exchange);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public interface ElytronTokeStore extends AdapterTokenStore {
|
||||
void logout(boolean glo);
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* <p>A {@link ServletContextListener} that parses the keycloak adapter configuration and set the same configuration
|
||||
* as a {@link ServletContext} attribute in order to provide to {@link KeycloakHttpServerAuthenticationMechanism} a way
|
||||
* to obtain the configuration when processing requests.
|
||||
*
|
||||
* <p>This listener should be automatically registered to a deployment using the subsystem.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakConfigurationServletListener implements ServletContextListener {
|
||||
|
||||
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = AdapterDeploymentContext.class.getName();
|
||||
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON = AdapterDeploymentContext.class.getName() + ".elytron";
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext servletContext = sce.getServletContext();
|
||||
String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
|
||||
KeycloakConfigResolver configResolver;
|
||||
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) servletContext.getAttribute(AdapterDeploymentContext.class.getName());
|
||||
|
||||
if (deploymentContext == null) {
|
||||
if (configResolverClass != null) {
|
||||
try {
|
||||
configResolver = (KeycloakConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
|
||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
||||
} catch (Exception ex) {
|
||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||
}
|
||||
} else {
|
||||
InputStream is = getConfigInputStream(servletContext);
|
||||
|
||||
KeycloakDeployment deployment;
|
||||
|
||||
if (is == null) {
|
||||
deployment = new KeycloakDeployment();
|
||||
} else {
|
||||
deployment = KeycloakDeploymentBuilder.build(is);
|
||||
}
|
||||
|
||||
deploymentContext = new AdapterDeploymentContext(deployment);
|
||||
}
|
||||
}
|
||||
|
||||
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
||||
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON, deploymentContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
|
||||
}
|
||||
|
||||
private InputStream getConfigInputStream(ServletContext servletContext) {
|
||||
InputStream is = getJSONFromServletContext(servletContext);
|
||||
|
||||
if (is == null) {
|
||||
String path = servletContext.getInitParameter("keycloak.config.file");
|
||||
|
||||
if (path == null) {
|
||||
is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json");
|
||||
} else {
|
||||
try {
|
||||
is = new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
private InputStream getJSONFromServletContext(ServletContext servletContext) {
|
||||
String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ByteArrayInputStream(json.getBytes());
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.AuthenticatedActionsHandler;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.NodesRegistrationManagement;
|
||||
import org.keycloak.adapters.PreAuthActionsHandler;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.AuthChallenge;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
import org.keycloak.adapters.spi.UserSessionManagement;
|
||||
import org.wildfly.security.http.HttpAuthenticationException;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanism;
|
||||
import org.wildfly.security.http.HttpServerRequest;
|
||||
import org.wildfly.security.http.Scope;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
|
||||
|
||||
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanism.class);
|
||||
static final String NAME = "KEYCLOAK";
|
||||
|
||||
private final Map<String, ?> properties;
|
||||
private final CallbackHandler callbackHandler;
|
||||
private final AdapterDeploymentContext deploymentContext;
|
||||
private final NodesRegistrationManagement nodesRegistrationManagement;
|
||||
|
||||
public KeycloakHttpServerAuthenticationMechanism(Map<String, ?> properties, CallbackHandler callbackHandler, AdapterDeploymentContext deploymentContext, NodesRegistrationManagement nodesRegistrationManagement) {
|
||||
this.properties = properties;
|
||||
this.callbackHandler = callbackHandler;
|
||||
this.deploymentContext = deploymentContext;
|
||||
this.nodesRegistrationManagement = nodesRegistrationManagement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMechanismName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluateRequest(HttpServerRequest request) throws HttpAuthenticationException {
|
||||
LOGGER.debugf("Evaluating request for path [%s]", request.getRequestURI());
|
||||
AdapterDeploymentContext deploymentContext = getDeploymentContext(request);
|
||||
|
||||
if (deploymentContext == null) {
|
||||
LOGGER.debugf("Ignoring request for path [%s] from mechanism [%s]. No deployment context found.", request.getRequestURI(), getMechanismName());
|
||||
request.noAuthenticationInProgress();
|
||||
return;
|
||||
}
|
||||
|
||||
ElytronHttpFacade httpFacade = new ElytronHttpFacade(request, deploymentContext, callbackHandler);
|
||||
KeycloakDeployment deployment = httpFacade.getDeployment();
|
||||
|
||||
if (!deployment.isConfigured()) {
|
||||
request.noAuthenticationInProgress();
|
||||
return;
|
||||
}
|
||||
|
||||
RequestAuthenticator authenticator = createRequestAuthenticator(request, httpFacade, deployment);
|
||||
|
||||
httpFacade.getTokenStore().checkCurrentToken();
|
||||
|
||||
if (preActions(httpFacade, deploymentContext)) {
|
||||
LOGGER.debugf("Pre-actions has aborted the evaluation of [%s]", request.getRequestURI());
|
||||
httpFacade.authenticationInProgress();
|
||||
return;
|
||||
}
|
||||
|
||||
AuthOutcome outcome = authenticator.authenticate();
|
||||
|
||||
if (AuthOutcome.AUTHENTICATED.equals(outcome)) {
|
||||
if (new AuthenticatedActionsHandler(deployment, httpFacade).handledRequest()) {
|
||||
httpFacade.authenticationInProgress();
|
||||
} else {
|
||||
httpFacade.authenticationComplete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
AuthChallenge challenge = authenticator.getChallenge();
|
||||
|
||||
if (challenge != null) {
|
||||
httpFacade.noAuthenticationInProgress(challenge);
|
||||
return;
|
||||
}
|
||||
|
||||
if (AuthOutcome.FAILED.equals(outcome)) {
|
||||
httpFacade.getResponse().setStatus(403);
|
||||
httpFacade.authenticationFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
httpFacade.noAuthenticationInProgress();
|
||||
}
|
||||
|
||||
private ElytronRequestAuthenticator createRequestAuthenticator(HttpServerRequest request, ElytronHttpFacade httpFacade, KeycloakDeployment deployment) {
|
||||
return new ElytronRequestAuthenticator(this.callbackHandler, httpFacade, deployment, getConfidentialPort(request));
|
||||
}
|
||||
|
||||
private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
||||
if (this.deploymentContext == null) {
|
||||
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON);
|
||||
}
|
||||
|
||||
return this.deploymentContext;
|
||||
}
|
||||
|
||||
private boolean preActions(ElytronHttpFacade httpFacade, AdapterDeploymentContext deploymentContext) {
|
||||
nodesRegistrationManagement.tryRegister(httpFacade.getDeployment());
|
||||
|
||||
PreAuthActionsHandler preActions = new PreAuthActionsHandler(UserSessionManagement.class.cast(httpFacade.getTokenStore()), deploymentContext, httpFacade);
|
||||
|
||||
return preActions.handleRequest();
|
||||
}
|
||||
|
||||
// TODO: obtain confidential port from Elytron
|
||||
private int getConfidentialPort(HttpServerRequest request) {
|
||||
return 8443;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.NodesRegistrationManagement;
|
||||
import org.wildfly.security.http.HttpAuthenticationException;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanism;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
|
||||
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakHttpServerAuthenticationMechanismFactory implements HttpServerAuthenticationMechanismFactory {
|
||||
|
||||
private final AdapterDeploymentContext deploymentContext;
|
||||
private final NodesRegistrationManagement nodesRegistrationManagement;
|
||||
|
||||
/**
|
||||
* <p>Creates a new instance.
|
||||
*
|
||||
* <p>A default constructor is necessary in order to allow this factory to be loaded via {@link java.util.ServiceLoader}.
|
||||
*/
|
||||
public KeycloakHttpServerAuthenticationMechanismFactory() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public KeycloakHttpServerAuthenticationMechanismFactory(AdapterDeploymentContext deploymentContext) {
|
||||
this.deploymentContext = deploymentContext;
|
||||
this.nodesRegistrationManagement = new NodesRegistrationManagement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getMechanismNames(Map<String, ?> properties) {
|
||||
return new String[] {KeycloakHttpServerAuthenticationMechanism.NAME};
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServerAuthenticationMechanism createAuthenticationMechanism(String mechanismName, Map<String, ?> properties, CallbackHandler callbackHandler) throws HttpAuthenticationException {
|
||||
Map<String, Object> mechanismProperties = new HashMap();
|
||||
|
||||
mechanismProperties.putAll(properties);
|
||||
|
||||
if (KeycloakHttpServerAuthenticationMechanism.NAME.equals(mechanismName)) {
|
||||
return new KeycloakHttpServerAuthenticationMechanism(properties, callbackHandler, this.deploymentContext, nodesRegistrationManagement);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.nodesRegistrationManagement.stop();
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Set;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.adapters.AdapterUtils;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.wildfly.security.auth.SupportLevel;
|
||||
import org.wildfly.security.auth.server.RealmIdentity;
|
||||
import org.wildfly.security.auth.server.RealmUnavailableException;
|
||||
import org.wildfly.security.auth.server.SecurityRealm;
|
||||
import org.wildfly.security.authz.Attributes;
|
||||
import org.wildfly.security.authz.AuthorizationIdentity;
|
||||
import org.wildfly.security.authz.MapAttributes;
|
||||
import org.wildfly.security.authz.RoleDecoder;
|
||||
import org.wildfly.security.credential.Credential;
|
||||
import org.wildfly.security.evidence.Evidence;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakSecurityRealm implements SecurityRealm {
|
||||
|
||||
@Override
|
||||
public RealmIdentity getRealmIdentity(Principal principal) throws RealmUnavailableException {
|
||||
if (principal instanceof KeycloakPrincipal) {
|
||||
return createRealmIdentity((KeycloakPrincipal) principal);
|
||||
}
|
||||
return RealmIdentity.NON_EXISTENT;
|
||||
}
|
||||
|
||||
private RealmIdentity createRealmIdentity(KeycloakPrincipal principal) {
|
||||
return new RealmIdentity() {
|
||||
@Override
|
||||
public Principal getRealmIdentityPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
|
||||
return SupportLevel.UNSUPPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C extends Credential> C getCredential(Class<C> credentialType) throws RealmUnavailableException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
|
||||
return SupportLevel.SUPPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException {
|
||||
return principal != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() throws RealmUnavailableException {
|
||||
return principal != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
|
||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) principal.getKeycloakSecurityContext();
|
||||
Attributes attributes = new MapAttributes();
|
||||
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
||||
|
||||
attributes.addAll(RoleDecoder.KEY_ROLES, roles);
|
||||
|
||||
return AuthorizationIdentity.basicIdentity(attributes);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
|
||||
return SupportLevel.UNSUPPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
|
||||
return SupportLevel.POSSIBLY_SUPPORTED;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import io.undertow.server.HttpHandler;
|
||||
import io.undertow.servlet.ServletExtension;
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakServletExtension implements ServletExtension {
|
||||
|
||||
@Override
|
||||
public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
|
||||
deploymentInfo.addOuterHandlerChainWrapper(handler -> (HttpHandler) exchange -> {
|
||||
ServletRequest servletRequest = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletRequest();
|
||||
|
||||
servletRequest.setAttribute(ElytronHttpFacade.UNDERTOW_EXCHANGE, new ProtectedHttpServerExchange(exchange));
|
||||
|
||||
handler.handleRequest(exchange);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
|
||||
/**
|
||||
* <p>A wrapper for {@code {@link HttpServerExchange}} accessible only from classes in the same package.
|
||||
*
|
||||
* <p>This class is used to provide to the elytron mechanism access to the current exchange in order to allow making
|
||||
* changes to the exchange (e.g. response) during the evaluation of requests. By default, changes to the exchange are only
|
||||
* propagated after the execution of the mechanism. But in certain situations, such as when making a programmatic logout (HttpServletRequest.logout()) from
|
||||
* within application code, any change made to the exchange is not propagated.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class ProtectedHttpServerExchange {
|
||||
|
||||
private final HttpServerExchange exchange;
|
||||
|
||||
public ProtectedHttpServerExchange(HttpServerExchange exchange) {
|
||||
this.exchange = exchange;
|
||||
}
|
||||
|
||||
HttpServerExchange getExchange() {
|
||||
return exchange;
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.elytron;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.sasl.AuthorizeCallback;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
|
||||
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
|
||||
import org.wildfly.security.auth.callback.IdentityCredentialCallback;
|
||||
import org.wildfly.security.auth.callback.SecurityIdentityCallback;
|
||||
import org.wildfly.security.auth.server.SecurityIdentity;
|
||||
import org.wildfly.security.credential.BearerTokenCredential;
|
||||
import org.wildfly.security.evidence.Evidence;
|
||||
import org.wildfly.security.http.HttpAuthenticationException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
final class SecurityIdentityUtil {
|
||||
|
||||
static final SecurityIdentity authorize(CallbackHandler callbackHandler, Principal principal) {
|
||||
try {
|
||||
EvidenceVerifyCallback evidenceVerifyCallback = new EvidenceVerifyCallback(new Evidence() {
|
||||
@Override
|
||||
public Principal getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
});
|
||||
|
||||
callbackHandler.handle(new Callback[]{evidenceVerifyCallback});
|
||||
|
||||
if (evidenceVerifyCallback.isVerified()) {
|
||||
AuthorizeCallback authorizeCallback = new AuthorizeCallback(null, null);
|
||||
|
||||
try {
|
||||
callbackHandler.handle(new Callback[] {authorizeCallback});
|
||||
|
||||
authorizeCallback.isAuthorized();
|
||||
} catch (Exception e) {
|
||||
throw new HttpAuthenticationException(e);
|
||||
}
|
||||
|
||||
SecurityIdentityCallback securityIdentityCallback = new SecurityIdentityCallback();
|
||||
IdentityCredentialCallback credentialCallback = new IdentityCredentialCallback(new BearerTokenCredential(KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext().getTokenString()), true);
|
||||
|
||||
callbackHandler.handle(new Callback[]{credentialCallback, AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
|
||||
|
||||
SecurityIdentity securityIdentity = securityIdentityCallback.getSecurityIdentity();
|
||||
|
||||
return securityIdentity;
|
||||
}
|
||||
} catch (UnsupportedCallbackException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
#
|
||||
# * Copyright 2018 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.
|
||||
#
|
||||
|
||||
#
|
||||
# * Copyright 2018 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.
|
||||
#
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
org.keycloak.adapters.elytron.KeycloakServletExtension
|
|
@ -1,19 +0,0 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
#
|
||||
|
||||
org.keycloak.adapters.elytron.KeycloakHttpServerAuthenticationMechanismFactory
|
|
@ -1,36 +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">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak WildFly Integration</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-wildfly-integration-pom</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>wildfly-subsystem</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -1,113 +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.
|
||||
-->
|
||||
<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/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-wildfly-subsystem</artifactId>
|
||||
<name>Keycloak Wildfly Adapter Subsystem</name>
|
||||
<description/>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<redirectTestOutputToFile>false</redirectTestOutputToFile>
|
||||
<enableAssertions>true</enableAssertions>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>jboss.home</name>
|
||||
<value>${jboss.home}</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
<includes>
|
||||
<include>**/*TestCase.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.core</groupId>
|
||||
<artifactId>wildfly-controller</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.core</groupId>
|
||||
<artifactId>wildfly-server</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${ee.maven.groupId}</groupId>
|
||||
<artifactId>wildfly-web-common</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.common</groupId>
|
||||
<artifactId>wildfly-common</artifactId>
|
||||
<version>${wildfly.common.wildfly.aligned.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.security</groupId>
|
||||
<artifactId>wildfly-elytron</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging-annotations</artifactId>
|
||||
<!-- This is a compile-time dependency of this project, but is not needed at compile or runtime by other
|
||||
projects that depend on this project.-->
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging-processor</artifactId>
|
||||
<!-- This is a compile-time dependency of this project, but is not needed at compile or runtime by other
|
||||
projects that depend on this project.-->
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.wildfly.core</groupId>
|
||||
<artifactId>wildfly-subsystem-test-framework</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.as.controller.AbstractAddStepHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.capability.RuntimeCapability;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Add a deployment to a realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
abstract class AbstractAdapterConfigurationAddHandler extends AbstractAddStepHandler {
|
||||
|
||||
private final boolean elytronEnabled;
|
||||
|
||||
AbstractAdapterConfigurationAddHandler(RuntimeCapability<Void> runtimeCapability, List<SimpleAttributeDefinition> attributes) {
|
||||
super(attributes);
|
||||
elytronEnabled = runtimeCapability != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.addSecureDeployment(operation, context.resolveExpressions(model), elytronEnabled);
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||
import org.jboss.as.controller.operations.validation.IntRangeValidator;
|
||||
import org.jboss.as.controller.operations.validation.StringLengthValidator;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.dmr.ModelType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines attributes and operations for a secure-deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
abstract class AbstractAdapterConfigurationDefinition extends SimpleResourceDefinition {
|
||||
|
||||
protected static final SimpleAttributeDefinition REALM =
|
||||
new SimpleAttributeDefinitionBuilder("realm", ModelType.STRING, true)
|
||||
.setXmlName("realm")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition RESOURCE =
|
||||
new SimpleAttributeDefinitionBuilder("resource", ModelType.STRING, true)
|
||||
.setXmlName("resource")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition USE_RESOURCE_ROLE_MAPPINGS =
|
||||
new SimpleAttributeDefinitionBuilder("use-resource-role-mappings", ModelType.BOOLEAN, true)
|
||||
.setXmlName("use-resource-role-mappings")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition BEARER_ONLY =
|
||||
new SimpleAttributeDefinitionBuilder("bearer-only", ModelType.BOOLEAN, true)
|
||||
.setXmlName("bearer-only")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition ENABLE_BASIC_AUTH =
|
||||
new SimpleAttributeDefinitionBuilder("enable-basic-auth", ModelType.BOOLEAN, true)
|
||||
.setXmlName("enable-basic-auth")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition PUBLIC_CLIENT =
|
||||
new SimpleAttributeDefinitionBuilder("public-client", ModelType.BOOLEAN, true)
|
||||
.setXmlName("public-client")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition TURN_OFF_CHANGE_SESSION =
|
||||
new SimpleAttributeDefinitionBuilder("turn-off-change-session-id-on-login", ModelType.BOOLEAN, true)
|
||||
.setXmlName("turn-off-change-session-id-on-login")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition TOKEN_MINIMUM_TIME_TO_LIVE =
|
||||
new SimpleAttributeDefinitionBuilder("token-minimum-time-to-live", ModelType.INT, true)
|
||||
.setXmlName("token-minimum-time-to-live")
|
||||
.setValidator(new IntRangeValidator(-1, true))
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition MIN_TIME_BETWEEN_JWKS_REQUESTS =
|
||||
new SimpleAttributeDefinitionBuilder("min-time-between-jwks-requests", ModelType.INT, true)
|
||||
.setXmlName("min-time-between-jwks-requests")
|
||||
.setValidator(new IntRangeValidator(-1, true))
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition PUBLIC_KEY_CACHE_TTL =
|
||||
new SimpleAttributeDefinitionBuilder("public-key-cache-ttl", ModelType.INT, true)
|
||||
.setXmlName("public-key-cache-ttl")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new IntRangeValidator(-1, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition ADAPTER_STATE_COOKIE_PATH =
|
||||
new SimpleAttributeDefinitionBuilder("adapter-state-cookie-path", ModelType.STRING, true)
|
||||
.setXmlName("adapter-state-cookie-path")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
|
||||
static final List<SimpleAttributeDefinition> DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||
|
||||
static {
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(REALM);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(ENABLE_BASIC_AUTH);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_CLIENT);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(TURN_OFF_CHANGE_SESSION);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(TOKEN_MINIMUM_TIME_TO_LIVE);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(MIN_TIME_BETWEEN_JWKS_REQUESTS);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_KEY_CACHE_TTL);
|
||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(ADAPTER_STATE_COOKIE_PATH);
|
||||
}
|
||||
|
||||
static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList();
|
||||
|
||||
static {
|
||||
ALL_ATTRIBUTES.addAll(DEPLOYMENT_ONLY_ATTRIBUTES);
|
||||
ALL_ATTRIBUTES.addAll(SharedAttributeDefinitons.ATTRIBUTES);
|
||||
}
|
||||
|
||||
static final Map<String, SimpleAttributeDefinition> XML_ATTRIBUTES = new HashMap<String, SimpleAttributeDefinition>();
|
||||
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
|
||||
XML_ATTRIBUTES.put(def.getXmlName(), def);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<String, SimpleAttributeDefinition> DEFINITION_LOOKUP = new HashMap<String, SimpleAttributeDefinition>();
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
|
||||
DEFINITION_LOOKUP.put(def.getXmlName(), def);
|
||||
}
|
||||
}
|
||||
|
||||
private final AbstractAdapterConfigurationWriteAttributeHandler attrWriteHandler;
|
||||
private final List<SimpleAttributeDefinition> attributes;
|
||||
|
||||
protected AbstractAdapterConfigurationDefinition(String name, List<SimpleAttributeDefinition> attributes, AbstractAdapterConfigurationAddHandler addHandler, AbstractAdapterConfigurationRemoveHandler removeHandler, AbstractAdapterConfigurationWriteAttributeHandler attrWriteHandler) {
|
||||
super(PathElement.pathElement(name),
|
||||
KeycloakExtension.getResourceDescriptionResolver(name),
|
||||
addHandler,
|
||||
removeHandler);
|
||||
this.attributes = attributes;
|
||||
this.attrWriteHandler = attrWriteHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerOperations(resourceRegistration);
|
||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerAttributes(resourceRegistration);
|
||||
for (AttributeDefinition attrDef : this.attributes) {
|
||||
resourceRegistration.registerReadWriteAttribute(attrDef, null, this.attrWriteHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public static SimpleAttributeDefinition lookup(String name) {
|
||||
return DEFINITION_LOOKUP.get(name);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractRemoveStepHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Remove a secure-deployment from a realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
abstract class AbstractAdapterConfigurationRemoveHandler extends AbstractRemoveStepHandler {
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.removeSecureDeployment(operation);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractWriteAttributeHandler;
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Update an attribute on a secure-deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
abstract class AbstractAdapterConfigurationWriteAttributeHandler extends AbstractWriteAttributeHandler<KeycloakAdapterConfigService> {
|
||||
|
||||
AbstractAdapterConfigurationWriteAttributeHandler(List<SimpleAttributeDefinition> definitions) {
|
||||
super(definitions.toArray(new AttributeDefinition[definitions.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode resolvedValue, ModelNode currentValue, HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
hh.setHandback(ckService);
|
||||
ckService.updateSecureDeployment(operation, attributeName, resolvedValue);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode valueToRestore, ModelNode valueToRevert, KeycloakAdapterConfigService ckService) throws OperationFailedException {
|
||||
ckService.updateSecureDeployment(operation, attributeName, valueToRestore);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractAddStepHandler;
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Add a credential to a deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||
*/
|
||||
public class CredentialAddHandler extends AbstractAddStepHandler {
|
||||
|
||||
public CredentialAddHandler(AttributeDefinition... attributes) {
|
||||
super(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.addCredential(operation, context.resolveExpressions(model));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||
import org.jboss.as.controller.operations.validation.StringLengthValidator;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
import org.jboss.dmr.ModelType;
|
||||
|
||||
/**
|
||||
* Defines attributes and operations for a credential.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public class CredentialDefinition extends SimpleResourceDefinition {
|
||||
|
||||
public static final String TAG_NAME = "credential";
|
||||
|
||||
protected static final AttributeDefinition VALUE =
|
||||
new SimpleAttributeDefinitionBuilder("value", ModelType.STRING, false)
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, false, true))
|
||||
.build();
|
||||
|
||||
public CredentialDefinition() {
|
||||
super(PathElement.pathElement(TAG_NAME),
|
||||
KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
|
||||
new CredentialAddHandler(VALUE),
|
||||
CredentialRemoveHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerOperations(resourceRegistration);
|
||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerAttributes(resourceRegistration);
|
||||
resourceRegistration.registerReadWriteAttribute(VALUE, null, new CredentialReadWriteAttributeHandler());
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractWriteAttributeHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Update a credential value.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||
*/
|
||||
public class CredentialReadWriteAttributeHandler extends AbstractWriteAttributeHandler<KeycloakAdapterConfigService> {
|
||||
|
||||
@Override
|
||||
protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode resolvedValue, ModelNode currentValue, AbstractWriteAttributeHandler.HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
|
||||
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.updateCredential(operation, attributeName, resolvedValue);
|
||||
|
||||
hh.setHandback(ckService);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode valueToRestore, ModelNode valueToRevert, KeycloakAdapterConfigService ckService) throws OperationFailedException {
|
||||
ckService.updateCredential(operation, attributeName, valueToRestore);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractRemoveStepHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Remove a credential from a deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||
*/
|
||||
public final class CredentialRemoveHandler extends AbstractRemoveStepHandler {
|
||||
|
||||
public static CredentialRemoveHandler INSTANCE = new CredentialRemoveHandler();
|
||||
|
||||
private CredentialRemoveHandler() {}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.removeCredential(operation);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.web.common.WarMetaData;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
import org.jboss.msc.service.ServiceName;
|
||||
|
||||
/**
|
||||
* Utility class for Elytron integration
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public final class Elytron {
|
||||
|
||||
private static final String DEFAULT_SECURITY_DOMAIN = "other";
|
||||
private static final String UNDERTOW_APPLICATION_SECURITY_DOMAIN = "org.wildfly.undertow.application-security-domain.";
|
||||
|
||||
static boolean isElytronEnabled(DeploymentPhaseContext phaseContext) {
|
||||
String securityDomain = getSecurityDomain(phaseContext.getDeploymentUnit());
|
||||
ServiceName serviceName = ServiceName.parse(new StringBuilder(UNDERTOW_APPLICATION_SECURITY_DOMAIN).append(securityDomain).toString());
|
||||
return phaseContext.getServiceRegistry().getService(serviceName) != null;
|
||||
}
|
||||
|
||||
private static String getSecurityDomain(DeploymentUnit deploymentUnit) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
|
||||
if (warMetaData != null) {
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
|
||||
if (webMetaData != null) {
|
||||
String configuredSecurityDomain = webMetaData.getSecurityDomain();
|
||||
|
||||
if (configuredSecurityDomain != null) {
|
||||
return configuredSecurityDomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT_SECURITY_DOMAIN;
|
||||
}
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import static org.keycloak.subsystem.adapter.extension.Elytron.isElytronEnabled;
|
||||
|
||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||
import org.jboss.as.web.common.WarMetaData;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.metadata.javaee.spec.ParamValueMetaData;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
import org.jboss.metadata.web.spec.ListenerMetaData;
|
||||
import org.jboss.metadata.web.spec.LoginConfigMetaData;
|
||||
import org.keycloak.adapters.elytron.KeycloakConfigurationServletListener;
|
||||
import org.keycloak.subsystem.adapter.logging.KeycloakLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Pass authentication data (keycloak.json) as a servlet context param so it can be read by the KeycloakServletExtension.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||
*/
|
||||
public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitProcessor {
|
||||
protected Logger log = Logger.getLogger(KeycloakAdapterConfigDeploymentProcessor.class);
|
||||
|
||||
// This param name is defined again in Keycloak Undertow Integration class
|
||||
// org.keycloak.adapters.undertow.KeycloakServletExtension. We have this value in
|
||||
// two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
|
||||
public static final String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
|
||||
|
||||
// not sure if we need this yet, keeping here just in case
|
||||
protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) {
|
||||
if (!service.isSecureDeployment(deploymentUnit)) {
|
||||
return;
|
||||
}
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) return;
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) return;
|
||||
|
||||
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
||||
if (loginConfig == null || !loginConfig.getAuthMethod().equalsIgnoreCase("KEYCLOAK")) {
|
||||
return;
|
||||
}
|
||||
|
||||
webMetaData.setSecurityDomain("keycloak");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
if (service.isSecureDeployment(deploymentUnit) && service.isDeploymentConfigured(deploymentUnit)) {
|
||||
addKeycloakAuthData(phaseContext, service);
|
||||
}
|
||||
|
||||
addConfigurationListener(phaseContext);
|
||||
|
||||
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
||||
|
||||
// todo notsure if we need this
|
||||
// addSecurityDomain(deploymentUnit, service);
|
||||
}
|
||||
|
||||
private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, KeycloakAdapterConfigService service) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
throw new DeploymentUnitProcessingException("WarMetaData not found for " + deploymentUnit.getName() + ". Make sure you have specified a WAR as your secure-deployment in the Keycloak subsystem.");
|
||||
}
|
||||
|
||||
addJSONData(service.getJSON(deploymentUnit), warMetaData);
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
webMetaData = new JBossWebMetaData();
|
||||
warMetaData.setMergedJBossWebMetaData(webMetaData);
|
||||
}
|
||||
|
||||
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
||||
if (loginConfig == null) {
|
||||
loginConfig = new LoginConfigMetaData();
|
||||
webMetaData.setLoginConfig(loginConfig);
|
||||
}
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||
}
|
||||
|
||||
private void addJSONData(String json, WarMetaData warMetaData) {
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
webMetaData = new JBossWebMetaData();
|
||||
warMetaData.setMergedJBossWebMetaData(webMetaData);
|
||||
}
|
||||
|
||||
List<ParamValueMetaData> contextParams = webMetaData.getContextParams();
|
||||
if (contextParams == null) {
|
||||
contextParams = new ArrayList<ParamValueMetaData>();
|
||||
}
|
||||
|
||||
ParamValueMetaData param = new ParamValueMetaData();
|
||||
param.setParamName(AUTH_DATA_PARAM_NAME);
|
||||
param.setParamValue(json);
|
||||
contextParams.add(param);
|
||||
|
||||
webMetaData.setContextParams(contextParams);
|
||||
}
|
||||
|
||||
private void addConfigurationListener(DeploymentPhaseContext phaseContext) {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
webMetaData = new JBossWebMetaData();
|
||||
warMetaData.setMergedJBossWebMetaData(webMetaData);
|
||||
}
|
||||
|
||||
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
||||
if (loginConfig == null) {
|
||||
return;
|
||||
}
|
||||
if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isElytronEnabled(phaseContext)) {
|
||||
ListenerMetaData listenerMetaData = new ListenerMetaData();
|
||||
|
||||
listenerMetaData.setListenerClass(KeycloakConfigurationServletListener.class.getName());
|
||||
|
||||
webMetaData.getListeners().add(listenerMetaData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undeploy(DeploymentUnit du) {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,313 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.web.common.WarMetaData;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.dmr.Property;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
||||
|
||||
/**
|
||||
* This service keeps track of the entire Keycloak management model so as to provide
|
||||
* adapter configuration to each deployment at deploy time.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public final class KeycloakAdapterConfigService {
|
||||
|
||||
private static final String CREDENTIALS_JSON_NAME = "credentials";
|
||||
|
||||
private static final String REDIRECT_REWRITE_RULE_JSON_NAME = "redirect-rewrite-rules";
|
||||
|
||||
private static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
|
||||
|
||||
public static KeycloakAdapterConfigService getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final Map<String, ModelNode> realms = new HashMap<String, ModelNode>();
|
||||
|
||||
// keycloak-secured deployments
|
||||
private final Map<String, ModelNode> secureDeployments = new HashMap<String, ModelNode>();
|
||||
private final Set<String> elytronEnabledDeployments = new HashSet<>();
|
||||
|
||||
|
||||
private KeycloakAdapterConfigService() {
|
||||
}
|
||||
|
||||
public void addRealm(ModelNode operation, ModelNode model) {
|
||||
this.realms.put(realmNameFromOp(operation), model.clone());
|
||||
}
|
||||
|
||||
public void updateRealm(ModelNode operation, String attrName, ModelNode resolvedValue) {
|
||||
ModelNode realm = this.realms.get(realmNameFromOp(operation));
|
||||
realm.get(attrName).set(resolvedValue);
|
||||
}
|
||||
|
||||
public void removeRealm(ModelNode operation) {
|
||||
this.realms.remove(realmNameFromOp(operation));
|
||||
}
|
||||
|
||||
public void addSecureDeployment(ModelNode operation, ModelNode model, boolean elytronEnabled) {
|
||||
ModelNode deployment = model.clone();
|
||||
String name = deploymentNameFromOp(operation);
|
||||
this.secureDeployments.put(name, deployment);
|
||||
if (elytronEnabled) {
|
||||
elytronEnabledDeployments.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSecureDeployment(ModelNode operation, String attrName, ModelNode resolvedValue) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentNameFromOp(operation));
|
||||
deployment.get(attrName).set(resolvedValue);
|
||||
}
|
||||
|
||||
public void removeSecureDeployment(ModelNode operation) {
|
||||
String name = deploymentNameFromOp(operation);
|
||||
this.secureDeployments.remove(name);
|
||||
elytronEnabledDeployments.remove(name);
|
||||
}
|
||||
|
||||
public void addCredential(ModelNode operation, ModelNode model) {
|
||||
ModelNode credentials = credentialsFromOp(operation);
|
||||
if (!credentials.isDefined()) {
|
||||
credentials = new ModelNode();
|
||||
}
|
||||
|
||||
String credentialName = credentialNameFromOp(operation);
|
||||
if (!credentialName.contains(".")) {
|
||||
credentials.get(credentialName).set(model.get("value").asString());
|
||||
} else {
|
||||
String[] parts = credentialName.split("\\.");
|
||||
String provider = parts[0];
|
||||
String property = parts[1];
|
||||
ModelNode credential = credentials.get(provider);
|
||||
if (!credential.isDefined()) {
|
||||
credential = new ModelNode();
|
||||
}
|
||||
credential.get(property).set(model.get("value").asString());
|
||||
credentials.set(provider, credential);
|
||||
}
|
||||
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentNameFromOp(operation));
|
||||
deployment.get(CREDENTIALS_JSON_NAME).set(credentials);
|
||||
}
|
||||
|
||||
public void removeCredential(ModelNode operation) {
|
||||
ModelNode credentials = credentialsFromOp(operation);
|
||||
if (!credentials.isDefined()) {
|
||||
throw new RuntimeException("Can not remove credential. No credential defined for deployment in op " + operation.toString());
|
||||
}
|
||||
|
||||
String credentialName = credentialNameFromOp(operation);
|
||||
credentials.remove(credentialName);
|
||||
}
|
||||
|
||||
public void updateCredential(ModelNode operation, String attrName, ModelNode resolvedValue) {
|
||||
ModelNode credentials = credentialsFromOp(operation);
|
||||
if (!credentials.isDefined()) {
|
||||
throw new RuntimeException("Can not update credential. No credential defined for deployment in op " + operation.toString());
|
||||
}
|
||||
|
||||
String credentialName = credentialNameFromOp(operation);
|
||||
credentials.get(credentialName).set(resolvedValue);
|
||||
}
|
||||
|
||||
private ModelNode credentialsFromOp(ModelNode operation) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentNameFromOp(operation));
|
||||
return deployment.get(CREDENTIALS_JSON_NAME);
|
||||
}
|
||||
|
||||
public void addRedirectRewriteRule(ModelNode operation, ModelNode model) {
|
||||
ModelNode redirectRewritesRules = redirectRewriteRuleFromOp(operation);
|
||||
if (!redirectRewritesRules.isDefined()) {
|
||||
redirectRewritesRules = new ModelNode();
|
||||
}
|
||||
String redirectRewriteRuleName = redirectRewriteRule(operation);
|
||||
redirectRewritesRules.get(redirectRewriteRuleName).set(model.get("value").asString());
|
||||
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentNameFromOp(operation));
|
||||
deployment.get(REDIRECT_REWRITE_RULE_JSON_NAME).set(redirectRewritesRules);
|
||||
}
|
||||
|
||||
public void removeRedirectRewriteRule(ModelNode operation) {
|
||||
ModelNode redirectRewritesRules = redirectRewriteRuleFromOp(operation);
|
||||
if (!redirectRewritesRules.isDefined()) {
|
||||
throw new RuntimeException("Can not remove redirect rewrite rule. No rules defined for deployment in op " + operation.toString());
|
||||
}
|
||||
|
||||
String ruleName = credentialNameFromOp(operation);
|
||||
redirectRewritesRules.remove(ruleName);
|
||||
}
|
||||
|
||||
public void updateRedirectRewriteRule(ModelNode operation, String attrName, ModelNode resolvedValue) {
|
||||
ModelNode redirectRewritesRules = redirectRewriteRuleFromOp(operation);
|
||||
if (!redirectRewritesRules.isDefined()) {
|
||||
throw new RuntimeException("Can not update redirect rewrite rule. No rules defined for deployment in op " + operation.toString());
|
||||
}
|
||||
|
||||
String ruleName = credentialNameFromOp(operation);
|
||||
redirectRewritesRules.get(ruleName).set(resolvedValue);
|
||||
}
|
||||
|
||||
private ModelNode redirectRewriteRuleFromOp(ModelNode operation) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentNameFromOp(operation));
|
||||
return deployment.get(REDIRECT_REWRITE_RULE_JSON_NAME);
|
||||
}
|
||||
|
||||
private String realmNameFromOp(ModelNode operation) {
|
||||
return valueFromOpAddress(RealmDefinition.TAG_NAME, operation);
|
||||
}
|
||||
|
||||
private String deploymentNameFromOp(ModelNode operation) {
|
||||
String deploymentName = valueFromOpAddress(SecureDeploymentDefinition.TAG_NAME, operation);
|
||||
|
||||
if (deploymentName == null) {
|
||||
deploymentName = valueFromOpAddress(KeycloakHttpServerAuthenticationMechanismFactoryDefinition.TAG_NAME, operation);
|
||||
}
|
||||
|
||||
if (deploymentName == null) {
|
||||
deploymentName = valueFromOpAddress(SecureServerDefinition.TAG_NAME, operation);
|
||||
}
|
||||
|
||||
if (deploymentName == null) throw new RuntimeException("Can't find deployment name in address " + operation);
|
||||
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
private String credentialNameFromOp(ModelNode operation) {
|
||||
return valueFromOpAddress(CredentialDefinition.TAG_NAME, operation);
|
||||
}
|
||||
|
||||
private String redirectRewriteRule(ModelNode operation) {
|
||||
return valueFromOpAddress(RedirecRewritetRuleDefinition.TAG_NAME, operation);
|
||||
}
|
||||
|
||||
private String valueFromOpAddress(String addrElement, ModelNode operation) {
|
||||
return getValueOfAddrElement(operation.get(ADDRESS), addrElement);
|
||||
}
|
||||
|
||||
private String getValueOfAddrElement(ModelNode address, String elementName) {
|
||||
for (ModelNode element : address.asList()) {
|
||||
if (element.has(elementName)) return element.get(elementName).asString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRealmName(DeploymentUnit deploymentUnit) {
|
||||
ModelNode deployment = getSecureDeployment(deploymentUnit);
|
||||
return deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
|
||||
}
|
||||
|
||||
protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
|
||||
ModelNode deployment = getSecureDeployment(deploymentUnit);
|
||||
if (! deployment.isDefined()) {
|
||||
return false;
|
||||
}
|
||||
ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
|
||||
return resource.isDefined();
|
||||
}
|
||||
|
||||
public String getJSON(DeploymentUnit deploymentUnit) {
|
||||
ModelNode deployment = getSecureDeployment(deploymentUnit);
|
||||
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
ModelNode realm = this.realms.get(realmName);
|
||||
|
||||
ModelNode json = new ModelNode();
|
||||
json.get(RealmDefinition.TAG_NAME).set(realmName);
|
||||
|
||||
// Realm values set first. Some can be overridden by deployment values.
|
||||
if (realm != null) setJSONValues(json, realm);
|
||||
setJSONValues(json, deployment);
|
||||
return json.toJSONString(true);
|
||||
}
|
||||
|
||||
public String getJSON(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
ModelNode realm = this.realms.get(realmName);
|
||||
|
||||
ModelNode json = new ModelNode();
|
||||
json.get(RealmDefinition.TAG_NAME).set(realmName);
|
||||
|
||||
// Realm values set first. Some can be overridden by deployment values.
|
||||
if (realm != null) setJSONValues(json, realm);
|
||||
setJSONValues(json, deployment);
|
||||
return json.toJSONString(true);
|
||||
}
|
||||
|
||||
private void setJSONValues(ModelNode json, ModelNode values) {
|
||||
synchronized (values) {
|
||||
for (Property prop : new ArrayList<>(values.asPropertyList())) {
|
||||
String name = prop.getName();
|
||||
ModelNode value = prop.getValue();
|
||||
if (value.isDefined()) {
|
||||
json.get(name).set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: deployments.size()" + deployments.size());
|
||||
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
return this.secureDeployments.containsKey(deploymentName);
|
||||
}
|
||||
|
||||
public boolean isElytronEnabled(DeploymentUnit deploymentUnit) {
|
||||
return elytronEnabledDeployments.contains(preferredDeploymentName(deploymentUnit));
|
||||
}
|
||||
|
||||
private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
return this.secureDeployments.containsKey(deploymentName)
|
||||
? this.secureDeployments.get(deploymentName)
|
||||
: new ModelNode();
|
||||
}
|
||||
|
||||
// KEYCLOAK-3273: prefer module name if available
|
||||
private String preferredDeploymentName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
String moduleName = webMetaData.getModuleName();
|
||||
if (moduleName != null) return moduleName + ".war";
|
||||
|
||||
return deploymentName;
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.server.deployment.Attachments;
|
||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||
import org.jboss.as.server.deployment.module.ModuleDependency;
|
||||
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
||||
import org.jboss.as.web.common.WarMetaData;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
import org.jboss.metadata.web.spec.LoginConfigMetaData;
|
||||
import org.jboss.modules.Module;
|
||||
import org.jboss.modules.ModuleIdentifier;
|
||||
import org.jboss.modules.ModuleLoader;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public abstract class KeycloakDependencyProcessor implements DeploymentUnitProcessor {
|
||||
|
||||
private static final ModuleIdentifier KEYCLOAK_JBOSS_CORE_ADAPTER = KeycloakSubsystemDefinition.KEYCLOAK_JBOSS_CORE_ADAPTER;
|
||||
private static final ModuleIdentifier KEYCLOAK_CORE_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-adapter-core");
|
||||
private static final ModuleIdentifier KEYCLOAK_CORE = ModuleIdentifier.create("org.keycloak.keycloak-core");
|
||||
private static final ModuleIdentifier KEYCLOAK_COMMON = ModuleIdentifier.create("org.keycloak.keycloak-common");
|
||||
|
||||
@Override
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentUnit)) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
}
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
return;
|
||||
}
|
||||
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
||||
if (loginConfig == null) return;
|
||||
if (loginConfig.getAuthMethod() == null) return;
|
||||
if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) return;
|
||||
}
|
||||
|
||||
final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
|
||||
ModuleLoader moduleLoader = Module.getCallerModuleLoader();
|
||||
if (moduleLoader == null) {
|
||||
moduleLoader = Module.getSystemModuleLoader();
|
||||
}
|
||||
addCommonModules(moduleSpecification, moduleLoader);
|
||||
addPlatformSpecificModules(phaseContext, moduleSpecification, moduleLoader);
|
||||
}
|
||||
|
||||
private void addCommonModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
||||
// ModuleDependency(ModuleLoader moduleLoader, ModuleIdentifier identifier, boolean optional, boolean export, boolean importServices, boolean userSpecified)
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_JBOSS_CORE_ADAPTER, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE_ADAPTER, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_COMMON, false, false, false, false));
|
||||
}
|
||||
|
||||
abstract protected void addPlatformSpecificModules(DeploymentPhaseContext phaseContext, ModuleSpecification moduleSpecification, ModuleLoader moduleLoader);
|
||||
|
||||
@Override
|
||||
public void undeploy(DeploymentUnit du) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import static org.keycloak.subsystem.adapter.extension.Elytron.isElytronEnabled;
|
||||
|
||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||
import org.jboss.as.server.deployment.module.ModuleDependency;
|
||||
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
||||
import org.jboss.modules.ModuleIdentifier;
|
||||
import org.jboss.modules.ModuleLoader;
|
||||
|
||||
/**
|
||||
* Add platform-specific modules for WildFly.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||
*/
|
||||
public class KeycloakDependencyProcessorWildFly extends KeycloakDependencyProcessor {
|
||||
|
||||
private static final ModuleIdentifier KEYCLOAK_ELYTRON_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-elytron-oidc-adapter");
|
||||
|
||||
@Override
|
||||
protected void addPlatformSpecificModules(DeploymentPhaseContext phaseContext, ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
||||
if (isElytronEnabled(phaseContext)) {
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_ELYTRON_ADAPTER, true, false, true, false));
|
||||
} else {
|
||||
throw new RuntimeException("Legacy WildFly security layer is no longer supported by the Keycloak WildFly adapter");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.Extension;
|
||||
import org.jboss.as.controller.ExtensionContext;
|
||||
import org.jboss.as.controller.ModelVersion;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.ResourceDefinition;
|
||||
import org.jboss.as.controller.SubsystemRegistration;
|
||||
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
|
||||
import org.jboss.as.controller.parsing.ExtensionParsingContext;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
import org.keycloak.subsystem.adapter.logging.KeycloakLogger;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
|
||||
|
||||
|
||||
/**
|
||||
* Main Extension class for the subsystem.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public class KeycloakExtension implements Extension {
|
||||
|
||||
public static final String SUBSYSTEM_NAME = "keycloak";
|
||||
public static final String NAMESPACE_1_1 = "urn:jboss:domain:keycloak:1.1";
|
||||
public static final String NAMESPACE_1_2 = "urn:jboss:domain:keycloak:1.2";
|
||||
public static final String CURRENT_NAMESPACE = NAMESPACE_1_2;
|
||||
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
|
||||
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||
private static final String RESOURCE_NAME = KeycloakExtension.class.getPackage().getName() + ".LocalDescriptions";
|
||||
private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1,1,0);
|
||||
static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||
private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
|
||||
static final RealmDefinition REALM_DEFINITION = new RealmDefinition();
|
||||
static final SecureDeploymentDefinition SECURE_DEPLOYMENT_DEFINITION = new SecureDeploymentDefinition();
|
||||
static final SecureServerDefinition SECURE_SERVER_DEFINITION = new SecureServerDefinition();
|
||||
static final CredentialDefinition CREDENTIAL_DEFINITION = new CredentialDefinition();
|
||||
static final RedirecRewritetRuleDefinition REDIRECT_RULE_DEFINITON = new RedirecRewritetRuleDefinition();
|
||||
|
||||
public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
||||
for (String kp : keyPrefix) {
|
||||
prefix.append('.').append(kp);
|
||||
}
|
||||
return new StandardResourceDescriptionResolver(prefix.toString(), RESOURCE_NAME, KeycloakExtension.class.getClassLoader(), true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void initializeParsers(final ExtensionParsingContext context) {
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakExtension.NAMESPACE_1_1, PARSER);
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakExtension.NAMESPACE_1_2, PARSER);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void initialize(final ExtensionContext context) {
|
||||
KeycloakLogger.ROOT_LOGGER.debug("Activating Keycloak Extension");
|
||||
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, MGMT_API_VERSION);
|
||||
|
||||
ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
||||
registration.registerSubModel(REALM_DEFINITION);
|
||||
ManagementResourceRegistration secureDeploymentRegistration = registration.registerSubModel(SECURE_DEPLOYMENT_DEFINITION);
|
||||
secureDeploymentRegistration.registerSubModel(CREDENTIAL_DEFINITION);
|
||||
secureDeploymentRegistration.registerSubModel(REDIRECT_RULE_DEFINITON);
|
||||
|
||||
ManagementResourceRegistration secureServerRegistration = registration.registerSubModel(SECURE_SERVER_DEFINITION);
|
||||
secureServerRegistration.registerSubModel(CREDENTIAL_DEFINITION);
|
||||
secureServerRegistration.registerSubModel(REDIRECT_RULE_DEFINITON);
|
||||
|
||||
subsystem.registerXMLElementWriter(PARSER);
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.msc.service.Service;
|
||||
import org.jboss.msc.service.StartContext;
|
||||
import org.jboss.msc.service.StartException;
|
||||
import org.jboss.msc.service.StopContext;
|
||||
import org.jboss.msc.value.InjectedValue;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.elytron.KeycloakHttpServerAuthenticationMechanismFactory;
|
||||
import org.wildfly.security.auth.server.SecurityDomain;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
|
||||
import org.wildfly.security.http.util.SetMechanismInformationMechanismFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakHttpAuthenticationFactoryService implements Service<HttpServerAuthenticationMechanismFactory> {
|
||||
|
||||
private final String factoryName;
|
||||
private HttpServerAuthenticationMechanismFactory httpAuthenticationFactory;
|
||||
|
||||
public KeycloakHttpAuthenticationFactoryService(String factoryName) {
|
||||
this.factoryName = factoryName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(StartContext context) throws StartException {
|
||||
KeycloakAdapterConfigService adapterConfigService = KeycloakAdapterConfigService.getInstance();
|
||||
String config = adapterConfigService.getJSON(this.factoryName);
|
||||
this.httpAuthenticationFactory = new KeycloakHttpServerAuthenticationMechanismFactory(createDeploymentContext(config.getBytes()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(StopContext context) {
|
||||
this.httpAuthenticationFactory = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServerAuthenticationMechanismFactory getValue() throws IllegalStateException, IllegalArgumentException {
|
||||
return new SetMechanismInformationMechanismFactory(this.httpAuthenticationFactory);
|
||||
}
|
||||
|
||||
private AdapterDeploymentContext createDeploymentContext(byte[] config) {
|
||||
return new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(new ByteArrayInputStream(config)));
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
|
||||
import static org.keycloak.subsystem.adapter.extension.KeycloakHttpServerAuthenticationMechanismFactoryDefinition.KeycloakHttpServerAuthenticationMechanismFactoryAddHandler.HTTP_SERVER_AUTHENTICATION_CAPABILITY;
|
||||
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.as.controller.PathAddress;
|
||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||
import org.jboss.as.controller.capability.RuntimeCapability;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.msc.service.ServiceController;
|
||||
import org.jboss.msc.service.ServiceName;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
|
||||
|
||||
/**
|
||||
* A {@link SimpleResourceDefinition} that can be used to configure a {@link org.keycloak.adapters.elytron.KeycloakHttpServerAuthenticationMechanismFactory}
|
||||
* and expose it as a capability for other subsystems.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class KeycloakHttpServerAuthenticationMechanismFactoryDefinition extends AbstractAdapterConfigurationDefinition {
|
||||
|
||||
static final String TAG_NAME = "http-server-mechanism-factory";
|
||||
|
||||
KeycloakHttpServerAuthenticationMechanismFactoryDefinition() {
|
||||
this(TAG_NAME);
|
||||
}
|
||||
|
||||
KeycloakHttpServerAuthenticationMechanismFactoryDefinition(String tagName) {
|
||||
super(tagName, ALL_ATTRIBUTES, new KeycloakHttpServerAuthenticationMechanismFactoryAddHandler(), new KeycloakHttpServerAuthenticationMechanismFactoryRemoveHandler(), new KeycloakHttpServerAuthenticationMechanismFactoryWriteHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link AbstractAdapterConfigurationAddHandler} that exposes a {@link KeycloakHttpServerAuthenticationMechanismFactoryDefinition}
|
||||
* as a capability through the installation of a {@link KeycloakHttpAuthenticationFactoryService}.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
static final class KeycloakHttpServerAuthenticationMechanismFactoryAddHandler extends AbstractAdapterConfigurationAddHandler {
|
||||
|
||||
static final String HTTP_SERVER_AUTHENTICATION_CAPABILITY = "org.wildfly.security.http-server-mechanism-factory";
|
||||
static final RuntimeCapability<Void> HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY = RuntimeCapability
|
||||
.Builder.of(HTTP_SERVER_AUTHENTICATION_CAPABILITY, true, HttpServerAuthenticationMechanismFactory.class)
|
||||
.build();
|
||||
|
||||
KeycloakHttpServerAuthenticationMechanismFactoryAddHandler() {
|
||||
super(HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY, ALL_ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.performRuntime(context, operation, model);
|
||||
installCapability(context, operation);
|
||||
}
|
||||
|
||||
static void installCapability(OperationContext context, ModelNode operation) {
|
||||
PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
|
||||
String factoryName = pathAddress.getLastElement().getValue();
|
||||
ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
|
||||
KeycloakHttpAuthenticationFactoryService service = new KeycloakHttpAuthenticationFactoryService(factoryName);
|
||||
context.getServiceTarget().addService(serviceName, service).setInitialMode(ServiceController.Mode.ACTIVE).install();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link AbstractAdapterConfigurationRemoveHandler} that handles the removal of {@link KeycloakHttpServerAuthenticationMechanismFactoryDefinition}.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
static final class KeycloakHttpServerAuthenticationMechanismFactoryRemoveHandler extends AbstractAdapterConfigurationRemoveHandler {
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.performRuntime(context, operation, model);
|
||||
PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
|
||||
String factoryName = pathAddress.getLastElement().getValue();
|
||||
ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
|
||||
|
||||
context.removeService(serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recoverServices(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.recoverServices(context, operation, model);
|
||||
KeycloakHttpServerAuthenticationMechanismFactoryAddHandler.installCapability(context, operation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link AbstractAdapterConfigurationWriteAttributeHandler} that updates attributes on a {@link KeycloakHttpServerAuthenticationMechanismFactoryDefinition}.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
static final class KeycloakHttpServerAuthenticationMechanismFactoryWriteHandler extends AbstractAdapterConfigurationWriteAttributeHandler {
|
||||
KeycloakHttpServerAuthenticationMechanismFactoryWriteHandler() {
|
||||
super(ALL_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
|
||||
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.server.AbstractDeploymentChainStep;
|
||||
import org.jboss.as.server.DeploymentProcessorTarget;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||
import org.jboss.as.server.deployment.Phase;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* The Keycloak subsystem add update handler.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
|
||||
|
||||
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
|
||||
|
||||
@Override
|
||||
protected void performBoottime(final OperationContext context, ModelNode operation, final ModelNode model) {
|
||||
context.addStep(new AbstractDeploymentChainStep() {
|
||||
@Override
|
||||
protected void execute(DeploymentProcessorTarget processorTarget) {
|
||||
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME, Phase.DEPENDENCIES, 0, chooseDependencyProcessor());
|
||||
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME,
|
||||
Phase.POST_MODULE, // PHASE
|
||||
Phase.POST_MODULE_VALIDATOR_FACTORY - 1, // PRIORITY
|
||||
chooseConfigDeploymentProcessor());
|
||||
}
|
||||
}, OperationContext.Stage.RUNTIME);
|
||||
}
|
||||
|
||||
private DeploymentUnitProcessor chooseDependencyProcessor() {
|
||||
return new KeycloakDependencyProcessorWildFly();
|
||||
}
|
||||
|
||||
private DeploymentUnitProcessor chooseConfigDeploymentProcessor() {
|
||||
return new KeycloakAdapterConfigDeploymentProcessor();
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
|
||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
import org.jboss.as.controller.registry.RuntimePackageDependency;
|
||||
import org.jboss.modules.ModuleIdentifier;
|
||||
|
||||
/**
|
||||
* Definition of subsystem=keycloak.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
|
||||
|
||||
static final ModuleIdentifier KEYCLOAK_JBOSS_CORE_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-jboss-adapter-core");
|
||||
|
||||
protected KeycloakSubsystemDefinition() {
|
||||
super(KeycloakExtension.SUBSYSTEM_PATH,
|
||||
KeycloakExtension.getResourceDescriptionResolver("subsystem"),
|
||||
KeycloakSubsystemAdd.INSTANCE,
|
||||
ReloadRequiredRemoveStepHandler.INSTANCE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerOperations(resourceRegistration);
|
||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAdditionalRuntimePackages(ManagementResourceRegistration resourceRegistration) {
|
||||
// This module is required by deployment but not referenced by JBoss modules
|
||||
resourceRegistration.registerAdditionalRuntimePackages(
|
||||
RuntimePackageDependency.required(KEYCLOAK_JBOSS_CORE_ADAPTER.getName()));
|
||||
}
|
||||
}
|
|
@ -1,386 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.PathAddress;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
|
||||
import org.jboss.as.controller.operations.common.Util;
|
||||
import org.jboss.as.controller.parsing.ParseUtils;
|
||||
import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.dmr.Property;
|
||||
import org.jboss.staxmapper.XMLElementReader;
|
||||
import org.jboss.staxmapper.XMLElementWriter;
|
||||
import org.jboss.staxmapper.XMLExtendedStreamReader;
|
||||
import org.jboss.staxmapper.XMLExtendedStreamWriter;
|
||||
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The subsystem parser, which uses stax to read and write to and from xml
|
||||
*/
|
||||
class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<List<ModelNode>>, XMLElementWriter<SubsystemMarshallingContext> {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException {
|
||||
// Require no attributes
|
||||
ParseUtils.requireNoAttributes(reader);
|
||||
ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(KeycloakExtension.PATH_SUBSYSTEM));
|
||||
list.add(addKeycloakSub);
|
||||
|
||||
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
||||
if (reader.getLocalName().equals(RealmDefinition.TAG_NAME)) {
|
||||
readRealm(reader, list);
|
||||
}
|
||||
else if (reader.getLocalName().equals(SecureDeploymentDefinition.TAG_NAME)) {
|
||||
readDeployment(reader, list);
|
||||
}
|
||||
else if (reader.getLocalName().equals(SecureServerDefinition.TAG_NAME)) {
|
||||
readSecureServer(reader, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// used for debugging
|
||||
private int nextTag(XMLExtendedStreamReader reader) throws XMLStreamException {
|
||||
return reader.nextTag();
|
||||
}
|
||||
|
||||
private void readRealm(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
|
||||
String realmName = readNameAttribute(reader);
|
||||
ModelNode addRealm = new ModelNode();
|
||||
addRealm.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
|
||||
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
|
||||
PathElement.pathElement(RealmDefinition.TAG_NAME, realmName));
|
||||
addRealm.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
|
||||
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
||||
String tagName = reader.getLocalName();
|
||||
SimpleAttributeDefinition def = RealmDefinition.lookup(tagName);
|
||||
if (def == null) throw new XMLStreamException("Unknown realm tag " + tagName);
|
||||
def.parseAndSetParameter(reader.getElementText(), addRealm, reader);
|
||||
}
|
||||
|
||||
list.add(addRealm);
|
||||
}
|
||||
|
||||
private void readDeployment(XMLExtendedStreamReader reader, List<ModelNode> resourcesToAdd) throws XMLStreamException {
|
||||
readSecureResource(KeycloakExtension.SECURE_DEPLOYMENT_DEFINITION.TAG_NAME, KeycloakExtension.SECURE_DEPLOYMENT_DEFINITION, reader, resourcesToAdd);
|
||||
}
|
||||
|
||||
private void readSecureServer(XMLExtendedStreamReader reader, List<ModelNode> resourcesToAdd) throws XMLStreamException {
|
||||
readSecureResource(KeycloakExtension.SECURE_SERVER_DEFINITION.TAG_NAME, KeycloakExtension.SECURE_SERVER_DEFINITION, reader, resourcesToAdd);
|
||||
}
|
||||
|
||||
private void readSecureResource(String tagName, AbstractAdapterConfigurationDefinition resource, XMLExtendedStreamReader reader, List<ModelNode> resourcesToAdd) throws XMLStreamException {
|
||||
String name = readNameAttribute(reader);
|
||||
ModelNode addSecureDeployment = new ModelNode();
|
||||
addSecureDeployment.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
|
||||
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
|
||||
PathElement.pathElement(tagName, name));
|
||||
addSecureDeployment.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
List<ModelNode> credentialsToAdd = new ArrayList<ModelNode>();
|
||||
List<ModelNode> redirectRulesToAdd = new ArrayList<ModelNode>();
|
||||
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
||||
String localName = reader.getLocalName();
|
||||
if (localName.equals(CredentialDefinition.TAG_NAME)) {
|
||||
readCredential(reader, addr, credentialsToAdd);
|
||||
continue;
|
||||
}
|
||||
if (localName.equals(RedirecRewritetRuleDefinition.TAG_NAME)) {
|
||||
readRewriteRule(reader, addr, redirectRulesToAdd);
|
||||
continue;
|
||||
}
|
||||
|
||||
SimpleAttributeDefinition def = resource.lookup(localName);
|
||||
if (def == null) throw new XMLStreamException("Unknown secure-deployment tag " + localName);
|
||||
def.parseAndSetParameter(reader.getElementText(), addSecureDeployment, reader);
|
||||
}
|
||||
|
||||
// Must add credentials after the deployment is added.
|
||||
resourcesToAdd.add(addSecureDeployment);
|
||||
resourcesToAdd.addAll(credentialsToAdd);
|
||||
resourcesToAdd.addAll(redirectRulesToAdd);
|
||||
}
|
||||
|
||||
public void readCredential(XMLExtendedStreamReader reader, PathAddress parent, List<ModelNode> credentialsToAdd) throws XMLStreamException {
|
||||
String name = readNameAttribute(reader);
|
||||
|
||||
Map<String, String> values = new HashMap<>();
|
||||
String textValue = null;
|
||||
while (reader.hasNext()) {
|
||||
int next = reader.next();
|
||||
if (next == CHARACTERS) {
|
||||
// text value of credential element (like for "secret" )
|
||||
String text = reader.getText();
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
textValue = text;
|
||||
} else if (next == START_ELEMENT) {
|
||||
String key = reader.getLocalName();
|
||||
reader.next();
|
||||
String value = reader.getText();
|
||||
reader.next();
|
||||
|
||||
values.put(key, value);
|
||||
} else if (next == END_ELEMENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (textValue != null) {
|
||||
ModelNode addCredential = getCredentialToAdd(parent, name, textValue);
|
||||
credentialsToAdd.add(addCredential);
|
||||
} else {
|
||||
for (Map.Entry<String, String> entry : values.entrySet()) {
|
||||
ModelNode addCredential = getCredentialToAdd(parent, name + "." + entry.getKey(), entry.getValue());
|
||||
credentialsToAdd.add(addCredential);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void readRewriteRule(XMLExtendedStreamReader reader, PathAddress parent, List<ModelNode> rewriteRuleToToAdd) throws XMLStreamException {
|
||||
String name = readNameAttribute(reader);
|
||||
|
||||
Map<String, String> values = new HashMap<>();
|
||||
String textValue = null;
|
||||
while (reader.hasNext()) {
|
||||
int next = reader.next();
|
||||
if (next == CHARACTERS) {
|
||||
// text value of redirect rule element
|
||||
String text = reader.getText();
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
textValue = text;
|
||||
} else if (next == START_ELEMENT) {
|
||||
String key = reader.getLocalName();
|
||||
reader.next();
|
||||
String value = reader.getText();
|
||||
reader.next();
|
||||
|
||||
values.put(key, value);
|
||||
} else if (next == END_ELEMENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (textValue != null) {
|
||||
ModelNode addRedirectRule = getRedirectRuleToAdd(parent, name, textValue);
|
||||
rewriteRuleToToAdd.add(addRedirectRule);
|
||||
} else {
|
||||
for (Map.Entry<String, String> entry : values.entrySet()) {
|
||||
ModelNode addRedirectRule = getRedirectRuleToAdd(parent, name + "." + entry.getKey(), entry.getValue());
|
||||
rewriteRuleToToAdd.add(addRedirectRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ModelNode getCredentialToAdd(PathAddress parent, String name, String value) {
|
||||
ModelNode addCredential = new ModelNode();
|
||||
addCredential.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
|
||||
PathAddress addr = PathAddress.pathAddress(parent, PathElement.pathElement(CredentialDefinition.TAG_NAME, name));
|
||||
addCredential.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
addCredential.get(CredentialDefinition.VALUE.getName()).set(value);
|
||||
return addCredential;
|
||||
}
|
||||
|
||||
private ModelNode getRedirectRuleToAdd(PathAddress parent, String name, String value) {
|
||||
ModelNode addRedirectRule = new ModelNode();
|
||||
addRedirectRule.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
|
||||
PathAddress addr = PathAddress.pathAddress(parent, PathElement.pathElement(RedirecRewritetRuleDefinition.TAG_NAME, name));
|
||||
addRedirectRule.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
addRedirectRule.get(RedirecRewritetRuleDefinition.VALUE.getName()).set(value);
|
||||
return addRedirectRule;
|
||||
}
|
||||
|
||||
// expects that the current tag will have one single attribute called "name"
|
||||
private String readNameAttribute(XMLExtendedStreamReader reader) throws XMLStreamException {
|
||||
String name = null;
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
String attr = reader.getAttributeLocalName(i);
|
||||
if (attr.equals("name")) {
|
||||
name = reader.getAttributeValue(i);
|
||||
continue;
|
||||
}
|
||||
throw ParseUtils.unexpectedAttribute(reader, i);
|
||||
}
|
||||
if (name == null) {
|
||||
throw ParseUtils.missingRequired(reader, Collections.singleton("name"));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
context.startSubsystemElement(KeycloakExtension.CURRENT_NAMESPACE, false);
|
||||
writeRealms(writer, context);
|
||||
writeSecureDeployments(writer, context);
|
||||
writeSecureServers(writer, context);
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
private void writeRealms(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
if (!context.getModelNode().get(RealmDefinition.TAG_NAME).isDefined()) {
|
||||
return;
|
||||
}
|
||||
for (Property realm : context.getModelNode().get(RealmDefinition.TAG_NAME).asPropertyList()) {
|
||||
writer.writeStartElement(RealmDefinition.TAG_NAME);
|
||||
writer.writeAttribute("name", realm.getName());
|
||||
ModelNode realmElements = realm.getValue();
|
||||
for (AttributeDefinition element : RealmDefinition.ALL_ATTRIBUTES) {
|
||||
element.marshallAsElement(realmElements, writer);
|
||||
}
|
||||
|
||||
writer.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSecureDeployments(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
writeSecureResource(SecureDeploymentDefinition.TAG_NAME, SecureDeploymentDefinition.ALL_ATTRIBUTES, writer, context);
|
||||
}
|
||||
|
||||
private void writeSecureServers(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
writeSecureResource(SecureServerDefinition.TAG_NAME, SecureServerDefinition.ALL_ATTRIBUTES, writer, context);
|
||||
}
|
||||
|
||||
private void writeSecureResource(String tagName, List<SimpleAttributeDefinition> attributes, XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
if (!context.getModelNode().get(tagName).isDefined()) {
|
||||
return;
|
||||
}
|
||||
for (Property deployment : context.getModelNode().get(tagName).asPropertyList()) {
|
||||
writer.writeStartElement(tagName);
|
||||
writer.writeAttribute("name", deployment.getName());
|
||||
ModelNode deploymentElements = deployment.getValue();
|
||||
for (AttributeDefinition element : attributes) {
|
||||
element.marshallAsElement(deploymentElements, writer);
|
||||
}
|
||||
|
||||
ModelNode credentials = deploymentElements.get(CredentialDefinition.TAG_NAME);
|
||||
if (credentials.isDefined()) {
|
||||
writeCredentials(writer, credentials);
|
||||
}
|
||||
|
||||
ModelNode redirectRewriteRule = deploymentElements.get(RedirecRewritetRuleDefinition.TAG_NAME);
|
||||
if (redirectRewriteRule.isDefined()) {
|
||||
writeRedirectRules(writer, redirectRewriteRule);
|
||||
}
|
||||
|
||||
writer.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCredentials(XMLExtendedStreamWriter writer, ModelNode credentials) throws XMLStreamException {
|
||||
Map<String, Object> parsed = new LinkedHashMap<>();
|
||||
for (Property credential : credentials.asPropertyList()) {
|
||||
String credName = credential.getName();
|
||||
String credValue = credential.getValue().get(CredentialDefinition.VALUE.getName()).asString();
|
||||
|
||||
if (credName.contains(".")) {
|
||||
String[] parts = credName.split("\\.");
|
||||
String provider = parts[0];
|
||||
String propKey = parts[1];
|
||||
|
||||
Map<String, String> currentProviderMap = (Map<String, String>) parsed.get(provider);
|
||||
if (currentProviderMap == null) {
|
||||
currentProviderMap = new LinkedHashMap<>();
|
||||
parsed.put(provider, currentProviderMap);
|
||||
}
|
||||
currentProviderMap.put(propKey, credValue);
|
||||
} else {
|
||||
parsed.put(credName, credValue);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : parsed.entrySet()) {
|
||||
writer.writeStartElement(CredentialDefinition.TAG_NAME);
|
||||
writer.writeAttribute("name", entry.getKey());
|
||||
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof String) {
|
||||
writeCharacters(writer, (String) value);
|
||||
} else {
|
||||
Map<String, String> credentialProps = (Map<String, String>) value;
|
||||
for (Map.Entry<String, String> prop : credentialProps.entrySet()) {
|
||||
writer.writeStartElement(prop.getKey());
|
||||
writeCharacters(writer, prop.getValue());
|
||||
writer.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeRedirectRules(XMLExtendedStreamWriter writer, ModelNode redirectRules) throws XMLStreamException {
|
||||
Map<String, Object> parsed = new LinkedHashMap<>();
|
||||
for (Property redirectRule : redirectRules.asPropertyList()) {
|
||||
String ruleName = redirectRule.getName();
|
||||
String ruleValue = redirectRule.getValue().get(RedirecRewritetRuleDefinition.VALUE.getName()).asString();
|
||||
parsed.put(ruleName, ruleValue);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : parsed.entrySet()) {
|
||||
writer.writeStartElement(RedirecRewritetRuleDefinition.TAG_NAME);
|
||||
writer.writeAttribute("name", entry.getKey());
|
||||
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof String) {
|
||||
writeCharacters(writer, (String) value);
|
||||
} else {
|
||||
Map<String, String> redirectRulesProps = (Map<String, String>) value;
|
||||
for (Map.Entry<String, String> prop : redirectRulesProps.entrySet()) {
|
||||
writer.writeStartElement(prop.getKey());
|
||||
writeCharacters(writer, prop.getValue());
|
||||
writer.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
// code taken from org.jboss.as.controller.AttributeMarshaller
|
||||
private void writeCharacters(XMLExtendedStreamWriter writer, String content) throws XMLStreamException {
|
||||
if (content.indexOf('\n') > -1) {
|
||||
// Multiline content. Use the overloaded variant that staxmapper will format
|
||||
writer.writeCharacters(content);
|
||||
} else {
|
||||
// Staxmapper will just output the chars without adding newlines if this is used
|
||||
char[] chars = content.toCharArray();
|
||||
writer.writeCharacters(chars, 0, chars.length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractAddStepHandler;
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
|
||||
|
||||
/**
|
||||
* Add a new realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public final class RealmAddHandler extends AbstractAddStepHandler {
|
||||
|
||||
public static RealmAddHandler INSTANCE = new RealmAddHandler();
|
||||
|
||||
private RealmAddHandler() {}
|
||||
|
||||
@Override
|
||||
protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
// TODO: localize exception. get id number
|
||||
if (!operation.get(OP).asString().equals(ADD)) {
|
||||
throw new OperationFailedException("Unexpected operation for add realm. operation=" + operation.toString());
|
||||
}
|
||||
|
||||
for (AttributeDefinition attrib : RealmDefinition.ALL_ATTRIBUTES) {
|
||||
attrib.validateAndSet(operation, model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.addRealm(operation, context.resolveExpressions(model));
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines attributes and operations for the Realm
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public class RealmDefinition extends SimpleResourceDefinition {
|
||||
|
||||
public static final String TAG_NAME = "realm";
|
||||
|
||||
|
||||
protected static final List<SimpleAttributeDefinition> REALM_ONLY_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||
static {
|
||||
}
|
||||
|
||||
protected static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||
static {
|
||||
ALL_ATTRIBUTES.addAll(REALM_ONLY_ATTRIBUTES);
|
||||
ALL_ATTRIBUTES.addAll(SharedAttributeDefinitons.ATTRIBUTES);
|
||||
}
|
||||
|
||||
private static final Map<String, SimpleAttributeDefinition> DEFINITION_LOOKUP = new HashMap<String, SimpleAttributeDefinition>();
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
|
||||
DEFINITION_LOOKUP.put(def.getXmlName(), def);
|
||||
}
|
||||
}
|
||||
|
||||
private static final RealmWriteAttributeHandler realmAttrHandler = new RealmWriteAttributeHandler(ALL_ATTRIBUTES.toArray(new SimpleAttributeDefinition[0]));
|
||||
|
||||
public RealmDefinition() {
|
||||
super(PathElement.pathElement("realm"),
|
||||
KeycloakExtension.getResourceDescriptionResolver("realm"),
|
||||
RealmAddHandler.INSTANCE,
|
||||
RealmRemoveHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerOperations(resourceRegistration);
|
||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerAttributes(resourceRegistration);
|
||||
|
||||
for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
|
||||
//TODO: use subclass of realmAttrHandler that can call RealmDefinition.validateTruststoreSetIfRequired
|
||||
resourceRegistration.registerReadWriteAttribute(attrDef, null, realmAttrHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static SimpleAttributeDefinition lookup(String name) {
|
||||
return DEFINITION_LOOKUP.get(name);
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractRemoveStepHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Remove a realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public final class RealmRemoveHandler extends AbstractRemoveStepHandler {
|
||||
|
||||
public static RealmRemoveHandler INSTANCE = new RealmRemoveHandler();
|
||||
|
||||
private RealmRemoveHandler() {}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.removeRealm(operation);
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractWriteAttributeHandler;
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
/**
|
||||
* Update an attribute on a realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public class RealmWriteAttributeHandler extends AbstractWriteAttributeHandler<KeycloakAdapterConfigService> {
|
||||
|
||||
public RealmWriteAttributeHandler(AttributeDefinition... definitions) {
|
||||
super(definitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode resolvedValue, ModelNode currentValue, HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.updateRealm(operation, attributeName, resolvedValue);
|
||||
|
||||
hh.setHandback(ckService);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode valueToRestore, ModelNode valueToRevert, KeycloakAdapterConfigService ckService) throws OperationFailedException {
|
||||
ckService.updateRealm(operation, attributeName, valueToRestore);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||
import org.jboss.as.controller.operations.validation.StringLengthValidator;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
import org.jboss.dmr.ModelType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sblanc
|
||||
*/
|
||||
public class RedirecRewritetRuleDefinition extends SimpleResourceDefinition {
|
||||
|
||||
public static final String TAG_NAME = "redirect-rewrite-rule";
|
||||
|
||||
protected static final AttributeDefinition VALUE =
|
||||
new SimpleAttributeDefinitionBuilder("value", ModelType.STRING, false)
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, false, true))
|
||||
.build();
|
||||
|
||||
public RedirecRewritetRuleDefinition() {
|
||||
super(PathElement.pathElement(TAG_NAME),
|
||||
KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
|
||||
new RedirectRewriteRuleAddHandler(VALUE),
|
||||
RedirectRewriteRuleRemoveHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerOperations(resourceRegistration);
|
||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
|
||||
super.registerAttributes(resourceRegistration);
|
||||
resourceRegistration.registerReadWriteAttribute(VALUE, null, new RedirectRewriteRuleReadWriteAttributeHandler());
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractAddStepHandler;
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
public class RedirectRewriteRuleAddHandler extends AbstractAddStepHandler {
|
||||
|
||||
public RedirectRewriteRuleAddHandler(AttributeDefinition... attributes) {
|
||||
super(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.addRedirectRewriteRule(operation, context.resolveExpressions(model));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractWriteAttributeHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
public class RedirectRewriteRuleReadWriteAttributeHandler extends AbstractWriteAttributeHandler<KeycloakAdapterConfigService> {
|
||||
|
||||
@Override
|
||||
protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode resolvedValue, ModelNode currentValue, AbstractWriteAttributeHandler.HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
|
||||
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.updateRedirectRewriteRule(operation, attributeName, resolvedValue);
|
||||
|
||||
hh.setHandback(ckService);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
|
||||
ModelNode valueToRestore, ModelNode valueToRevert, KeycloakAdapterConfigService ckService) throws OperationFailedException {
|
||||
ckService.updateRedirectRewriteRule(operation, attributeName, valueToRestore);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractRemoveStepHandler;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
||||
public class RedirectRewriteRuleRemoveHandler extends AbstractRemoveStepHandler {
|
||||
|
||||
public static RedirectRewriteRuleRemoveHandler INSTANCE = new RedirectRewriteRuleRemoveHandler();
|
||||
|
||||
private RedirectRewriteRuleRemoveHandler() {}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
|
||||
ckService.removeRedirectRewriteRule(operation);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
|
||||
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.as.controller.PathAddress;
|
||||
import org.jboss.as.controller.capability.RuntimeCapability;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.msc.service.ServiceController;
|
||||
import org.jboss.msc.service.ServiceName;
|
||||
import org.jboss.msc.service.ServiceTarget;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
|
||||
|
||||
/**
|
||||
* Defines attributes and operations for a secure-deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
final class SecureDeploymentDefinition extends AbstractAdapterConfigurationDefinition {
|
||||
|
||||
static final String TAG_NAME = "secure-deployment";
|
||||
|
||||
public SecureDeploymentDefinition() {
|
||||
super(TAG_NAME, ALL_ATTRIBUTES, new SecureDeploymentAddHandler(), new SecureDeploymentRemoveHandler(), new SecureDeploymentWriteAttributeHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a deployment to a realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
static final class SecureDeploymentAddHandler extends AbstractAdapterConfigurationAddHandler {
|
||||
|
||||
static final String HTTP_SERVER_AUTHENTICATION_CAPABILITY = "org.wildfly.security.http-server-mechanism-factory";
|
||||
static RuntimeCapability<Void> HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY;
|
||||
|
||||
static {
|
||||
try {
|
||||
HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY = RuntimeCapability
|
||||
.Builder.of(HTTP_SERVER_AUTHENTICATION_CAPABILITY, true, HttpServerAuthenticationMechanismFactory.class)
|
||||
.build();
|
||||
} catch (NoClassDefFoundError ncfe) {
|
||||
// ignore, Elytron not present thus no capability will be published by this resource definition
|
||||
}
|
||||
}
|
||||
|
||||
SecureDeploymentAddHandler() {
|
||||
super(HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY, ALL_ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.performRuntime(context, operation, model);
|
||||
if (HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY != null) {
|
||||
installCapability(context, operation);
|
||||
}
|
||||
}
|
||||
|
||||
static void installCapability(OperationContext context, ModelNode operation) {
|
||||
PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
|
||||
String factoryName = pathAddress.getLastElement().getValue();
|
||||
ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
|
||||
KeycloakHttpAuthenticationFactoryService service = new KeycloakHttpAuthenticationFactoryService(factoryName);
|
||||
ServiceTarget serviceTarget = context.getServiceTarget();
|
||||
serviceTarget.addService(serviceName, service).setInitialMode(ServiceController.Mode.ACTIVE).install();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a secure-deployment from a realm.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
static final class SecureDeploymentRemoveHandler extends AbstractAdapterConfigurationRemoveHandler {}
|
||||
|
||||
/**
|
||||
* Update an attribute on a secure-deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
static final class SecureDeploymentWriteAttributeHandler extends AbstractAdapterConfigurationWriteAttributeHandler {
|
||||
SecureDeploymentWriteAttributeHandler() {
|
||||
super(ALL_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,258 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
|
||||
import static org.keycloak.subsystem.adapter.extension.KeycloakHttpServerAuthenticationMechanismFactoryDefinition.KeycloakHttpServerAuthenticationMechanismFactoryAddHandler.HTTP_SERVER_AUTHENTICATION_CAPABILITY;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import io.undertow.io.IoCallback;
|
||||
import io.undertow.io.Sender;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.server.handlers.resource.Resource;
|
||||
import io.undertow.server.handlers.resource.ResourceChangeListener;
|
||||
import io.undertow.server.handlers.resource.ResourceManager;
|
||||
import io.undertow.util.ETag;
|
||||
import io.undertow.util.MimeMappings;
|
||||
import org.jboss.as.controller.OperationContext;
|
||||
import org.jboss.as.controller.OperationFailedException;
|
||||
import org.jboss.as.controller.PathAddress;
|
||||
import org.jboss.as.controller.capability.RuntimeCapability;
|
||||
import org.jboss.as.server.mgmt.domain.ExtensibleHttpManagement;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.msc.service.Service;
|
||||
import org.jboss.msc.service.ServiceController.Mode;
|
||||
import org.jboss.msc.service.ServiceName;
|
||||
import org.jboss.msc.service.ServiceTarget;
|
||||
import org.jboss.msc.service.StartContext;
|
||||
import org.jboss.msc.service.StartException;
|
||||
import org.jboss.msc.service.StopContext;
|
||||
import org.jboss.msc.value.InjectedValue;
|
||||
import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
|
||||
|
||||
/**
|
||||
* Defines attributes and operations for a secure-deployment.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
final class SecureServerDefinition extends AbstractAdapterConfigurationDefinition {
|
||||
|
||||
public static final String TAG_NAME = "secure-server";
|
||||
|
||||
SecureServerDefinition() {
|
||||
super(TAG_NAME, ALL_ATTRIBUTES, new SecureServerAddHandler(), new SecureServerRemoveHandler(), new SecureServerWriteHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link AbstractAdapterConfigurationAddHandler} that exposes a {@link SecureServerDefinition}
|
||||
* as a capability through the installation of a {@link KeycloakHttpAuthenticationFactoryService}.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
static final class SecureServerAddHandler extends AbstractAdapterConfigurationAddHandler {
|
||||
|
||||
static final String HTTP_SERVER_AUTHENTICATION_CAPABILITY = "org.wildfly.security.http-server-mechanism-factory";
|
||||
static final String HTTP_MANAGEMENT_HTTP_EXTENSIBLE_CAPABILITY = "org.wildfly.management.http.extensible";
|
||||
static RuntimeCapability<Void> HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY;
|
||||
|
||||
static {
|
||||
try {
|
||||
HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY = RuntimeCapability
|
||||
.Builder.of(HTTP_SERVER_AUTHENTICATION_CAPABILITY, true, HttpServerAuthenticationMechanismFactory.class)
|
||||
.build();
|
||||
} catch (NoClassDefFoundError ncfe) {
|
||||
// ignore, Elytron not present thus no capability will be published by this resource definition
|
||||
}
|
||||
}
|
||||
|
||||
SecureServerAddHandler() {
|
||||
super(HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY, ALL_ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.performRuntime(context, operation, model);
|
||||
if (HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY != null) {
|
||||
installCapability(context, operation);
|
||||
}
|
||||
}
|
||||
|
||||
static void installCapability(OperationContext context, ModelNode operation) throws OperationFailedException {
|
||||
PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
|
||||
String factoryName = pathAddress.getLastElement().getValue();
|
||||
ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
|
||||
boolean publicClient = SecureServerDefinition.PUBLIC_CLIENT.resolveModelAttribute(context, operation).asBoolean(false);
|
||||
|
||||
if (!publicClient) {
|
||||
throw new OperationFailedException("Only public clients are allowed to have their configuration exposed through the management interface");
|
||||
}
|
||||
|
||||
KeycloakHttpAuthenticationFactoryService service = new KeycloakHttpAuthenticationFactoryService(factoryName);
|
||||
ServiceTarget serviceTarget = context.getServiceTarget();
|
||||
InjectedValue<ExtensibleHttpManagement> injectedValue = new InjectedValue<>();
|
||||
serviceTarget.addService(serviceName.append("http-management-context"), createHttpManagementConfigContextService(factoryName, injectedValue))
|
||||
.addDependency(context.getCapabilityServiceName(HTTP_MANAGEMENT_HTTP_EXTENSIBLE_CAPABILITY, ExtensibleHttpManagement.class), ExtensibleHttpManagement.class, injectedValue).setInitialMode(Mode.ACTIVE).install();
|
||||
serviceTarget.addService(serviceName, service).setInitialMode(Mode.ACTIVE).install();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link AbstractAdapterConfigurationRemoveHandler} that handles the removal of {@link SecureServerDefinition}.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
static final class SecureServerRemoveHandler extends AbstractAdapterConfigurationRemoveHandler {
|
||||
@Override
|
||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.performRuntime(context, operation, model);
|
||||
PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
|
||||
String factoryName = pathAddress.getLastElement().getValue();
|
||||
ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
|
||||
context.removeService(serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recoverServices(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
super.recoverServices(context, operation, model);
|
||||
SecureServerDefinition.SecureServerAddHandler.installCapability(context, operation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link AbstractAdapterConfigurationWriteAttributeHandler} that updates attributes on a {@link SecureServerDefinition}.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
static final class SecureServerWriteHandler extends AbstractAdapterConfigurationWriteAttributeHandler {
|
||||
SecureServerWriteHandler() {
|
||||
super(ALL_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
|
||||
private static Service<Void> createHttpManagementConfigContextService(final String factoryName, final InjectedValue<ExtensibleHttpManagement> httpConfigContext) {
|
||||
final String contextName = "/keycloak/adapter/" + factoryName + "/";
|
||||
return new Service<Void>() {
|
||||
public void start(StartContext startContext) throws StartException {
|
||||
ExtensibleHttpManagement extensibleHttpManagement = (ExtensibleHttpManagement)httpConfigContext.getValue();
|
||||
extensibleHttpManagement.addStaticContext(contextName, new ResourceManager() {
|
||||
public Resource getResource(final String path) throws IOException {
|
||||
KeycloakAdapterConfigService adapterConfigService = KeycloakAdapterConfigService.getInstance();
|
||||
final String config = adapterConfigService.getJSON(factoryName);
|
||||
|
||||
if (config == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Resource() {
|
||||
public String getPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Date getLastModified() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getLastModifiedString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ETag getETag() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Resource> list() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public String getContentType(MimeMappings mimeMappings) {
|
||||
return "application/json";
|
||||
}
|
||||
|
||||
public void serve(Sender sender, HttpServerExchange exchange, IoCallback completionCallback) {
|
||||
sender.send(config);
|
||||
}
|
||||
|
||||
public Long getContentLength() {
|
||||
return Long.valueOf((long)config.length());
|
||||
}
|
||||
|
||||
public String getCacheKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Path getFilePath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getResourceManagerRoot() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Path getResourceManagerRootPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public URL getUrl() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isResourceChangeListenerSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void registerResourceChangeListener(ResourceChangeListener listener) {
|
||||
}
|
||||
|
||||
public void removeResourceChangeListener(ResourceChangeListener listener) {
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void stop(StopContext stopContext) {
|
||||
((ExtensibleHttpManagement)httpConfigContext.getValue()).removeContext(contextName);
|
||||
}
|
||||
|
||||
public Void getValue() throws IllegalStateException, IllegalArgumentException {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,276 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import org.jboss.as.controller.operations.validation.IntRangeValidator;
|
||||
import org.jboss.as.controller.operations.validation.LongRangeValidator;
|
||||
import org.jboss.as.controller.operations.validation.StringLengthValidator;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.dmr.ModelType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defines attributes that can be present in both a realm and an application (secure-deployment).
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
public class SharedAttributeDefinitons {
|
||||
|
||||
protected static final SimpleAttributeDefinition REALM_PUBLIC_KEY =
|
||||
new SimpleAttributeDefinitionBuilder("realm-public-key", ModelType.STRING, true)
|
||||
.setXmlName("realm-public-key")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition AUTH_SERVER_URL =
|
||||
new SimpleAttributeDefinitionBuilder("auth-server-url", ModelType.STRING, true)
|
||||
.setXmlName("auth-server-url")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition SSL_REQUIRED =
|
||||
new SimpleAttributeDefinitionBuilder("ssl-required", ModelType.STRING, true)
|
||||
.setXmlName("ssl-required")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode("external"))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition ALLOW_ANY_HOSTNAME =
|
||||
new SimpleAttributeDefinitionBuilder("allow-any-hostname", ModelType.BOOLEAN, true)
|
||||
.setXmlName("allow-any-hostname")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition DISABLE_TRUST_MANAGER =
|
||||
new SimpleAttributeDefinitionBuilder("disable-trust-manager", ModelType.BOOLEAN, true)
|
||||
.setXmlName("disable-trust-manager")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition TRUSTSTORE =
|
||||
new SimpleAttributeDefinitionBuilder("truststore", ModelType.STRING, true)
|
||||
.setXmlName("truststore")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition TRUSTSTORE_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder("truststore-password", ModelType.STRING, true)
|
||||
.setXmlName("truststore-password")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CONNECTION_POOL_SIZE =
|
||||
new SimpleAttributeDefinitionBuilder("connection-pool-size", ModelType.INT, true)
|
||||
.setXmlName("connection-pool-size")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new IntRangeValidator(0, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition SOCKET_TIMEOUT =
|
||||
new SimpleAttributeDefinitionBuilder("socket-timeout-millis", ModelType.LONG, true)
|
||||
.setXmlName("socket-timeout-millis")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new LongRangeValidator(-1L, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CONNECTION_TTL =
|
||||
new SimpleAttributeDefinitionBuilder("connection-ttl-millis", ModelType.LONG, true)
|
||||
.setXmlName("connection-ttl-millis")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new LongRangeValidator(-1L, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CONNECTION_TIMEOUT =
|
||||
new SimpleAttributeDefinitionBuilder("connection-timeout-millis", ModelType.LONG, true)
|
||||
.setXmlName("connection-timeout-millis")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new LongRangeValidator(-1L, true))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition ENABLE_CORS =
|
||||
new SimpleAttributeDefinitionBuilder("enable-cors", ModelType.BOOLEAN, true)
|
||||
.setXmlName("enable-cors")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CLIENT_KEYSTORE =
|
||||
new SimpleAttributeDefinitionBuilder("client-keystore", ModelType.STRING, true)
|
||||
.setXmlName("client-keystore")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CLIENT_KEYSTORE_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder("client-keystore-password", ModelType.STRING, true)
|
||||
.setXmlName("client-keystore-password")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CLIENT_KEY_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder("client-key-password", ModelType.STRING, true)
|
||||
.setXmlName("client-key-password")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CORS_MAX_AGE =
|
||||
new SimpleAttributeDefinitionBuilder("cors-max-age", ModelType.INT, true)
|
||||
.setXmlName("cors-max-age")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new IntRangeValidator(-1, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CORS_ALLOWED_HEADERS =
|
||||
new SimpleAttributeDefinitionBuilder("cors-allowed-headers", ModelType.STRING, true)
|
||||
.setXmlName("cors-allowed-headers")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CORS_ALLOWED_METHODS =
|
||||
new SimpleAttributeDefinitionBuilder("cors-allowed-methods", ModelType.STRING, true)
|
||||
.setXmlName("cors-allowed-methods")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition CORS_EXPOSED_HEADERS =
|
||||
new SimpleAttributeDefinitionBuilder("cors-exposed-headers", ModelType.STRING, true)
|
||||
.setXmlName("cors-exposed-headers")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition EXPOSE_TOKEN =
|
||||
new SimpleAttributeDefinitionBuilder("expose-token", ModelType.BOOLEAN, true)
|
||||
.setXmlName("expose-token")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition AUTH_SERVER_URL_FOR_BACKEND_REQUESTS =
|
||||
new SimpleAttributeDefinitionBuilder("auth-server-url-for-backend-requests", ModelType.STRING, true)
|
||||
.setXmlName("auth-server-url-for-backend-requests")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition ALWAYS_REFRESH_TOKEN =
|
||||
new SimpleAttributeDefinitionBuilder("always-refresh-token", ModelType.BOOLEAN, true)
|
||||
.setXmlName("always-refresh-token")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition REGISTER_NODE_AT_STARTUP =
|
||||
new SimpleAttributeDefinitionBuilder("register-node-at-startup", ModelType.BOOLEAN, true)
|
||||
.setXmlName("register-node-at-startup")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition REGISTER_NODE_PERIOD =
|
||||
new SimpleAttributeDefinitionBuilder("register-node-period", ModelType.INT, true)
|
||||
.setXmlName("register-node-period")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new IntRangeValidator(-1, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition TOKEN_STORE =
|
||||
new SimpleAttributeDefinitionBuilder("token-store", ModelType.STRING, true)
|
||||
.setXmlName("token-store")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition PRINCIPAL_ATTRIBUTE =
|
||||
new SimpleAttributeDefinitionBuilder("principal-attribute", ModelType.STRING, true)
|
||||
.setXmlName("principal-attribute")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
protected static final SimpleAttributeDefinition AUTODETECT_BEARER_ONLY =
|
||||
new SimpleAttributeDefinitionBuilder("autodetect-bearer-only", ModelType.BOOLEAN, true)
|
||||
.setXmlName("autodetect-bearer-only")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition IGNORE_OAUTH_QUERY_PARAMETER =
|
||||
new SimpleAttributeDefinitionBuilder("ignore-oauth-query-parameter", ModelType.BOOLEAN, true)
|
||||
.setXmlName("ignore-oauth-query-parameter")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition CONFIDENTIAL_PORT =
|
||||
new SimpleAttributeDefinitionBuilder("confidential-port", ModelType.INT, true)
|
||||
.setXmlName("confidential-port")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(8443))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition PROXY_URL =
|
||||
new SimpleAttributeDefinitionBuilder("proxy-url", ModelType.STRING, true)
|
||||
.setXmlName("proxy-url")
|
||||
.setAllowExpression(true)
|
||||
.setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition VERIFY_TOKEN_AUDIENCE =
|
||||
new SimpleAttributeDefinitionBuilder("verify-token-audience", ModelType.BOOLEAN, true)
|
||||
.setXmlName("verify-token-audience")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
|
||||
|
||||
protected static final List<SimpleAttributeDefinition> ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||
static {
|
||||
ATTRIBUTES.add(REALM_PUBLIC_KEY);
|
||||
ATTRIBUTES.add(AUTH_SERVER_URL);
|
||||
ATTRIBUTES.add(TRUSTSTORE);
|
||||
ATTRIBUTES.add(TRUSTSTORE_PASSWORD);
|
||||
ATTRIBUTES.add(SSL_REQUIRED);
|
||||
ATTRIBUTES.add(CONFIDENTIAL_PORT);
|
||||
ATTRIBUTES.add(ALLOW_ANY_HOSTNAME);
|
||||
ATTRIBUTES.add(DISABLE_TRUST_MANAGER);
|
||||
ATTRIBUTES.add(CONNECTION_POOL_SIZE);
|
||||
ATTRIBUTES.add(SOCKET_TIMEOUT);
|
||||
ATTRIBUTES.add(CONNECTION_TTL);
|
||||
ATTRIBUTES.add(CONNECTION_TIMEOUT);
|
||||
ATTRIBUTES.add(ENABLE_CORS);
|
||||
ATTRIBUTES.add(CLIENT_KEYSTORE);
|
||||
ATTRIBUTES.add(CLIENT_KEYSTORE_PASSWORD);
|
||||
ATTRIBUTES.add(CLIENT_KEY_PASSWORD);
|
||||
ATTRIBUTES.add(CORS_MAX_AGE);
|
||||
ATTRIBUTES.add(CORS_ALLOWED_HEADERS);
|
||||
ATTRIBUTES.add(CORS_ALLOWED_METHODS);
|
||||
ATTRIBUTES.add(CORS_EXPOSED_HEADERS);
|
||||
ATTRIBUTES.add(EXPOSE_TOKEN);
|
||||
ATTRIBUTES.add(AUTH_SERVER_URL_FOR_BACKEND_REQUESTS);
|
||||
ATTRIBUTES.add(ALWAYS_REFRESH_TOKEN);
|
||||
ATTRIBUTES.add(REGISTER_NODE_AT_STARTUP);
|
||||
ATTRIBUTES.add(REGISTER_NODE_PERIOD);
|
||||
ATTRIBUTES.add(TOKEN_STORE);
|
||||
ATTRIBUTES.add(PRINCIPAL_ATTRIBUTE);
|
||||
ATTRIBUTES.add(AUTODETECT_BEARER_ONLY);
|
||||
ATTRIBUTES.add(IGNORE_OAUTH_QUERY_PARAMETER);
|
||||
ATTRIBUTES.add(PROXY_URL);
|
||||
ATTRIBUTES.add(VERIFY_TOKEN_AUDIENCE);
|
||||
}
|
||||
|
||||
private static boolean isSet(ModelNode attributes, SimpleAttributeDefinition def) {
|
||||
ModelNode attribute = attributes.get(def.getName());
|
||||
|
||||
if (def.getType() == ModelType.BOOLEAN) {
|
||||
return attribute.isDefined() && attribute.asBoolean();
|
||||
}
|
||||
|
||||
return attribute.isDefined() && !attribute.asString().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.logging;
|
||||
|
||||
import org.jboss.logging.BasicLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.annotations.LogMessage;
|
||||
import org.jboss.logging.annotations.Message;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.INFO;
|
||||
|
||||
/**
|
||||
* This interface to be fleshed out later when error messages are fully externalized.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
@MessageLogger(projectCode = "KEYCLOAK")
|
||||
public interface KeycloakLogger extends BasicLogger {
|
||||
|
||||
/**
|
||||
* A logger with a category of the package name.
|
||||
*/
|
||||
KeycloakLogger ROOT_LOGGER = Logger.getMessageLogger(KeycloakLogger.class, "org.jboss.keycloak");
|
||||
|
||||
@LogMessage(level = INFO)
|
||||
@Message(value = "Keycloak subsystem override for deployment %s")
|
||||
void deploymentSecured(String deployment);
|
||||
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.logging;
|
||||
|
||||
import org.jboss.logging.Messages;
|
||||
import org.jboss.logging.annotations.MessageBundle;
|
||||
|
||||
/**
|
||||
* This interface to be fleshed out later when error messages are fully externalized.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2012 Red Hat Inc.
|
||||
*/
|
||||
@MessageBundle(projectCode = "KEYCLOAK")
|
||||
public interface KeycloakMessages {
|
||||
|
||||
/**
|
||||
* The messages
|
||||
*/
|
||||
KeycloakMessages MESSAGES = Messages.getBundle(KeycloakMessages.class);
|
||||
}
|
|
@ -1,18 +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.
|
||||
#
|
||||
|
||||
org.keycloak.subsystem.adapter.extension.KeycloakExtension
|
|
@ -1,168 +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.
|
||||
#
|
||||
|
||||
keycloak.subsystem=Keycloak adapter subsystem
|
||||
keycloak.subsystem.add=Operation Adds Keycloak adapter subsystem
|
||||
keycloak.subsystem.remove=Operation removes Keycloak adapter subsystem
|
||||
keycloak.subsystem.realm=A Keycloak realm.
|
||||
keycloak.subsystem.secure-deployment=A deployment secured by Keycloak.
|
||||
keycloak.subsystem.secure-server=A configuration exposed to the server.
|
||||
keycloak.subsystem.http-server-mechanism-factory=A http-server-mechanism-factory exposed to the server.
|
||||
|
||||
keycloak.realm=A Keycloak realm.
|
||||
keycloak.realm.add=Add a realm definition to the subsystem.
|
||||
keycloak.realm.remove=Remove a realm from the subsystem.
|
||||
keycloak.realm.realm-public-key=Public key of the realm
|
||||
keycloak.realm.auth-server-url=Base URL of the Realm Auth Server
|
||||
keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||
keycloak.realm.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||
keycloak.realm.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||
keycloak.realm.allow-any-hostname=SSL Setting
|
||||
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
|
||||
keycloak.realm.truststore-password=Password of the Truststore
|
||||
keycloak.realm.connection-pool-size=Connection pool size for the client used by the adapter
|
||||
keycloak.realm.socket-timeout-millis=Timeout for socket waiting for data in milliseconds
|
||||
keycloak.realm.connection-ttl-millis=Connection time to live in milliseconds
|
||||
keycloak.realm.connection-timeout-millis=Timeout for establishing the connection with the remote host in milliseconds
|
||||
keycloak.realm.enable-cors=Enable Keycloak CORS support
|
||||
keycloak.realm.client-keystore=n/a
|
||||
keycloak.realm.client-keystore-password=n/a
|
||||
keycloak.realm.client-key-password=n/a
|
||||
keycloak.realm.cors-max-age=CORS max-age header
|
||||
keycloak.realm.cors-allowed-headers=CORS allowed headers
|
||||
keycloak.realm.cors-allowed-methods=CORS allowed methods
|
||||
keycloak.realm.cors-exposed-headers=CORS exposed headers
|
||||
keycloak.realm.expose-token=Enable secure URL that exposes access token
|
||||
keycloak.realm.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
|
||||
keycloak.realm.always-refresh-token=Refresh token on every single web request
|
||||
keycloak.realm.register-node-at-startup=Cluster setting
|
||||
keycloak.realm.register-node-period=how often to re-register node
|
||||
keycloak.realm.token-store=cookie or session storage for auth session data
|
||||
keycloak.realm.principal-attribute=token attribute to use to set Principal name
|
||||
keycloak.realm.autodetect-bearer-only=autodetect bearer-only requests
|
||||
keycloak.realm.ignore-oauth-query-parameter=disable query parameter parsing for access_token
|
||||
keycloak.realm.proxy-url=The URL for the HTTP proxy if one is used.
|
||||
keycloak.realm.verify-token-audience=If true, then during bearer-only authentication, the adapter will verify if token contains this client name (resource) as an audience
|
||||
|
||||
keycloak.secure-deployment=A deployment secured by Keycloak
|
||||
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
|
||||
keycloak.secure-deployment.realm=Keycloak realm
|
||||
keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak
|
||||
keycloak.secure-deployment.realm-public-key=Public key of the realm
|
||||
keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server
|
||||
keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||
keycloak.secure-deployment.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||
keycloak.secure-deployment.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||
keycloak.secure-deployment.allow-any-hostname=SSL Setting
|
||||
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
|
||||
keycloak.secure-deployment.truststore-password=Password of the Truststore
|
||||
keycloak.secure-deployment.connection-pool-size=Connection pool size for the client used by the adapter
|
||||
keycloak.secure-deployment.socket-timeout-millis=Timeout for socket waiting for data in milliseconds
|
||||
keycloak.secure-deployment.connection-ttl-millis=Connection time to live in milliseconds
|
||||
keycloak.secure-deployment.connection-timeout-millis=Timeout for establishing the connection with the remote host in milliseconds
|
||||
keycloak.secure-deployment.resource=Application name
|
||||
keycloak.secure-deployment.use-resource-role-mappings=Use resource level permissions from token
|
||||
keycloak.secure-deployment.credentials=Adapter credentials
|
||||
keycloak.secure-deployment.redirect-rewrite-rule=Apply a rewrite rule for the redirect URI
|
||||
keycloak.secure-deployment.bearer-only=Bearer Token Auth only
|
||||
keycloak.secure-deployment.enable-basic-auth=Enable Basic Authentication
|
||||
keycloak.secure-deployment.public-client=Public client
|
||||
keycloak.secure-deployment.enable-cors=Enable Keycloak CORS support
|
||||
keycloak.secure-deployment.autodetect-bearer-only=autodetect bearer-only requests
|
||||
keycloak.secure-deployment.client-keystore=n/a
|
||||
keycloak.secure-deployment.client-keystore-password=n/a
|
||||
keycloak.secure-deployment.client-key-password=n/a
|
||||
keycloak.secure-deployment.cors-max-age=CORS max-age header
|
||||
keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
|
||||
keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
|
||||
keycloak.secure-deployment.cors-exposed-headers=CORS exposed headers
|
||||
keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
|
||||
keycloak.secure-deployment.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
|
||||
keycloak.secure-deployment.always-refresh-token=Refresh token on every single web request
|
||||
keycloak.secure-deployment.register-node-at-startup=Cluster setting
|
||||
keycloak.secure-deployment.register-node-period=how often to re-register node
|
||||
keycloak.secure-deployment.token-store=cookie or session storage for auth session data
|
||||
keycloak.secure-deployment.principal-attribute=token attribute to use to set Principal name
|
||||
keycloak.secure-deployment.turn-off-change-session-id-on-login=The session id is changed by default on a successful login. Change this to true if you want to turn this off
|
||||
keycloak.secure-deployment.token-minimum-time-to-live=The adapter will refresh the token if the current token is expired OR will expire in 'token-minimum-time-to-live' seconds or less
|
||||
keycloak.secure-deployment.min-time-between-jwks-requests=If adapter recognize token signed by unknown public key, it will try to download new public key from keycloak server. However it won't try to download if already tried it in less than 'min-time-between-jwks-requests' seconds
|
||||
keycloak.secure-deployment.public-key-cache-ttl=Maximum time the downloaded public keys are considered valid. When this time reach, the adapter is forced to download public keys from keycloak server
|
||||
keycloak.secure-deployment.ignore-oauth-query-parameter=disable query parameter parsing for access_token
|
||||
keycloak.secure-deployment.proxy-url=The URL for the HTTP proxy if one is used.
|
||||
keycloak.secure-deployment.verify-token-audience=If true, then during bearer-only authentication, the adapter will verify if token contains this client name (resource) as an audience
|
||||
keycloak.secure-deployment.adapter-state-cookie-path=If set, defines the path used in cookies set by the adapter. Useful when deploying the application in the root context path.
|
||||
|
||||
keycloak.secure-server=A deployment secured by Keycloak
|
||||
keycloak.secure-server.add=Add a deployment to be secured by Keycloak
|
||||
keycloak.secure-server.realm=Keycloak realm
|
||||
keycloak.secure-server.remove=Remove a deployment to be secured by Keycloak
|
||||
keycloak.secure-server.realm-public-key=Public key of the realm
|
||||
keycloak.secure-server.auth-server-url=Base URL of the Realm Auth Server
|
||||
keycloak.secure-server.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||
keycloak.secure-server.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||
keycloak.secure-server.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||
keycloak.secure-server.allow-any-hostname=SSL Setting
|
||||
keycloak.secure-server.truststore=Truststore used for adapter client HTTPS requests
|
||||
keycloak.secure-server.truststore-password=Password of the Truststore
|
||||
keycloak.secure-server.connection-pool-size=Connection pool size for the client used by the adapter
|
||||
keycloak.secure-server.socket-timeout-millis=Timeout for socket waiting for data in milliseconds
|
||||
keycloak.secure-server.connection-ttl-millis=Connection time to live in milliseconds
|
||||
keycloak.secure-server.connection-timeout-millis=Timeout for establishing the connection with the remote host in milliseconds
|
||||
keycloak.secure-server.resource=Application name
|
||||
keycloak.secure-server.use-resource-role-mappings=Use resource level permissions from token
|
||||
keycloak.secure-server.credentials=Adapter credentials
|
||||
keycloak.secure-server.redirect-rewrite-rule=Apply a rewrite rule for the redirect URI
|
||||
keycloak.secure-server.bearer-only=Bearer Token Auth only
|
||||
keycloak.secure-server.enable-basic-auth=Enable Basic Authentication
|
||||
keycloak.secure-server.public-client=Public client
|
||||
keycloak.secure-server.enable-cors=Enable Keycloak CORS support
|
||||
keycloak.secure-server.autodetect-bearer-only=autodetect bearer-only requests
|
||||
keycloak.secure-server.client-keystore=n/a
|
||||
keycloak.secure-server.client-keystore-password=n/a
|
||||
keycloak.secure-server.client-key-password=n/a
|
||||
keycloak.secure-server.cors-max-age=CORS max-age header
|
||||
keycloak.secure-server.cors-allowed-headers=CORS allowed headers
|
||||
keycloak.secure-server.cors-allowed-methods=CORS allowed methods
|
||||
keycloak.secure-server.cors-exposed-headers=CORS exposed headers
|
||||
keycloak.secure-server.expose-token=Enable secure URL that exposes access token
|
||||
keycloak.secure-server.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
|
||||
keycloak.secure-server.always-refresh-token=Refresh token on every single web request
|
||||
keycloak.secure-server.register-node-at-startup=Cluster setting
|
||||
keycloak.secure-server.register-node-period=how often to re-register node
|
||||
keycloak.secure-server.token-store=cookie or session storage for auth session data
|
||||
keycloak.secure-server.principal-attribute=token attribute to use to set Principal name
|
||||
keycloak.secure-server.turn-off-change-session-id-on-login=The session id is changed by default on a successful login. Change this to true if you want to turn this off
|
||||
keycloak.secure-server.token-minimum-time-to-live=The adapter will refresh the token if the current token is expired OR will expire in 'token-minimum-time-to-live' seconds or less
|
||||
keycloak.secure-server.min-time-between-jwks-requests=If adapter recognize token signed by unknown public key, it will try to download new public key from keycloak server. However it won't try to download if already tried it in less than 'min-time-between-jwks-requests' seconds
|
||||
keycloak.secure-server.public-key-cache-ttl=Maximum time the downloaded public keys are considered valid. When this time reach, the adapter is forced to download public keys from keycloak server
|
||||
keycloak.secure-server.ignore-oauth-query-parameter=disable query parameter parsing for access_token
|
||||
keycloak.secure-server.proxy-url=The URL for the HTTP proxy if one is used.
|
||||
keycloak.secure-server.verify-token-audience=If true, then during bearer-only authentication, the adapter will verify if token contains this client name (resource) as an audience
|
||||
keycloak.secure-server.adapter-state-cookie-path=If set, defines the path used in cookies set by the adapter. Useful when deploying the application in the root context path.
|
||||
|
||||
keycloak.secure-deployment.credential=Credential value
|
||||
keycloak.secure-server.credential=Credential value
|
||||
|
||||
keycloak.credential=Credential
|
||||
keycloak.credential.value=Credential value
|
||||
keycloak.credential.add=Credential add
|
||||
keycloak.credential.remove=Credential remove
|
||||
|
||||
keycloak.redirect-rewrite-rule=redirect-rewrite-rule
|
||||
keycloak.redirect-rewrite-rule.value=redirect-rewrite-rule value
|
||||
keycloak.redirect-rewrite-rule.add=redirect-rewrite-rule add
|
||||
keycloak.redirect-rewrite-rule.remove=redirect-rewrite-rule remove
|
|
@ -1,146 +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.
|
||||
-->
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="urn:jboss:domain:keycloak:1.1"
|
||||
xmlns="urn:jboss:domain:keycloak:1.1"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified"
|
||||
version="1.0">
|
||||
|
||||
<!-- The subsystem root element -->
|
||||
<xs:element name="subsystem" type="subsystem-type"/>
|
||||
|
||||
<xs:complexType name="subsystem-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<![CDATA[
|
||||
The Keycloak adapter subsystem, used to register deployments managed by Keycloak
|
||||
]]>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="realm" maxOccurs="unbounded" minOccurs="0" type="realm-type"/>
|
||||
<xs:element name="secure-deployment" maxOccurs="unbounded" minOccurs="0" type="secure-deployment-type"/>
|
||||
<xs:element name="secure-server" maxOccurs="unbounded" minOccurs="0" type="secure-deployment-type"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="realm-type">
|
||||
<xs:all>
|
||||
<xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-keystore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-keystore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="enable-cors" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="allow-any-hostname" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="client-key-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-max-age" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-at-startup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="autodetect-bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ignore-oauth-query-parameter" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="proxy-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="verify-token-audience" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name of the realm.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="secure-deployment-type">
|
||||
<xs:all>
|
||||
<xs:element name="client-keystore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-keystore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="enable-cors" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="allow-any-hostname" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="use-resource-role-mappings" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-max-age" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="realm" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="resource" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-key-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="public-client" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="credential" type="credential-type" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="redirect-rewrite-rule" type="redirect-rewrite-rule-type" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-at-startup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="enable-basic-auth" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="turn-off-change-session-id-on-login" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="token-minimum-time-to-live" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="min-time-between-jwks-requests" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="public-key-cache-ttl" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="autodetect-bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ignore-oauth-query-parameter" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="proxy-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="verify-token-audience" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="adapter-state-cookie-path" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name of the realm.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="credential-type" mixed="true">
|
||||
<xs:sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:any processContents="lax"></xs:any>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
<xs:complexType name="redirect-rewrite-rule-type" mixed="true">
|
||||
<xs:sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:any processContents="lax"></xs:any>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
|
@ -1,152 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright 2021 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.
|
||||
-->
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="urn:jboss:domain:keycloak:1.2"
|
||||
xmlns="urn:jboss:domain:keycloak:1.2"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified"
|
||||
version="1.0">
|
||||
|
||||
<!-- The subsystem root element -->
|
||||
<xs:element name="subsystem" type="subsystem-type"/>
|
||||
|
||||
<xs:complexType name="subsystem-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<![CDATA[
|
||||
The Keycloak adapter subsystem, used to register deployments managed by Keycloak
|
||||
]]>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="realm" maxOccurs="unbounded" minOccurs="0" type="realm-type"/>
|
||||
<xs:element name="secure-deployment" maxOccurs="unbounded" minOccurs="0" type="secure-deployment-type"/>
|
||||
<xs:element name="secure-server" maxOccurs="unbounded" minOccurs="0" type="secure-deployment-type"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="realm-type">
|
||||
<xs:all>
|
||||
<xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-keystore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-keystore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="enable-cors" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="allow-any-hostname" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="client-key-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="socket-timeout-millis" type="xs:long" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-ttl-millis" type="xs:long" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-timeout-millis" type="xs:long" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-max-age" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-at-startup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="autodetect-bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ignore-oauth-query-parameter" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="proxy-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="verify-token-audience" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name of the realm.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="secure-deployment-type">
|
||||
<xs:all>
|
||||
<xs:element name="client-keystore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-keystore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="enable-cors" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="allow-any-hostname" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="use-resource-role-mappings" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-max-age" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="realm" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="resource" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="client-key-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="public-client" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="socket-timeout-millis" type="xs:long" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-ttl-millis" type="xs:long" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="connection-timeout-millis" type="xs:long" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="credential" type="credential-type" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="redirect-rewrite-rule" type="redirect-rewrite-rule-type" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-at-startup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="enable-basic-auth" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="turn-off-change-session-id-on-login" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="token-minimum-time-to-live" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="min-time-between-jwks-requests" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="public-key-cache-ttl" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="autodetect-bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ignore-oauth-query-parameter" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="proxy-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="verify-token-audience" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="adapter-state-cookie-path" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name of the realm.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="credential-type" mixed="true">
|
||||
<xs:sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:any processContents="lax"></xs:any>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
<xs:complexType name="redirect-rewrite-rule-type" mixed="true">
|
||||
<xs:sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:any processContents="lax"></xs:any>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
|
@ -1,24 +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.
|
||||
-->
|
||||
|
||||
<!-- Template used by WildFly build when directed to include Keycloak subsystem in a configuration. -->
|
||||
<config>
|
||||
<extension-module>org.keycloak.keycloak-adapter-subsystem</extension-module>
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.2">
|
||||
</subsystem>
|
||||
</config>
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.adapter.extension;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.jboss.as.controller.PathAddress;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
|
||||
import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;
|
||||
import org.jboss.as.subsystem.test.KernelServices;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* Tests all management expects for subsystem, parsing, marshaling, model definition and other
|
||||
* Here is an example that allows you a fine grained controller over what is tested and how. So it can give you ideas what can be done and tested.
|
||||
* If you have no need for advanced testing of subsystem you look at {@link SubsystemBaseParsingTestCase} that testes same stuff but most of the code
|
||||
* is hidden inside of test harness
|
||||
*
|
||||
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
|
||||
* @author Tomaz Cerar
|
||||
* @author <a href="marko.strukelj@gmail.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
||||
|
||||
public SubsystemParsingTestCase() {
|
||||
super(KeycloakExtension.SUBSYSTEM_NAME, new KeycloakExtension());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJson() throws Exception {
|
||||
ModelNode node = new ModelNode();
|
||||
node.get("realm").set("demo");
|
||||
node.get("resource").set("customer-portal");
|
||||
node.get("realm-public-key").set("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB");
|
||||
node.get("auth-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/login");
|
||||
node.get("code-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/access/codes");
|
||||
node.get("ssl-required").set("external");
|
||||
node.get("confidential-port").set(443);
|
||||
node.get("expose-token").set(true);
|
||||
|
||||
ModelNode jwtCredential = new ModelNode();
|
||||
jwtCredential.get("client-keystore-file").set("/tmp/keystore.jks");
|
||||
jwtCredential.get("client-keystore-password").set("changeit");
|
||||
ModelNode credential = new ModelNode();
|
||||
credential.get("jwt").set(jwtCredential);
|
||||
node.get("credentials").set(credential);
|
||||
|
||||
System.out.println("json=" + node.toJSONString(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsonFromSignedJWTCredentials() {
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
|
||||
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement("subsystem", "keycloak"), PathElement.pathElement("secure-deployment", "foo"));
|
||||
ModelNode deploymentOp = new ModelNode();
|
||||
deploymentOp.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
ModelNode deployment = new ModelNode();
|
||||
deployment.get("realm").set("demo");
|
||||
deployment.get("resource").set("customer-portal");
|
||||
service.addSecureDeployment(deploymentOp, deployment, false);
|
||||
|
||||
addCredential(addr, service, "secret", "secret1");
|
||||
addCredential(addr, service, "jwt.client-keystore-file", "/tmp/foo.jks");
|
||||
addCredential(addr, service, "jwt.token-timeout", "10");
|
||||
}
|
||||
|
||||
private void addCredential(PathAddress parent, KeycloakAdapterConfigService service, String key, String value) {
|
||||
PathAddress credAddr = PathAddress.pathAddress(parent, PathElement.pathElement("credential", key));
|
||||
ModelNode credOp = new ModelNode();
|
||||
credOp.get(ModelDescriptionConstants.OP_ADDR).set(credAddr.toModelNode());
|
||||
ModelNode credential = new ModelNode();
|
||||
credential.get("value").set(value);
|
||||
service.addCredential(credOp, credential);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubsystemXml() throws IOException {
|
||||
return readResource("keycloak-1.2.xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubsystemXsdPath() throws Exception {
|
||||
return "schema/wildfly-keycloak_1_2.xsd";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getSubsystemTemplatePaths() throws IOException {
|
||||
return new String[]{
|
||||
"/subsystem-templates/keycloak-adapter.xml"
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the subsystem is still capable of reading a configuration that uses version 1.1 of the schema.
|
||||
*
|
||||
* @throws Exception if an error occurs while running the test.
|
||||
*/
|
||||
@Test
|
||||
public void testSubsystem1_1() throws Exception {
|
||||
KernelServices servicesA = super.createKernelServicesBuilder(createAdditionalInitialization())
|
||||
.setSubsystemXml(readResource("keycloak-1.1.xml")).build();
|
||||
Assert.assertTrue("Subsystem boot failed!", servicesA.isSuccessfulBoot());
|
||||
ModelNode modelA = servicesA.readWholeModel();
|
||||
super.validateModel(modelA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a subsystem configuration that contains a {@code redirect-rewrite-rule}, checking that the resulting JSON
|
||||
* can be properly used to create an {@link AdapterConfig}.
|
||||
*
|
||||
* Added as part of the fix for {@code KEYCLOAK-18302}.
|
||||
*/
|
||||
@Test
|
||||
public void testJsonFromRedirectRewriteRuleConfiguration() {
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
|
||||
// add a secure deployment with a redirect-rewrite-rule
|
||||
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement("subsystem", "keycloak"), PathElement.pathElement("secure-deployment", "foo"));
|
||||
ModelNode deploymentOp = new ModelNode();
|
||||
deploymentOp.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
ModelNode deployment = new ModelNode();
|
||||
deployment.get("realm").set("demo");
|
||||
deployment.get("resource").set("customer-portal");
|
||||
service.addSecureDeployment(deploymentOp, deployment, false);
|
||||
this.addRedirectRewriteRule(addr, service, "^/wsmaster/api/(.*)$", "api/$1");
|
||||
|
||||
// get the subsystem config as JSON
|
||||
String jsonConfig = service.getJSON("foo");
|
||||
|
||||
// attempt to create an adapter config instance from the subsystem JSON config
|
||||
AdapterConfig config = KeycloakDeploymentBuilder.loadAdapterConfig(new ByteArrayInputStream(jsonConfig.getBytes()));
|
||||
Assert.assertNotNull(config);
|
||||
|
||||
// assert that the config has the configured rule
|
||||
Map<String, String> redirectRewriteRules = config.getRedirectRewriteRules();
|
||||
Assert.assertNotNull(redirectRewriteRules);
|
||||
Map.Entry<String, String> entry = redirectRewriteRules.entrySet().iterator().next();
|
||||
Assert.assertEquals("^/wsmaster/api/(.*)$", entry.getKey());
|
||||
Assert.assertEquals("api/$1", entry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsonHttpClientAttributes() {
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
|
||||
// add a secure deployment
|
||||
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement("subsystem", "keycloak"), PathElement.pathElement("secure-deployment", "foo"));
|
||||
ModelNode deploymentOp = new ModelNode();
|
||||
deploymentOp.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||
|
||||
ModelNode deployment = new ModelNode();
|
||||
deployment.get("realm").set("demo");
|
||||
deployment.get("resource").set("customer-portal");
|
||||
|
||||
deployment.get(SharedAttributeDefinitons.SOCKET_TIMEOUT.getName()).set(3000L);
|
||||
deployment.get(SharedAttributeDefinitons.CONNECTION_TIMEOUT.getName()).set(5000L);
|
||||
deployment.get(SharedAttributeDefinitons.CONNECTION_TTL.getName()).set(1000L);
|
||||
|
||||
service.addSecureDeployment(deploymentOp, deployment, false);
|
||||
|
||||
// get the subsystem config as JSON
|
||||
String jsonConfig = service.getJSON("foo");
|
||||
|
||||
// attempt to create an adapter config instance from the subsystem JSON config
|
||||
AdapterConfig config = KeycloakDeploymentBuilder.loadAdapterConfig(new ByteArrayInputStream(jsonConfig.getBytes()));
|
||||
assertThat(config, CoreMatchers.notNullValue());
|
||||
|
||||
assertThat(config.getSocketTimeout(), CoreMatchers.notNullValue());
|
||||
assertThat(config.getSocketTimeout(), CoreMatchers.is(3000L));
|
||||
|
||||
assertThat(config.getConnectionTimeout(), CoreMatchers.notNullValue());
|
||||
assertThat(config.getConnectionTimeout(), CoreMatchers.is(5000L));
|
||||
|
||||
assertThat(config.getConnectionTTL(), CoreMatchers.notNullValue());
|
||||
assertThat(config.getConnectionTTL(), CoreMatchers.is(1000L));
|
||||
}
|
||||
|
||||
private void addRedirectRewriteRule(PathAddress parent, KeycloakAdapterConfigService service, String key, String value) {
|
||||
PathAddress redirectRewriteAddr = PathAddress.pathAddress(parent, PathElement.pathElement("redirect-rewrite-rule", key));
|
||||
ModelNode redirectRewriteOp = new ModelNode();
|
||||
redirectRewriteOp.get(ModelDescriptionConstants.OP_ADDR).set(redirectRewriteAddr.toModelNode());
|
||||
ModelNode rule = new ModelNode();
|
||||
rule.get("value").set(value);
|
||||
service.addRedirectRewriteRule(redirectRewriteOp, rule);
|
||||
}
|
||||
}
|
|
@ -1,99 +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.
|
||||
-->
|
||||
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
|
||||
<realm name="master">
|
||||
<realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<truststore>truststore.jks</truststore>
|
||||
<truststore-password>secret</truststore-password>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<allow-any-hostname>false</allow-any-hostname>
|
||||
<disable-trust-manager>true</disable-trust-manager>
|
||||
<connection-pool-size>20</connection-pool-size>
|
||||
<enable-cors>true</enable-cors>
|
||||
<client-keystore>keys.jks</client-keystore>
|
||||
<client-keystore-password>secret</client-keystore-password>
|
||||
<client-key-password>secret</client-key-password>
|
||||
<cors-max-age>600</cors-max-age>
|
||||
<cors-allowed-headers>X-Custom</cors-allowed-headers>
|
||||
<cors-allowed-methods>PUT,POST,DELETE,GET</cors-allowed-methods>
|
||||
<expose-token>false</expose-token>
|
||||
<auth-server-url-for-backend-requests>http://127.0.0.2:8080/auth</auth-server-url-for-backend-requests>
|
||||
<always-refresh-token>false</always-refresh-token>
|
||||
<register-node-at-startup>true</register-node-at-startup>
|
||||
<register-node-period>60</register-node-period>
|
||||
<token-store>session</token-store>
|
||||
<principal-attribute>sub</principal-attribute>
|
||||
<proxy-url>http://localhost:9000</proxy-url>
|
||||
</realm>
|
||||
<realm name="jboss-infra">
|
||||
<realm-public-key>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqKoq+a9MgXepmsPJDmo45qswuChW9pWjanX68oIBuI4hGvhQxFHryCow230A+sr7tFdMQMt8f1l/ysmV/fYAuW29WaoY4kI4Ou1yYPuwywKSsxT6PooTs83hKyZ1h4LZMj5DkLGDDDyVRHob2WmPaYg9RGVRw3iGGsD/p+Yb+L/gnBYQnZZ7lYqmN7h36p5CkzzlgXQA1Ha8sQxL+rJNH8+sZm0vBrKsoII3Of7TqHGsm1RwFV3XCuGJ7S61AbjJMXL5DQgJl9Z5scvxGAyoRLKC294UgMnQdzyBTMPw2GybxkRKmiK2KjQKmcopmrJp/Bt6fBR6ZkGSs9qUlxGHgwIDAQAB</realm-public-key>
|
||||
<auth-server-url>http://localhost:8180/auth</auth-server-url>
|
||||
</realm>
|
||||
<secure-deployment name="web-console">
|
||||
<realm>master</realm>
|
||||
<resource>web-console</resource>
|
||||
<use-resource-role-mappings>true</use-resource-role-mappings>
|
||||
<turn-off-change-session-id-on-login>false</turn-off-change-session-id-on-login>
|
||||
<token-minimum-time-to-live>10</token-minimum-time-to-live>
|
||||
<min-time-between-jwks-requests>20</min-time-between-jwks-requests>
|
||||
<public-key-cache-ttl>3600</public-key-cache-ttl>
|
||||
<realm-public-key>
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB
|
||||
</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<proxy-url>http://localhost:9000</proxy-url>
|
||||
<verify-token-audience>true</verify-token-audience>
|
||||
<credential name="secret">0aa31d98-e0aa-404c-b6e0-e771dba1e798</credential>
|
||||
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">api/$1/</redirect-rewrite-rule>
|
||||
</secure-deployment>
|
||||
<secure-deployment name="http-endpoint">
|
||||
<realm>master</realm>
|
||||
<resource>http-endpoint</resource>
|
||||
<use-resource-role-mappings>true</use-resource-role-mappings>
|
||||
<adapter-state-cookie-path>/</adapter-state-cookie-path>
|
||||
<realm-public-key>
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB
|
||||
</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<credential name="jwt">
|
||||
<client-keystore-file>/tmp/keystore.jks</client-keystore-file>
|
||||
</credential>
|
||||
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">/api/$1/</redirect-rewrite-rule>
|
||||
</secure-deployment>
|
||||
<secure-deployment name="wildfly-management">
|
||||
<realm>jboss-infra</realm>
|
||||
<resource>wildfly-management</resource>
|
||||
<bearer-only>true</bearer-only>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<principal-attribute>preferred_username</principal-attribute>
|
||||
</secure-deployment>
|
||||
<secure-server name="wildfly-console">
|
||||
<realm>jboss-infra</realm>
|
||||
<resource>wildfly-console</resource>
|
||||
<public-client>true</public-client>
|
||||
<adapter-state-cookie-path>/</adapter-state-cookie-path>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<proxy-url>http://localhost:9000</proxy-url>
|
||||
</secure-server>
|
||||
</subsystem>
|
|
@ -1,105 +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.
|
||||
-->
|
||||
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.2">
|
||||
<realm name="master">
|
||||
<realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<truststore>truststore.jks</truststore>
|
||||
<truststore-password>secret</truststore-password>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<allow-any-hostname>false</allow-any-hostname>
|
||||
<disable-trust-manager>true</disable-trust-manager>
|
||||
<connection-pool-size>20</connection-pool-size>
|
||||
<socket-timeout-millis>2000</socket-timeout-millis>
|
||||
<connection-ttl-millis>5000</connection-ttl-millis>
|
||||
<connection-timeout-millis>3000</connection-timeout-millis>
|
||||
<enable-cors>true</enable-cors>
|
||||
<client-keystore>keys.jks</client-keystore>
|
||||
<client-keystore-password>secret</client-keystore-password>
|
||||
<client-key-password>secret</client-key-password>
|
||||
<cors-max-age>600</cors-max-age>
|
||||
<cors-allowed-headers>X-Custom</cors-allowed-headers>
|
||||
<cors-allowed-methods>PUT,POST,DELETE,GET</cors-allowed-methods>
|
||||
<expose-token>false</expose-token>
|
||||
<auth-server-url-for-backend-requests>http://127.0.0.2:8080/auth</auth-server-url-for-backend-requests>
|
||||
<always-refresh-token>false</always-refresh-token>
|
||||
<register-node-at-startup>true</register-node-at-startup>
|
||||
<register-node-period>60</register-node-period>
|
||||
<token-store>session</token-store>
|
||||
<principal-attribute>sub</principal-attribute>
|
||||
<proxy-url>http://localhost:9000</proxy-url>
|
||||
</realm>
|
||||
<realm name="jboss-infra">
|
||||
<realm-public-key>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqKoq+a9MgXepmsPJDmo45qswuChW9pWjanX68oIBuI4hGvhQxFHryCow230A+sr7tFdMQMt8f1l/ysmV/fYAuW29WaoY4kI4Ou1yYPuwywKSsxT6PooTs83hKyZ1h4LZMj5DkLGDDDyVRHob2WmPaYg9RGVRw3iGGsD/p+Yb+L/gnBYQnZZ7lYqmN7h36p5CkzzlgXQA1Ha8sQxL+rJNH8+sZm0vBrKsoII3Of7TqHGsm1RwFV3XCuGJ7S61AbjJMXL5DQgJl9Z5scvxGAyoRLKC294UgMnQdzyBTMPw2GybxkRKmiK2KjQKmcopmrJp/Bt6fBR6ZkGSs9qUlxGHgwIDAQAB</realm-public-key>
|
||||
<auth-server-url>http://localhost:8180/auth</auth-server-url>
|
||||
</realm>
|
||||
<secure-deployment name="web-console">
|
||||
<realm>master</realm>
|
||||
<resource>web-console</resource>
|
||||
<use-resource-role-mappings>true</use-resource-role-mappings>
|
||||
<turn-off-change-session-id-on-login>false</turn-off-change-session-id-on-login>
|
||||
<token-minimum-time-to-live>10</token-minimum-time-to-live>
|
||||
<min-time-between-jwks-requests>20</min-time-between-jwks-requests>
|
||||
<public-key-cache-ttl>3600</public-key-cache-ttl>
|
||||
<realm-public-key>
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB
|
||||
</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<proxy-url>http://localhost:9000</proxy-url>
|
||||
<verify-token-audience>true</verify-token-audience>
|
||||
<credential name="secret">0aa31d98-e0aa-404c-b6e0-e771dba1e798</credential>
|
||||
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">api/$1/</redirect-rewrite-rule>
|
||||
</secure-deployment>
|
||||
<secure-deployment name="http-endpoint">
|
||||
<realm>master</realm>
|
||||
<resource>http-endpoint</resource>
|
||||
<use-resource-role-mappings>true</use-resource-role-mappings>
|
||||
<adapter-state-cookie-path>/</adapter-state-cookie-path>
|
||||
<realm-public-key>
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4siLKUew0WYxdtq6/rwk4Uj/4amGFFnE/yzIxQVU0PUqz3QBRVkUWpDj0K6ZnS5nzJV/y6DHLEy7hjZTdRDphyF1sq09aDOYnVpzu8o2sIlMM8q5RnUyEfIyUZqwo8pSZDJ90fS0s+IDUJNCSIrAKO3w1lqZDHL6E/YFHXyzkvQIDAQAB
|
||||
</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<credential name="jwt">
|
||||
<client-keystore-file>/tmp/keystore.jks</client-keystore-file>
|
||||
</credential>
|
||||
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">/api/$1/</redirect-rewrite-rule>
|
||||
</secure-deployment>
|
||||
<secure-deployment name="wildfly-management">
|
||||
<realm>jboss-infra</realm>
|
||||
<resource>wildfly-management</resource>
|
||||
<bearer-only>true</bearer-only>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<socket-timeout-millis>10000</socket-timeout-millis>
|
||||
<connection-ttl-millis>40000</connection-ttl-millis>
|
||||
<connection-timeout-millis>50000</connection-timeout-millis>
|
||||
<principal-attribute>preferred_username</principal-attribute>
|
||||
</secure-deployment>
|
||||
<secure-server name="wildfly-console">
|
||||
<realm>jboss-infra</realm>
|
||||
<resource>wildfly-console</resource>
|
||||
<public-client>true</public-client>
|
||||
<adapter-state-cookie-path>/</adapter-state-cookie-path>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<proxy-url>http://localhost:9000</proxy-url>
|
||||
</secure-server>
|
||||
</subsystem>
|
|
@ -1,36 +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">
|
||||
<parent>
|
||||
<artifactId>keycloak-distribution-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>Adapters Distribution Parent</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-adapters-distribution-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>wildfly-adapter</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -1,63 +0,0 @@
|
|||
if (outcome != success) of /extension=org.keycloak.keycloak-adapter-subsystem:read-resource
|
||||
/extension=org.keycloak.keycloak-adapter-subsystem/:add(module=org.keycloak.keycloak-adapter-subsystem)
|
||||
else
|
||||
echo Keycloak OpenID Connect Extension already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=keycloak:read-resource
|
||||
/subsystem=keycloak:add
|
||||
else
|
||||
echo Keycloak OpenID Connect Subsystem already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/custom-realm=KeycloakOIDCRealm:read-resource
|
||||
/subsystem=elytron/custom-realm=KeycloakOIDCRealm:add(class-name=org.keycloak.adapters.elytron.KeycloakSecurityRealm, module=org.keycloak.keycloak-wildfly-elytron-oidc-adapter)
|
||||
else
|
||||
echo Keycloak OpenID Connect Realm already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/security-domain=KeycloakDomain:read-resource
|
||||
/subsystem=elytron/security-domain=KeycloakDomain:add(default-realm=KeycloakOIDCRealm,permission-mapper=default-permission-mapper,security-event-listener=local-audit,realms=[{realm=KeycloakOIDCRealm}])
|
||||
else
|
||||
echo Keycloak Security Domain already installed. Trying to install Keycloak OpenID Connect Realm.
|
||||
/subsystem=elytron/security-domain=KeycloakDomain:list-add(name=realms, value={realm=KeycloakOIDCRealm})
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/constant-realm-mapper=keycloak-oidc-realm-mapper:read-resource
|
||||
/subsystem=elytron/constant-realm-mapper=keycloak-oidc-realm-mapper:add(realm-name=KeycloakOIDCRealm)
|
||||
else
|
||||
echo Keycloak OpenID Connect Realm Mapper already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/service-loader-http-server-mechanism-factory=keycloak-oidc-http-server-mechanism-factory:read-resource
|
||||
/subsystem=elytron/service-loader-http-server-mechanism-factory=keycloak-oidc-http-server-mechanism-factory:add(module=org.keycloak.keycloak-wildfly-elytron-oidc-adapter)
|
||||
else
|
||||
echo Keycloak OpenID Connect HTTP Mechanism already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:read-resource
|
||||
/subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-mechanism-factories=[keycloak-oidc-http-server-mechanism-factory, global])
|
||||
else
|
||||
echo Keycloak HTTP Mechanism Factory already installed. Trying to install Keycloak OpenID Connect HTTP Mechanism Factory.
|
||||
/subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-mechanism-factories, value=keycloak-oidc-http-server-mechanism-factory)
|
||||
end-if
|
||||
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/http-authentication-factory=keycloak-http-authentication:read-resource
|
||||
/subsystem=elytron/http-authentication-factory=keycloak-http-authentication:add(security-domain=KeycloakDomain,http-server-mechanism-factory=keycloak-http-server-mechanism-factory,mechanism-configurations=[{mechanism-name=KEYCLOAK,mechanism-realm-configurations=[{realm-name=KeycloakOIDCRealm,realm-mapper=keycloak-oidc-realm-mapper}]}])
|
||||
else
|
||||
echo Keycloak HTTP Authentication Factory already installed. Trying to install Keycloak OpenID Connect Mechanism Configuration
|
||||
/subsystem=elytron/http-authentication-factory=keycloak-http-authentication:list-add(name=mechanism-configurations, value={mechanism-name=KEYCLOAK,mechanism-realm-configurations=[{realm-name=KeycloakOIDCRealm,realm-mapper=keycloak-oidc-realm-mapper}]})
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=undertow/application-security-domain=other:read-resource
|
||||
/subsystem=undertow/application-security-domain=other:add(http-authentication-factory=keycloak-http-authentication)
|
||||
else
|
||||
echo Undertow already configured with Keycloak
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=ejb3/application-security-domain=other:read-resource
|
||||
/subsystem=ejb3/application-security-domain=other:add(security-domain=KeycloakDomain)
|
||||
else
|
||||
echo EJB already configured with Keycloak
|
||||
end-if
|
|
@ -1,4 +0,0 @@
|
|||
/subsystem=security/security-domain=keycloak/:add
|
||||
/subsystem=security/security-domain=keycloak/authentication=classic/:add(login-modules=[{ "code" => "org.keycloak.adapters.jboss.KeycloakLoginModule","flag" => "required"}])
|
||||
/extension=org.keycloak.keycloak-adapter-subsystem/:add(module=org.keycloak.keycloak-adapter-subsystem)
|
||||
/subsystem=keycloak:add
|
|
@ -1,89 +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>server-dist</id>
|
||||
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>target/${project.build.finalName}</directory>
|
||||
<outputDirectory/>
|
||||
<filtered>true</filtered>
|
||||
<includes>
|
||||
<include>**/module.xml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>target/${project.build.finalName}</directory>
|
||||
<outputDirectory/>
|
||||
<filtered>false</filtered>
|
||||
<excludes>
|
||||
<exclude>docs/schema/**</exclude>
|
||||
<exclude>README.md</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>target/${project.build.finalName}</directory>
|
||||
<outputDirectory/>
|
||||
<includes>
|
||||
<include>bin/*.sh</include>
|
||||
</includes>
|
||||
<fileMode>0755</fileMode>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>target/${project.build.finalName}</directory>
|
||||
<outputDirectory/>
|
||||
<includes>
|
||||
<include>themes/**</include>
|
||||
</includes>
|
||||
<fileMode>0444</fileMode>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/modules</directory>
|
||||
<outputDirectory>modules</outputDirectory>
|
||||
<includes>
|
||||
<include>layers.conf</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<files>
|
||||
<file>
|
||||
<source>../shared-cli/adapter-install.cli</source>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
</file>
|
||||
<file>
|
||||
<source>cli/adapter-install-offline.cli</source>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
</file>
|
||||
<file>
|
||||
<source>../shared-cli/adapter-elytron-install.cli</source>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
</file>
|
||||
<file>
|
||||
<source>cli/adapter-elytron-install-offline.cli</source>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
</assembly>
|
|
@ -1,65 +0,0 @@
|
|||
embed-server --server-config=${server.config:standalone.xml}
|
||||
|
||||
if (outcome != success) of /extension=org.keycloak.keycloak-adapter-subsystem:read-resource
|
||||
/extension=org.keycloak.keycloak-adapter-subsystem/:add(module=org.keycloak.keycloak-adapter-subsystem)
|
||||
else
|
||||
echo Keycloak OpenID Connect Extension already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=keycloak:read-resource
|
||||
/subsystem=keycloak:add
|
||||
else
|
||||
echo Keycloak OpenID Connect Subsystem already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/custom-realm=KeycloakOIDCRealm:read-resource
|
||||
/subsystem=elytron/custom-realm=KeycloakOIDCRealm:add(class-name=org.keycloak.adapters.elytron.KeycloakSecurityRealm, module=org.keycloak.keycloak-wildfly-elytron-oidc-adapter)
|
||||
else
|
||||
echo Keycloak OpenID Connect Realm already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/security-domain=KeycloakDomain:read-resource
|
||||
/subsystem=elytron/security-domain=KeycloakDomain:add(default-realm=KeycloakOIDCRealm,permission-mapper=default-permission-mapper,security-event-listener=local-audit,realms=[{realm=KeycloakOIDCRealm}])
|
||||
else
|
||||
echo Keycloak Security Domain already installed. Trying to install Keycloak OpenID Connect Realm.
|
||||
/subsystem=elytron/security-domain=KeycloakDomain:list-add(name=realms, value={realm=KeycloakOIDCRealm})
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/constant-realm-mapper=keycloak-oidc-realm-mapper:read-resource
|
||||
/subsystem=elytron/constant-realm-mapper=keycloak-oidc-realm-mapper:add(realm-name=KeycloakOIDCRealm)
|
||||
else
|
||||
echo Keycloak OpenID Connect Realm Mapper already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/service-loader-http-server-mechanism-factory=keycloak-oidc-http-server-mechanism-factory:read-resource
|
||||
/subsystem=elytron/service-loader-http-server-mechanism-factory=keycloak-oidc-http-server-mechanism-factory:add(module=org.keycloak.keycloak-wildfly-elytron-oidc-adapter)
|
||||
else
|
||||
echo Keycloak OpenID Connect HTTP Mechanism already installed
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:read-resource
|
||||
/subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-mechanism-factories=[keycloak-oidc-http-server-mechanism-factory, global])
|
||||
else
|
||||
echo Keycloak HTTP Mechanism Factory already installed. Trying to install Keycloak OpenID Connect HTTP Mechanism Factory.
|
||||
/subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-mechanism-factories, value=keycloak-oidc-http-server-mechanism-factory)
|
||||
end-if
|
||||
|
||||
|
||||
if (outcome != success) of /subsystem=elytron/http-authentication-factory=keycloak-http-authentication:read-resource
|
||||
/subsystem=elytron/http-authentication-factory=keycloak-http-authentication:add(security-domain=KeycloakDomain,http-server-mechanism-factory=keycloak-http-server-mechanism-factory,mechanism-configurations=[{mechanism-name=KEYCLOAK,mechanism-realm-configurations=[{realm-name=KeycloakOIDCRealm,realm-mapper=keycloak-oidc-realm-mapper}]}])
|
||||
else
|
||||
echo Keycloak HTTP Authentication Factory already installed. Trying to install Keycloak OpenID Connect Mechanism Configuration
|
||||
/subsystem=elytron/http-authentication-factory=keycloak-http-authentication:list-add(name=mechanism-configurations, value={mechanism-name=KEYCLOAK,mechanism-realm-configurations=[{realm-name=KeycloakOIDCRealm,realm-mapper=keycloak-oidc-realm-mapper}]})
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=undertow/application-security-domain=other:read-resource
|
||||
/subsystem=undertow/application-security-domain=other:add(http-authentication-factory=keycloak-http-authentication)
|
||||
else
|
||||
echo Undertow already configured with Keycloak
|
||||
end-if
|
||||
|
||||
if (outcome != success) of /subsystem=ejb3/application-security-domain=other:read-resource
|
||||
/subsystem=ejb3/application-security-domain=other:add(security-domain=KeycloakDomain)
|
||||
else
|
||||
echo EJB already configured with Keycloak
|
||||
end-if
|
|
@ -1,5 +0,0 @@
|
|||
embed-server --server-config=${server.config:standalone.xml}
|
||||
/subsystem=security/security-domain=keycloak/:add
|
||||
/subsystem=security/security-domain=keycloak/authentication=classic/:add(login-modules=[{ "code" => "org.keycloak.adapters.jboss.KeycloakLoginModule","flag" => "required"}])
|
||||
/extension=org.keycloak.keycloak-adapter-subsystem/:add(module=org.keycloak.keycloak-adapter-subsystem)
|
||||
/subsystem=keycloak:add
|
|
@ -1,93 +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-adapters-distribution-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<wildfly.version>23.0.2.Final</wildfly.version>
|
||||
<wildfly.build-tools.version>1.2.13.Final</wildfly.build-tools.version>
|
||||
<wildfly.core.version>15.0.1.Final</wildfly.core.version>
|
||||
<org.wildfly.galleon-plugins.version>5.1.3.Final</org.wildfly.galleon-plugins.version>
|
||||
<assemblyFile>assembly.xml</assemblyFile>
|
||||
</properties>
|
||||
|
||||
<artifactId>keycloak-wildfly-adapter-dist</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Keycloak Adapter Overlay Distribution</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-feature-pack</artifactId>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.wildfly.build</groupId>
|
||||
<artifactId>wildfly-server-provisioning-maven-plugin</artifactId>
|
||||
<version>${wildfly.build-tools.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>server-provisioning</id>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
<configuration>
|
||||
<config-file>server-provisioning.xml</config-file>
|
||||
<overlay>true</overlay>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>assemble</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${assemblyFile}</descriptor>
|
||||
</descriptors>
|
||||
<recompressZippedFiles>true</recompressZippedFiles>
|
||||
<finalName>${project.build.finalName}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||
<workDirectory>${project.build.directory}/assembly/work</workDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,21 +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.
|
||||
-->
|
||||
<server-provisioning xmlns="urn:wildfly:server-provisioning:1.2" extract-schemas="true" copy-module-artifacts="true">
|
||||
<feature-packs>
|
||||
<feature-pack groupId="org.keycloak" artifactId="keycloak-adapter-feature-pack" version="${project.version}"/>
|
||||
</feature-packs>
|
||||
</server-provisioning>
|
|
@ -92,26 +92,6 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-subsystem</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
|
|
|
@ -1,31 +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.3" name="org.keycloak.keycloak-adapter-subsystem">
|
||||
<properties>
|
||||
<property name="jboss.api" value="private"/>
|
||||
</properties>
|
||||
<resources>
|
||||
<resource-root path="."/>
|
||||
</resources>
|
||||
|
||||
<dependencies>
|
||||
<module name="org.keycloak.keycloak-wildfly-subsystem" export="true" services="export"/>
|
||||
</dependencies>
|
||||
</module>
|
|
@ -1,51 +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.3" name="org.keycloak.keycloak-wildfly-elytron-oidc-adapter">
|
||||
<properties>
|
||||
<property name="jboss.api" value="private"/>
|
||||
</properties>
|
||||
<resources>
|
||||
<artifact name="${org.keycloak:keycloak-wildfly-elytron-oidc-adapter}"/>
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="org.bouncycastle" />
|
||||
<module name="com.fasterxml.jackson.core.jackson-annotations"/>
|
||||
<module name="com.fasterxml.jackson.core.jackson-core"/>
|
||||
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
||||
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-undertow-adapter"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-common"/>
|
||||
<module name="org.wildfly.security.elytron" optional="true"/>
|
||||
<module name="org.wildfly.security.elytron-web.undertow-server" optional="true"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -1,47 +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.3" name="org.keycloak.keycloak-wildfly-subsystem">
|
||||
<properties>
|
||||
<property name="jboss.api" value="private"/>
|
||||
</properties>
|
||||
<resources>
|
||||
<resource-root path="."/>
|
||||
<artifact name="${org.keycloak:keycloak-wildfly-subsystem}"/>
|
||||
</resources>
|
||||
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="org.jboss.staxmapper"/>
|
||||
<module name="org.jboss.as.controller"/>
|
||||
<module name="org.jboss.as.ee"/>
|
||||
<module name="org.jboss.as.server"/>
|
||||
<module name="org.jboss.modules"/>
|
||||
<module name="org.jboss.msc"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.jboss.vfs"/>
|
||||
<module name="org.jboss.as.web-common"/>
|
||||
<module name="org.jboss.metadata.common"/>
|
||||
<module name="org.jboss.metadata.web"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-wildfly-elytron-oidc-adapter"/>
|
||||
<module name="org.wildfly.security.elytron" optional="true"/>
|
||||
<module name="io.undertow.core"/>
|
||||
</dependencies>
|
||||
</module>
|
|
@ -41,7 +41,6 @@
|
|||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>adapters</module>
|
||||
<module>saml-adapters</module>
|
||||
<module>feature-packs</module>
|
||||
<module>galleon-feature-packs</module>
|
||||
|
|
16
pom.xml
16
pom.xml
|
@ -1048,11 +1048,6 @@
|
|||
<artifactId>keycloak-as7-subsystem</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-subsystem</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-server-subsystem</artifactId>
|
||||
|
@ -1093,11 +1088,6 @@
|
|||
<artifactId>keycloak-undertow-adapter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-wildfly-elytron-adapter</artifactId>
|
||||
|
@ -1312,12 +1302,6 @@
|
|||
<version>${project.version}</version>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-wildfly-adapter-dist</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
embed-server --server-config=standalone.xml
|
||||
|
||||
/subsystem=keycloak/secure-deployment=customer-portal-subsystem.war/:add( \
|
||||
realm=demo, \
|
||||
resource=customer-portal-subsystem, \
|
||||
auth-server-url=${auth.server.actual.protocol:https}://${auth.server.host:localhost}:${auth.server.https.port:8543}/auth, \
|
||||
ssl-required=EXTERNAL, \
|
||||
disable-trust-manager=true, \
|
||||
)
|
||||
/subsystem=keycloak/secure-deployment=customer-portal-subsystem.war/credential=secret/:add(value=password)
|
||||
|
||||
/subsystem=keycloak/secure-deployment=product-portal-subsystem.war/:add( \
|
||||
realm=demo, \
|
||||
resource=product-portal-subsystem, \
|
||||
auth-server-url=${auth.server.actual.protocol:https}://${auth.server.host:localhost}:${auth.server.https.port:8543}/auth, \
|
||||
ssl-required=EXTERNAL, \
|
||||
disable-trust-manager=true, \
|
||||
)
|
||||
/subsystem=keycloak/secure-deployment=product-portal-subsystem.war/credential=secret/:add(value=password)
|
|
@ -37,7 +37,6 @@
|
|||
<app.server.jboss.version>${eap.version}</app.server.jboss.version>
|
||||
<app.server.jboss.unpacked.folder.name>jboss-eap-7.4</app.server.jboss.unpacked.folder.name>
|
||||
|
||||
<app.server.oidc.adapter.artifactId>keycloak-wildfly-adapter-dist</app.server.oidc.adapter.artifactId>
|
||||
<app.server.saml.adapter.artifactId>keycloak-saml-wildfly-adapter-dist</app.server.saml.adapter.artifactId>
|
||||
|
||||
<skip.elytron.adapter.installation>false</skip.elytron.adapter.installation>
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArch
|
|||
import org.jboss.arquillian.test.spi.TestClass;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.shrinkwrap.api.Archive;
|
||||
import org.keycloak.testsuite.utils.annotation.UseServletFilter;
|
||||
import org.keycloak.testsuite.utils.arquillian.DeploymentArchiveProcessorUtils;
|
||||
|
||||
/**
|
||||
|
@ -35,8 +34,6 @@ public class EAPDeploymentArchiveProcessor implements ApplicationArchiveProcesso
|
|||
public void process(Archive<?> archive, TestClass testClass) {
|
||||
if (DeploymentArchiveProcessorUtils.checkRunOnServerDeployment(archive)) return;
|
||||
|
||||
modifyWebXML(archive, testClass);
|
||||
|
||||
modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
|
||||
modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH_JS);
|
||||
|
||||
|
@ -45,16 +42,6 @@ public class EAPDeploymentArchiveProcessor implements ApplicationArchiveProcesso
|
|||
modifySAMLAdapterConfig(archive, DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH_TENANT2);
|
||||
}
|
||||
|
||||
private void modifyWebXML(Archive<?> archive, TestClass testClass) {
|
||||
if (!archive.contains(DeploymentArchiveProcessorUtils.WEBXML_PATH)) return;
|
||||
if (!testClass.getJavaClass().isAnnotationPresent(UseServletFilter.class)) return;
|
||||
if (!archive.contains(DeploymentArchiveProcessorUtils.JBOSS_DEPLOYMENT_XML_PATH)) return;
|
||||
|
||||
log.debug("Modifying WEB.XML in " + archive.getName() + " for Servlet Filter.");
|
||||
DeploymentArchiveProcessorUtils.modifyWebXMLForServletFilter(archive, testClass);
|
||||
DeploymentArchiveProcessorUtils.addFilterDependencies(archive, testClass);
|
||||
}
|
||||
|
||||
private void modifyOIDCAdapterConfig(Archive<?> archive, String adapterConfigPath) {
|
||||
if (!archive.contains(adapterConfigPath)) return;
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
<fuse.installer.artifactId>fuse-eap-installer</fuse.installer.artifactId>
|
||||
<fuse.installer.version>${fuse63.version}</fuse.installer.version>
|
||||
|
||||
<app.server.oidc.adapter.artifactId>keycloak-eap6-adapter-dist</app.server.oidc.adapter.artifactId>
|
||||
<app.server.saml.adapter.artifactId>keycloak-saml-eap6-adapter-dist</app.server.saml.adapter.artifactId>
|
||||
<skip.apply.offline.cli>true</skip.apply.offline.cli>
|
||||
<skip.configure.clustered.scenario>true</skip.configure.clustered.scenario>
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArch
|
|||
import org.jboss.arquillian.test.spi.TestClass;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.shrinkwrap.api.Archive;
|
||||
import org.keycloak.testsuite.utils.annotation.UseServletFilter;
|
||||
import org.keycloak.testsuite.utils.arquillian.DeploymentArchiveProcessorUtils;
|
||||
|
||||
public class EAP8DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
|
||||
|
@ -44,12 +43,7 @@ public class EAP8DeploymentArchiveProcessor implements ApplicationArchiveProcess
|
|||
|
||||
DeploymentArchiveProcessorUtils.useJakartaEEServletClass(archive, DeploymentArchiveProcessorUtils.WEBXML_PATH);
|
||||
|
||||
if (!testClass.getJavaClass().isAnnotationPresent(UseServletFilter.class)) return;
|
||||
if (!archive.contains(DeploymentArchiveProcessorUtils.JBOSS_DEPLOYMENT_XML_PATH)) return;
|
||||
|
||||
log.debug("Modifying WEB.XML in " + archive.getName() + " for Servlet Filter.");
|
||||
DeploymentArchiveProcessorUtils.modifyWebXMLForServletFilter(archive, testClass);
|
||||
DeploymentArchiveProcessorUtils.addFilterDependencies(archive, testClass);
|
||||
}
|
||||
|
||||
private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
<assembly.xml>${project.parent.basedir}/assembly.xml</assembly.xml>
|
||||
<app.server.jboss.home>${containers.home}/${app.server.jboss.unpacked.folder.name}</app.server.jboss.home>
|
||||
<app.server.jboss.unpacked.folder.path>${containers.home}</app.server.jboss.unpacked.folder.path>
|
||||
<app.server.oidc.adapter.artifactId>keycloak-wildfly-adapter-dist</app.server.oidc.adapter.artifactId>
|
||||
|
||||
<oidc-adapter.version>${project.version}</oidc-adapter.version>
|
||||
<saml-adapter.version>${project.version}</saml-adapter.version>
|
||||
|
@ -76,18 +75,6 @@
|
|||
</activation>
|
||||
<dependencies>
|
||||
<!-- These ZIPs can be fetched from artifactItems, but we need to properly assess the Maven build execution order -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>${app.server.oidc.adapter.artifactId}</artifactId>
|
||||
<version>${oidc-adapter.version}</version>
|
||||
<type>zip</type>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>${app.server.saml.adapter.artifactId}</artifactId>
|
||||
|
@ -119,7 +106,6 @@
|
|||
<property>app.server.jboss.artifactId</property>
|
||||
<property>app.server.jboss.version</property>
|
||||
<property>app.server.jboss.unpacked.folder.name</property>
|
||||
<property>app.server.oidc.adapter.artifactId</property>
|
||||
</requireProperty>
|
||||
</rules>
|
||||
</configuration>
|
||||
|
@ -148,25 +134,6 @@
|
|||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>unpack-oidc-adapter</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>${skip.oidc.adapter.installation}</skip>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>${app.server.oidc.adapter.artifactId}</artifactId>
|
||||
<version>${oidc-adapter.version}</version>
|
||||
<type>zip</type>
|
||||
<outputDirectory>${app.server.jboss.home}</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
@ -356,59 +323,6 @@
|
|||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<!--OIDC: eap, wf11-->
|
||||
<id>adapter-elytron-install-offline-standalone</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>${skip.elytron.adapter.installation}</skip>
|
||||
<executable>${cli.executable}</executable>
|
||||
<workingDirectory>${cli.working.dir}</workingDirectory>
|
||||
<environmentVariables>
|
||||
<JAVA_HOME>${app.server.java.home}</JAVA_HOME>
|
||||
</environmentVariables>
|
||||
<arguments>
|
||||
<argument>${cli.jboss-cli.arg}</argument>
|
||||
<argument>--file=${app.server.jboss.home}/bin/adapter-elytron-install-offline.cli</argument>
|
||||
<!--
|
||||
following attribute is required just for windows
|
||||
see ${common.resources}/win/run-jboss-cli.bat
|
||||
!! the ordering is important, if you need to change it edit run-jboss-cli.bat !!
|
||||
-->
|
||||
<argument>${cli.win.working.dir}</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<!--OIDC: eap, wf11-->
|
||||
<id>adapter-elytron-install-offline-standalone-ha</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>${skip.elytron.adapter.installation}</skip>
|
||||
<executable>${cli.executable}</executable>
|
||||
<workingDirectory>${cli.working.dir}</workingDirectory>
|
||||
<environmentVariables>
|
||||
<JAVA_HOME>${app.server.java.home}</JAVA_HOME>
|
||||
</environmentVariables>
|
||||
<arguments>
|
||||
<argument>${cli.jboss-cli.arg}</argument>
|
||||
<argument>--file=${app.server.jboss.home}/bin/adapter-elytron-install-offline.cli</argument>
|
||||
<!--
|
||||
following attribute is required just for windows
|
||||
see ${common.resources}/win/run-jboss-cli.bat
|
||||
!! the ordering is important, if you need to change it edit run-jboss-cli.bat !!
|
||||
-->
|
||||
<argument>${cli.win.working.dir}</argument>
|
||||
<argument>-Dserver.config=standalone-ha.xml</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<!--SAML: eap, wf11-->
|
||||
<id>adapter-elytron-install-saml-offline-standalone</id>
|
||||
|
@ -614,32 +528,6 @@
|
|||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>add-secured-deployments</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>${skip.apply.offline.cli}</skip><!--eap6-->
|
||||
<executable>${cli.executable}</executable>
|
||||
<workingDirectory>${cli.working.dir}</workingDirectory>
|
||||
<environmentVariables>
|
||||
<JAVA_HOME>${app.server.java.home}</JAVA_HOME>
|
||||
</environmentVariables>
|
||||
<arguments>
|
||||
<argument>${cli.jboss-cli.arg}</argument>
|
||||
<argument>--file=${common.resources}/cli/add-secured-deployments.cli</argument>
|
||||
<!--
|
||||
following attribute is required just for windows
|
||||
see ${common.resources}/win/run-jboss-cli.bat
|
||||
!! the ordering is important, if you need to change it edit run-jboss-cli.bat !!
|
||||
-->
|
||||
<argument>${cli.win.working.dir}</argument>
|
||||
<argument>-Djboss.server.config.dir=${app.server.jboss.home}/standalone-secured-deployments/configuration</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>configure-cluster-config</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
<app.server.jboss.version>${wildfly.server.version}</app.server.jboss.version>
|
||||
<app.server.jboss.unpacked.folder.name>wildfly-${wildfly.server.version}</app.server.jboss.unpacked.folder.name>
|
||||
|
||||
<app.server.oidc.adapter.artifactId>keycloak-wildfly-adapter-dist</app.server.oidc.adapter.artifactId>
|
||||
<app.server.saml.adapter.artifactId>keycloak-saml-wildfly-adapter-dist</app.server.saml.adapter.artifactId>
|
||||
|
||||
<skip.elytron.adapter.installation>false</skip.elytron.adapter.installation>
|
||||
|
|
|
@ -48,11 +48,7 @@ import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class DefaultAuthzConfigAdapterTest extends AbstractExampleAdapterTest {
|
||||
|
||||
private static final String REALM_NAME = "hello-world-authz";
|
||||
|
|
|
@ -35,11 +35,7 @@ import static org.hamcrest.Matchers.is;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class PermissiveModeAdapterTest extends AbstractBaseServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -38,11 +38,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletAuthzCIPAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -30,11 +30,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletAuthzCacheDisabledAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -29,11 +29,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletAuthzCacheLifespanAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -28,11 +28,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletAuthzLazyLoadPathsAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -26,11 +26,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletAuthzNoLazyLoadPathsAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -26,11 +26,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletPolicyEnforcerLifespanTest extends AbstractServletPolicyEnforcerTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -24,11 +24,7 @@ import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
|||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ServletPolicyEnforcerTest extends AbstractServletPolicyEnforcerTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.adapter.example.cors;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.page.AngularCorsProductTestApp;
|
||||
import org.keycloak.testsuite.adapter.page.CorsDatabaseServiceTestApp;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.JavascriptBrowser;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.auth.page.login.OIDCLogin;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
import org.keycloak.testsuite.util.DroneUtils;
|
||||
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||
|
||||
/**
|
||||
* Tests CORS functionality in adapters.
|
||||
*
|
||||
* <p>
|
||||
* Note, for SSL this test disables TLS certificate verification. Since CORS uses different hostnames
|
||||
* (localhost-auth for example), the Subject Name won't match.
|
||||
* </p>
|
||||
*
|
||||
* @author fkiss
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class CorsExampleAdapterTest extends AbstractExampleAdapterTest {
|
||||
|
||||
public static final String CORS = "cors";
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
// Javascript browser needed, but not PhantomJS
|
||||
@Drone
|
||||
@JavascriptBrowser
|
||||
protected WebDriver jsDriver;
|
||||
|
||||
@Page
|
||||
@JavascriptBrowser
|
||||
protected OIDCLogin jsDriverTestRealmLoginPage;
|
||||
|
||||
@Page
|
||||
@JavascriptBrowser
|
||||
private AngularCorsProductTestApp jsDriverAngularCorsProductPage;
|
||||
|
||||
@Deployment(name = AngularCorsProductTestApp.DEPLOYMENT_NAME, managed = false)
|
||||
protected static WebArchive angularCorsProductExample() throws IOException {
|
||||
return exampleDeployment(AngularCorsProductTestApp.CLIENT_ID);
|
||||
}
|
||||
|
||||
@Deployment(name = CorsDatabaseServiceTestApp.DEPLOYMENT_NAME, managed = false)
|
||||
protected static WebArchive corsDatabaseServiceExample() throws IOException {
|
||||
return exampleDeployment(CorsDatabaseServiceTestApp.CLIENT_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(
|
||||
loadRealm(new File(TEST_APPS_HOME_DIR + "/cors/cors-realm.json")));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void onBefore() {
|
||||
DroneUtils.addWebDriver(jsDriver);
|
||||
deployer.deploy(CorsDatabaseServiceTestApp.DEPLOYMENT_NAME);
|
||||
deployer.deploy(AngularCorsProductTestApp.DEPLOYMENT_NAME);
|
||||
}
|
||||
|
||||
@After
|
||||
public void onAfter() {
|
||||
deployer.undeploy(CorsDatabaseServiceTestApp.DEPLOYMENT_NAME);
|
||||
deployer.undeploy(AngularCorsProductTestApp.DEPLOYMENT_NAME);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
jsDriverTestRealmLoginPage.setAuthRealm(CORS);
|
||||
oauth.realm(CORS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void angularCorsProductTest() {
|
||||
jsDriverAngularCorsProductPage.navigateTo();
|
||||
jsDriverTestRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
|
||||
assertCurrentUrlStartsWith(jsDriverAngularCorsProductPage);
|
||||
jsDriverAngularCorsProductPage.reloadData();
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("iphone");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("ipad");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("ipod");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getHeaders()).text().contains("\"x-custom1\":\"some-value\"");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getHeaders()).text().contains("\"www-authenticate\":\"some-value\"");
|
||||
|
||||
jsDriverAngularCorsProductPage.loadRoles();
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("user");
|
||||
|
||||
jsDriverAngularCorsProductPage.addRole();
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("stuff");
|
||||
|
||||
jsDriverAngularCorsProductPage.deleteRole();
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().not().contains("stuff");
|
||||
|
||||
jsDriverAngularCorsProductPage.loadAvailableSocialProviders();
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("twitter");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("google");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("linkedin");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("facebook");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("stackoverflow");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("github");
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("microsoft");
|
||||
|
||||
jsDriverAngularCorsProductPage.loadPublicRealmInfo();
|
||||
waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("Realm name: cors");
|
||||
|
||||
String serverVersion = getAuthServerVersion();
|
||||
assertNotNull(serverVersion);
|
||||
|
||||
jsDriverAngularCorsProductPage.navigateTo();
|
||||
waitForPageToLoad();
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getAuthServerVersion() {
|
||||
DroneUtils.getCurrentDriver().navigate().to(suiteContext.getAuthServerInfo().getContextRoot().toString() +
|
||||
"/auth/admin/master/console/#/master/info");
|
||||
jsDriverTestRealmLoginPage.form().login("admin", "admin");
|
||||
// just get the first list description which is the version
|
||||
List<WebElement> elements = jsDriver.findElements(By.xpath(".//dd[@class='pf-v5-c-description-list__description']"));
|
||||
if (!elements.isEmpty()) {
|
||||
return elements.get(0).getText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -105,10 +105,6 @@ import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWit
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
@EnableFeature(value = Profile.Feature.TOKEN_EXCHANGE, skipRestart = true)
|
||||
@EnableFeature(value = Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, skipRestart = true)
|
||||
public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest {
|
||||
|
|
|
@ -81,10 +81,6 @@ import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class ClientInitiatedAccountLinkTest extends AbstractServletsAdapterTest {
|
||||
public static final String CHILD_IDP = "child";
|
||||
public static final String PARENT_IDP = "parent-idp";
|
||||
|
|
|
@ -138,10 +138,6 @@ import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
|||
* @author tkyjovsk
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class DemoServletsAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -15,8 +15,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
|
||||
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
// The purpose of this class is to test KeycloakPrincipal serialization on different app-server-jdks
|
||||
public class KeycloakPrincipalSerializationTest extends AbstractServletsAdapterTest {
|
||||
@Page
|
||||
|
|
|
@ -42,10 +42,6 @@ import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
|||
* @author Juraci Paixão Kröhling <juraci at kroehling.de>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class MultiTenancyTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -79,10 +79,6 @@ import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
|||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class OIDCPublicKeyRotationAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -50,10 +50,6 @@ import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
|||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Rule
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.adapter.servlet;
|
||||
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.enableHTTPSForAppServer;
|
||||
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SSL_REQUIRED;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.ContainerController;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.After;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
|
||||
import org.keycloak.testsuite.adapter.page.CustomerDb;
|
||||
import org.keycloak.testsuite.adapter.page.CustomerPortalSubsystem;
|
||||
import org.keycloak.testsuite.adapter.page.ProductPortalSubsystem;
|
||||
import org.keycloak.testsuite.arquillian.AppServerTestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.arquillian.containers.SelfManagedAppContainerLifecycle;
|
||||
import org.wildfly.extras.creaper.core.CommandFailedException;
|
||||
import org.wildfly.extras.creaper.core.online.CliException;
|
||||
import org.wildfly.extras.creaper.core.online.operations.OperationException;
|
||||
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class SecuredDeploymentsAdapterTest extends AbstractServletsAdapterTest implements SelfManagedAppContainerLifecycle {
|
||||
|
||||
@ArquillianResource
|
||||
private ContainerController controller;
|
||||
|
||||
@Page
|
||||
private CustomerPortalSubsystem customerPortalSubsystem;
|
||||
|
||||
@Page
|
||||
private ProductPortalSubsystem productPortalSubsystem;
|
||||
|
||||
@Deployment(name = CustomerPortalSubsystem.DEPLOYMENT_NAME)
|
||||
protected static WebArchive customerPortalSubsystem() {
|
||||
return servletDeployment(CustomerPortalSubsystem.DEPLOYMENT_NAME, CustomerServlet.class, ErrorServlet.class, ServletTestUtils.class);
|
||||
}
|
||||
|
||||
@Deployment(name = ProductPortalSubsystem.DEPLOYMENT_NAME)
|
||||
protected static WebArchive productPortalSubsystem() {
|
||||
return servletDeployment(ProductPortalSubsystem.DEPLOYMENT_NAME, ProductServlet.class);
|
||||
}
|
||||
|
||||
@Deployment(name = CustomerDb.DEPLOYMENT_NAME)
|
||||
protected static WebArchive customerDb() {
|
||||
return servletDeployment(CustomerDb.DEPLOYMENT_NAME, AdapterActionsFilter.class, CustomerDatabaseServlet.class);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void assumeTLSEnabled() {
|
||||
Assume.assumeTrue(AUTH_SERVER_SSL_REQUIRED);
|
||||
}
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void startServer() throws InterruptedException, IOException, OperationException, TimeoutException, CommandFailedException, CliException {
|
||||
try {
|
||||
AppServerTestEnricher.prepareServerDir("standalone-secured-deployments");
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Wasn't able to prepare server dir.", ex);
|
||||
}
|
||||
|
||||
controller.start(testContext.getAppServerInfo().getQualifier());
|
||||
|
||||
if (!sslConfigured && super.shouldConfigureSSL()) {
|
||||
enableHTTPSForAppServer();
|
||||
sslConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This is SelfManagedAppContainerLifecycle, we can't enable ssl in before in parent class, because it will fail as
|
||||
// the container is not started yet
|
||||
@Override
|
||||
public boolean shouldConfigureSSL() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@After
|
||||
@Override
|
||||
public void stopServer() {
|
||||
controller.stop(testContext.getAppServerInfo().getQualifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecuredDeployments() {
|
||||
customerPortalSubsystem.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
assertPageContains("Bill Burke");
|
||||
assertPageContains("Stian Thorgersen");
|
||||
|
||||
productPortalSubsystem.navigateTo();
|
||||
assertCurrentUrlEquals(productPortalSubsystem);
|
||||
assertPageContains("iPhone");
|
||||
assertPageContains("iPad");
|
||||
}
|
||||
|
||||
private void assertPageContains(String string) {
|
||||
String pageSource = driver.getPageSource();
|
||||
assertThat(pageSource, containsString(string));
|
||||
}
|
||||
}
|
|
@ -54,10 +54,6 @@ import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
|||
* @author tkyjovsk
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class SessionServletAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -64,10 +64,6 @@ import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
public class UserStorageConsentTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue