diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-subsystem/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-subsystem/main/module.xml index 636909dd99..404393d222 100755 --- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-subsystem/main/module.xml +++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-subsystem/main/module.xml @@ -43,7 +43,10 @@ - + + + + diff --git a/integration/as7-eap-subsystem/pom.xml b/integration/as7-eap-subsystem/pom.xml index 642fefa7d1..8e06da1b80 100755 --- a/integration/as7-eap-subsystem/pom.xml +++ b/integration/as7-eap-subsystem/pom.xml @@ -25,7 +25,7 @@ keycloak-as7-subsystem - Keycloak Wildfly Subsystem + Keycloak Wildfly AS7 Subsystem jar diff --git a/integration/wildfly-subsystem/pom.xml b/integration/wildfly-subsystem/pom.xml index ed0a337428..eaba62ba22 100755 --- a/integration/wildfly-subsystem/pom.xml +++ b/integration/wildfly-subsystem/pom.xml @@ -70,6 +70,11 @@ wildfly-server provided + + org.wildfly.core + wildfly-version + provided + org.wildfly wildfly-ee @@ -110,5 +115,17 @@ junit test + + + org.jboss.as + jboss-as-web + 7.1.1.Final + + + + org.keycloak + keycloak-as7-adapter + ${project.version} + diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/Environment.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/Environment.java new file mode 100644 index 0000000000..243bf94252 --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/Environment.java @@ -0,0 +1,58 @@ +/* + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.extension; + +import org.jboss.as.version.Version; +import org.jboss.modules.Module; +import org.jboss.modules.ModuleIdentifier; +import org.jboss.modules.ModuleLoadException; + +/** + * Allows the Keycloak subsystem to learn about its environment. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ +public class Environment { + private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-subsystem"); + + private static final boolean isWildFly = findIsWildFly(); + + public Environment() { + } + + private static boolean findIsWildFly() { + try { + return !Version.AS_VERSION.startsWith("7"); + } catch (Exception e) { + return false; + } + } + + public Module getSubsysModule() { + // Unfortunately, we can't cache this because unit tests will fail + try { + return Module.getModuleFromCallerModuleLoader(KEYCLOAK_SUBSYSTEM); + } catch (ModuleLoadException e) { + throw new IllegalStateException("Can't find Keycloak subsystem.", e); + } + } + + public static boolean isWildFly() { + return isWildFly; + } +} diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java index ea26666714..f96d1c2c99 100755 --- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java @@ -21,7 +21,6 @@ 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.Phase; import org.jboss.as.web.common.WarMetaData; import org.jboss.logging.Logger; import org.jboss.metadata.javaee.spec.ParamValueMetaData; @@ -31,10 +30,6 @@ import org.keycloak.subsystem.logging.KeycloakLogger; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import org.jboss.as.ee.component.EEModuleDescription; -import org.jboss.as.server.deployment.Attachments; -import org.jboss.as.server.deployment.MountedDeploymentOverlay; /** * Pass authentication data (keycloak.json) as a servlet context param so it can be read by the KeycloakServletExtension. @@ -49,10 +44,6 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP // two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration. public static final String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig"; - public static final Phase PHASE = Phase.POST_MODULE; - // This needs to run just before bean validator factory - public static final int PRIORITY = Phase.POST_MODULE_VALIDATOR_FACTORY - 1; - // not sure if we need this yet, keeping here just in case protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) { String deploymentName = deploymentUnit.getName(); @@ -83,12 +74,6 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP addKeycloakAuthData(phaseContext, deploymentName, service); } - if (service.isKeycloakServerDeployment(deploymentName)) { - final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION); - String webContext = service.getWebContext(deploymentName); - if (webContext == null) throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Auth Server"); - description.setModuleName(webContext); - } // FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK // todo notsure if we need this diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java new file mode 100644 index 0000000000..d5c05f086e --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java @@ -0,0 +1,132 @@ +/* + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.extension; + +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.deployment.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.jboss.ValveMetaData; +import org.jboss.metadata.web.spec.LoginConfigMetaData; +import org.keycloak.adapters.as7.KeycloakAuthenticatorValve; +import org.keycloak.subsystem.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. + * This is used for AS7/EAP6. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ + +// Note: Even though this class closely resembles the WildFly KeycloakAdapterConfigDeploymentProcessor +// it can not be easily refactored because the WarMetaData classes are of different types. +public class KeycloakAdapterConfigDeploymentProcessorAS7 implements DeploymentUnitProcessor { + protected Logger log = Logger.getLogger(KeycloakAdapterConfigDeploymentProcessorAS7.class); + + @Override + public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException { + DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); + String deploymentName = deploymentUnit.getName(); + + KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry()); + //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName); + if (service.isSecureDeployment(deploymentName)) { + addKeycloakAuthData(phaseContext, deploymentName, service); + return; + } + + // else check to see if KEYCLOAK is specified as login config + 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 && "KEYCLOAK".equalsIgnoreCase(loginConfig.getAuthMethod())) { + addValve(webMetaData); + } + } + + private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, String deploymentName, KeycloakAdapterConfigService service) { + DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); + WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY); + + addJSONData(service.getJSON(deploymentName), warMetaData); + JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData(); + if (webMetaData == null) { + webMetaData = new JBossWebMetaData(); + warMetaData.setMergedJBossWebMetaData(webMetaData); + } + addValve(webMetaData); + + LoginConfigMetaData loginConfig = webMetaData.getLoginConfig(); + if (loginConfig == null) { + loginConfig = new LoginConfigMetaData(); + webMetaData.setLoginConfig(loginConfig); + } + loginConfig.setAuthMethod("KEYCLOAK"); + loginConfig.setRealmName(service.getRealmName(deploymentName)); + KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentName); + } + + private void addValve(JBossWebMetaData webMetaData) { + List valves = webMetaData.getValves(); + if (valves == null) { + valves = new ArrayList(1); + webMetaData.setValves(valves); + } + ValveMetaData valve = new ValveMetaData(); + valve.setValveClass(KeycloakAuthenticatorValve.class.getName()); + valve.setModule("org.keycloak.keycloak-as7-adapter"); + //log.info("******* adding Keycloak valve to: " + deploymentName); + valves.add(valve); + } + + private void addJSONData(String json, WarMetaData warMetaData) { + JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData(); + if (webMetaData == null) { + webMetaData = new JBossWebMetaData(); + warMetaData.setMergedJBossWebMetaData(webMetaData); + } + + List contextParams = webMetaData.getContextParams(); + if (contextParams == null) { + contextParams = new ArrayList(); + } + + ParamValueMetaData param = new ParamValueMetaData(); + param.setParamName(KeycloakAdapterConfigDeploymentProcessor.AUTH_DATA_PARAM_NAME); + param.setParamValue(json); + contextParams.add(param); + + webMetaData.setContextParams(contextParams); + } + + @Override + public void undeploy(DeploymentUnit du) { + + } + +} diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java index 868f5858d0..d860cb65c4 100755 --- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java @@ -224,7 +224,7 @@ public final class KeycloakAdapterConfigService implements Service container = registry.getService(KeycloakAdapterConfigService.SERVICE_NAME); if (container != null) { KeycloakAdapterConfigService service = (KeycloakAdapterConfigService)container.getValue(); @@ -233,7 +233,7 @@ public final class KeycloakAdapterConfigService implements Service> newControllers) throws OperationFailedException { super.performRuntime(context, operation, model, verificationHandler, newControllers); diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java index 25b632a85a..117af14128 100644 --- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java @@ -56,23 +56,13 @@ public class AuthServerUtil { private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-subsystem"); - private final String authServerName; - private final PathAddress pathAddress; private final String deploymentName; - - //private String overlayName; private final Module subsysModule; private final String keycloakVersion; private final boolean isAuthServerExploded; - - //private File overlaysDir; private final URI authServerUri; - //private URL serverConfig = null; - //private Set spiUrls = new HashSet(); AuthServerUtil(ModelNode operation) { - this.authServerName = getAuthServerName(operation); - this.pathAddress = getPathAddress(operation); this.deploymentName = getDeploymentName(operation); this.subsysModule = findSubsysModule(); this.keycloakVersion = subsysModule.getProperty("keycloak-version"); diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java new file mode 100644 index 0000000000..dd66a01127 --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java @@ -0,0 +1,54 @@ +/* + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.extension.authserver; + +import org.jboss.as.ee.component.EEModuleDescription; +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.keycloak.subsystem.extension.KeycloakAdapterConfigService; + +/** + * DUP responsible for setting the web context of a Keycloak auth server. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ +public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcessor { + + @Override + public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException { + DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); + String deploymentName = deploymentUnit.getName(); + KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry()); + if (!service.isKeycloakServerDeployment(deploymentName)) { + return; + } + + final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION); + String webContext = service.getWebContext(deploymentName); + if (webContext == null) { + throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Auth Server"); + } + description.setModuleName(webContext); + } + + @Override + public void undeploy(DeploymentUnit du) { + + } +} diff --git a/pom.xml b/pom.xml index ba351f100e..036db3f1c7 100755 --- a/pom.xml +++ b/pom.xml @@ -482,6 +482,11 @@ zip ${wildfly.core.version} + + org.wildfly.core + wildfly-version + ${wildfly.core.version} + org.wildfly wildfly-undertow