From 4776582a6a247cc5b026006c19e99f155f1cec10 Mon Sep 17 00:00:00 2001 From: Stan Silvert Date: Wed, 1 Oct 2014 13:55:39 -0400 Subject: [PATCH] Old experiment with keycloak-server.json embedded into standalone.xml --- .gitignore | 3 +- .../main/module.xml | 1 + integration/wildfly-subsystem/pom.xml | 29 ++- ...cloakAdapterConfigDeploymentProcessor.java | 17 +- .../KeycloakAdapterConfigService.java | 33 +++- .../KeycloakDependencyProcessor.java | 40 ++++- .../extension/KeycloakExtension.java | 7 +- .../extension/KeycloakStructureProcessor.java | 80 +++++++++ .../extension/KeycloakSubsystemAdd.java | 15 +- .../extension/KeycloakSubsystemParser.java | 38 ++++ .../authserver/AuthServerAddHandler.java | 88 +++++++++ .../authserver/AuthServerDefinition.java | 134 ++++++++++++++ .../authserver/AuthServerRemoveHandler.java | 54 ++++++ .../extension/authserver/AuthServerUtil.java | 168 ++++++++++++++++++ .../AuthServerWriteAttributeHandler.java | 41 +++++ .../extension/LocalDescriptions.properties | 9 + pom.xml | 5 + .../resources/KeycloakApplication.java | 23 ++- 18 files changed, 768 insertions(+), 17 deletions(-) create mode 100755 integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakStructureProcessor.java create mode 100755 integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java create mode 100755 integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java create mode 100644 integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java create mode 100644 integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java create mode 100755 integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java diff --git a/.gitignore b/.gitignore index 319769bf2a3..44612eb8b4a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,10 +9,11 @@ .settings .classpath - # NetBeans # ############ +nbactions.xml nb-configuration.xml +catalog.xml # Compiled source # ################### 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 0bc0ec9f78a..22d6beacb8f 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 @@ -31,6 +31,7 @@ + diff --git a/integration/wildfly-subsystem/pom.xml b/integration/wildfly-subsystem/pom.xml index d776e6006a9..52475151c9d 100755 --- a/integration/wildfly-subsystem/pom.xml +++ b/integration/wildfly-subsystem/pom.xml @@ -42,11 +42,9 @@ org.apache.maven.plugins maven-surefire-plugin - 2.8.1 false true - -Xmx512m jboss.home @@ -56,9 +54,34 @@ **/*TestCase.java - once + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + compile + + copy + + + + + org.keycloak + keycloak-server + ${project.version} + war + true + ${project.build.directory}/classes/deployments + auth-server.war + + + + + + 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 55e47eba7fd..cc5b73c5da4 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 @@ -31,6 +31,7 @@ import org.keycloak.subsystem.logging.KeycloakLogger; import java.util.ArrayList; import java.util.List; +import org.jboss.as.ee.component.EEModuleDescription; /** * Pass authentication data (keycloak.json) as a servlet context param so it can be read by the KeycloakServletExtension. @@ -45,9 +46,9 @@ 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.INSTALL; - // Seems wise to have this run after INSTALL_WAR_DEPLOYMENT - public static final int PRIORITY = Phase.INSTALL_WAR_DEPLOYMENT - 1; + 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) { @@ -73,6 +74,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); String deploymentName = deploymentUnit.getName(); + System.out.println(">>>>> deploymentName=" + deploymentName); KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry()); //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName); if (service.isKeycloakDeployment(deploymentName)) { @@ -99,6 +101,15 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP webMetaData = new JBossWebMetaData(); warMetaData.setMergedJBossWebMetaData(webMetaData); } + + 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); + return; + } + LoginConfigMetaData loginConfig = webMetaData.getLoginConfig(); if (loginConfig == null) { loginConfig = new LoginConfigMetaData(); 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 eb820fcff85..ee91ef3152b 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 @@ -53,6 +53,11 @@ public final class KeycloakAdapterConfigService implements Service realms = new HashMap(); private Map deployments = new HashMap(); + // key=server deployment name; value=json + private Map serverDeployments = new HashMap(); + // key=server deployment name; value=web-context + private Map webContexts = new HashMap(); + private KeycloakAdapterConfigService() { } @@ -72,6 +77,24 @@ public final class KeycloakAdapterConfigService implements Service list) throws XMLStreamException { + String authServerName = readNameAttribute(reader); + ModelNode addAuthServer = new ModelNode(); + addAuthServer.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD); + PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME), + PathElement.pathElement(AuthServerDefinition.TAG_NAME, authServerName)); + addAuthServer.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode()); + + while (reader.hasNext() && nextTag(reader) != END_ELEMENT) { + String tagName = reader.getLocalName(); + SimpleAttributeDefinition def = AuthServerDefinition.lookup(tagName); + if (def == null) throw new XMLStreamException("Unknown auth-server tag " + tagName); + def.parseAndSetParameter(reader.getElementText(), addAuthServer, reader); + } + + list.add(addAuthServer); + } + private void readRealm(XMLExtendedStreamReader reader, List list) throws XMLStreamException { String realmName = readNameAttribute(reader); ModelNode addRealm = new ModelNode(); @@ -157,11 +178,28 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader
  • > newControllers) throws OperationFailedException { + } +} diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java new file mode 100755 index 00000000000..685a9103552 --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java @@ -0,0 +1,134 @@ +/* + * 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.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.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; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.operations.validation.ParameterValidator; +import org.jboss.as.controller.registry.OperationEntry; +import org.keycloak.subsystem.extension.KeycloakAdapterConfigService; +import org.keycloak.subsystem.extension.KeycloakExtension; + +/** + * Defines attributes and operations for an Auth Server + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ +public class AuthServerDefinition extends SimpleResourceDefinition { + + public static final String TAG_NAME = "auth-server"; + + protected static final SimpleAttributeDefinition ENABLED = + new SimpleAttributeDefinitionBuilder("enabled", ModelType.BOOLEAN, true) + .setXmlName("enabled") + .setAllowExpression(true) + .setDefaultValue(new ModelNode(true)) + .setRestartAllServices() + .build(); + + protected static final SimpleAttributeDefinition WEB_CONTEXT = + new SimpleAttributeDefinitionBuilder("web-context", ModelType.STRING, true) + .setXmlName("web-context") + .setAllowExpression(true) + .setDefaultValue(new ModelNode("auth")) + .setValidator(new WebContextValidator()) + .setRestartAllServices() + .build(); + + /* protected static final SimpleAttributeDefinition KEYCLOAK_SERVER_JSON = + new SimpleAttributeDefinitionBuilder("keycloak-server-json", ModelType.STRING, true) + .setXmlName("keycloak-server-json") + .setAllowExpression(true) + .setRestartAllServices() + .build(); */ + + public static final List ALL_ATTRIBUTES = new ArrayList(); + static { + ALL_ATTRIBUTES.add(ENABLED); + ALL_ATTRIBUTES.add(WEB_CONTEXT); + //ALL_ATTRIBUTES.add(KEYCLOAK_SERVER_JSON); + } + + private static final Map DEFINITION_LOOKUP = new HashMap(); + static { + for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) { + DEFINITION_LOOKUP.put(def.getXmlName(), def); + } + } + + private static AuthServerWriteAttributeHandler attrHandler = new AuthServerWriteAttributeHandler(ALL_ATTRIBUTES); + + public AuthServerDefinition() { + super(PathElement.pathElement(TAG_NAME), + KeycloakExtension.getResourceDescriptionResolver(TAG_NAME), + AuthServerAddHandler.INSTANCE, + AuthServerRemoveHandler.INSTANCE, + null, + OperationEntry.Flag.RESTART_ALL_SERVICES); + } + + @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) { + resourceRegistration.registerReadWriteAttribute(attrDef, null, attrHandler); + } + } + + public static SimpleAttributeDefinition lookup(String name) { + return DEFINITION_LOOKUP.get(name); + } + + private static class WebContextValidator implements ParameterValidator { + + @Override + public void validateParameter(String paramName, ModelNode value) throws OperationFailedException { + String strValue = value.asString(); + if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) { + throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments."); + } + } + + @Override + public void validateResolvedParameter(String paramName, ModelNode value) throws OperationFailedException { + String strValue = value.asString(); + if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) { + throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments."); + } + } + + } +} diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java new file mode 100644 index 00000000000..7f92ab2ae8b --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.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.controller.AbstractRemoveStepHandler; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.dmr.ModelNode; +import org.keycloak.subsystem.extension.KeycloakAdapterConfigService; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS; + +/** + * Remove an auth-server from a realm. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ +public final class AuthServerRemoveHandler extends AbstractRemoveStepHandler { + + public static AuthServerRemoveHandler INSTANCE = new AuthServerRemoveHandler(); + + private AuthServerRemoveHandler() {} + + @Override + protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { + //KeycloakAdapterConfigService.INSTANCE.removeAuthServer() + System.out.println("*** performRuntime ** operation"); + System.out.println(operation.toString()); + System.out.println("*** performRuntime ** model"); + System.out.println(model.toString()); + String deploymentName = Util.getNameFromAddress(operation.get(ADDRESS)); + System.out.println("*** authServerName=" + deploymentName); + if (!deploymentName.toLowerCase().endsWith(".war")) { + deploymentName += ".war"; + } + KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName); + } +} 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 new file mode 100644 index 00000000000..a7a4fd798d1 --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java @@ -0,0 +1,168 @@ +/* + * 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 java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.OperationStepHandler; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.PathElement; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PERSISTENT; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration; +import org.jboss.dmr.ModelNode; +import org.jboss.modules.Module; +import org.jboss.modules.ModuleIdentifier; +import org.jboss.modules.ModuleLoadException; +import org.jboss.modules.Resource; +import org.jboss.modules.filter.PathFilter; + +/** + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ +public class AuthServerUtil { + + private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-subsystem"); + + private static URL authServerUrl = null; + + private static String defaultAuthServerJson = ""; + + static String getDefaultAuthServerJson() { + if (authServerUrl == null) getWarUrl(); + return defaultAuthServerJson; + } + + // Can return the URL, null, or throw IllegalStateException + // This also finds the defaultAuthServerJson and sets the instance var for it. + private static URL getWarUrl() throws IllegalStateException { + if (authServerUrl != null) { // only need to find this once + return authServerUrl; + } + + Module module; + try { + module = Module.getModuleFromCallerModuleLoader(KEYCLOAK_AUTH_SERVER); + } catch (ModuleLoadException e) { + throw new IllegalStateException("Keycloak Auth Server not installed as a module.", e); + } + + URL warUrl = null; + try { + java.util.Iterator rscIterator = module.iterateResources(new PathFilter() { + @Override + public boolean accept(String string) { + return true; + } + }); + + // There should be only one war resource, the auth server + while (rscIterator.hasNext()) { + Resource rsc = rscIterator.next(); + System.out.println("rsc.getName()=" + rsc.getName()); + URL url = rsc.getURL(); + if (url.toExternalForm().toLowerCase().endsWith(".war")) { + warUrl = url; + setDefaultAuthServerJson(rsc); + break; + } + } + } catch (ModuleLoadException e) { + throw new IllegalStateException(e); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + authServerUrl = warUrl; + System.out.println("&&&&& authServerUrl=" + authServerUrl); + return authServerUrl; + } + + // return deploymentName this will be started under + static String addStepToStartAuthServer(OperationContext context, ModelNode operation) throws OperationFailedException { + + PathAddress authServerAddr = PathAddress.pathAddress(operation.get(ADDRESS)); + String deploymentName = authServerAddr.getElement(1).getValue(); + if (!deploymentName.toLowerCase().endsWith(".war")) { + deploymentName += ".war"; + } + + PathAddress deploymentAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName)); + ModelNode op = Util.createOperation(ADD, deploymentAddress); + op.get(ENABLED).set(true); + op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml + + URL warUrl = null; + try { + warUrl = getWarUrl(); + } catch (IllegalStateException e) { + throw new OperationFailedException(e); + } + + if (warUrl == null) { + throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-auth-server module"); + } + + String urlString = warUrl.toExternalForm(); + System.out.println(warUrl); + ModelNode contentItem = new ModelNode(); + contentItem.get(URL).set(urlString); + op.get(CONTENT).add(contentItem); + System.out.println("****** operation ************"); + System.out.println(op.toString()); + ImmutableManagementResourceRegistration rootResourceRegistration = context.getRootResourceRegistration(); + OperationStepHandler handler = rootResourceRegistration.getOperationHandler(deploymentAddress, ADD); + context.addStep(op, handler, OperationContext.Stage.MODEL); + + return deploymentName; + } + + private static void setDefaultAuthServerJson(Resource rsc) throws IOException { + JarInputStream jarStream = null; + try { + jarStream = new JarInputStream(rsc.openStream()); + JarEntry je; + while ((je = jarStream.getNextJarEntry()) != null) { + if (!je.getName().equals("WEB-INF/classes/META-INF/keycloak-server.json")) continue; + + int len = 0; + byte[] buffer = new byte[1024]; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + while ((len = jarStream.read(buffer)) != -1) { + baos.write(buffer, 0, len); + } + + defaultAuthServerJson = baos.toString(); + return; + } + } finally { + jarStream.close(); + } + } +} diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java new file mode 100755 index 00000000000..b7e53ea7534 --- /dev/null +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java @@ -0,0 +1,41 @@ +/* + * 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.controller.AttributeDefinition; +import org.jboss.as.controller.SimpleAttributeDefinition; + +import java.util.List; +import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler; + +/** + * Update an attribute on an Auth Server. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc. + */ +public class AuthServerWriteAttributeHandler extends ReloadRequiredWriteAttributeHandler { + + public AuthServerWriteAttributeHandler(List definitions) { + this(definitions.toArray(new AttributeDefinition[definitions.size()])); + } + + public AuthServerWriteAttributeHandler(AttributeDefinition... definitions) { + super(definitions); + } + +} diff --git a/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties b/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties index 524ae4d60c7..533234b85d4 100755 --- a/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties +++ b/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties @@ -1,9 +1,18 @@ keycloak.subsystem=Keycloak subsystem keycloak.subsystem.add=Operation Adds Keycloak subsystem keycloak.subsystem.remove=Operation removes Keycloak subsystem +keycloak.subsystem.auth-server=Keycloak Auth Server keycloak.subsystem.realm=A Keycloak realm. keycloak.subsystem.secure-deployment=A deployment secured by Keycloak. + +keycloak.auth-server=A Keycloak Auth Server +keycloak.auth-server.add=Add an Auth Server to the subsystem. +keycloak.auth-server.remove=Remove an Auth Server from the subsystem. +keycloak.auth-server.enabled=Enable or disable the Auth Server. +keycloak.auth-server.keycloak-server-json=Externalized version of keycloak-server.json +keycloak.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment. + keycloak.realm=A Keycloak realm. keycloak.realm.add=Add a realm definition to the subsystem. keycloak.realm.remove=Remove a realm from the subsystem. diff --git a/pom.xml b/pom.xml index f6164ff8280..80d627c49a0 100755 --- a/pom.xml +++ b/pom.xml @@ -485,6 +485,11 @@ + + org.apache.maven.plugins + maven-dependency-plugin + 2.8 + org.apache.maven.plugins maven-surefire-plugin diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java index a2d5a60d297..89e5d40d7c7 100755 --- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java +++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java @@ -41,6 +41,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; +import org.keycloak.adapters.AdapterConstants; /** * @author Bill Burke @@ -57,7 +58,7 @@ public class KeycloakApplication extends Application { protected String contextPath; public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) { - loadConfig(); + loadConfig(context); this.sessionFactory = createSessionFactory(); @@ -102,6 +103,26 @@ public class KeycloakApplication extends Application { return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build(); } + private static void loadConfig(ServletContext context) { + String json = context.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME); + if (json == null) { + loadConfig(); // from file + } else { + loadConfig(json); // from ServletContext/Keycloak subsystem + } + } + + private static void loadConfig(String json) { + try { + JsonNode node = new ObjectMapper().readTree(json); + Config.init(new JsonConfigProvider(node)); + } catch (IOException e) { + throw new RuntimeException("Failed to load config", e); + } + + log.info("Loaded config from Keycloak subsystem"); + } + public static void loadConfig() { try { URL config = null;