Merge pull request #1340 from mstruk/srv-subsystem
Cleanup, and simplify keycloak-server-subsystem
This commit is contained in:
commit
966d939c12
23 changed files with 185 additions and 927 deletions
|
@ -126,7 +126,7 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<type>war</type>
|
<type>war</type>
|
||||||
<overWrite>true</overWrite>
|
<overWrite>true</overWrite>
|
||||||
<outputDirectory>${project.build.directory}/${project.build.finalName}/modules/system/layers/base/org/keycloak/keycloak-server-subsystem/main/auth-server</outputDirectory>
|
<outputDirectory>${project.build.directory}/${project.build.finalName}/modules/system/layers/base/org/keycloak/keycloak-server-subsystem/main/server-war</outputDirectory>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
</artifactItems>
|
</artifactItems>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-server-subsystem">
|
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-server-subsystem">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="keycloak-version" value="${project.version}"/>
|
<property name="keycloak-version" value="${project.version}"/>
|
||||||
<property name="auth-server-exploded" value="false"/>
|
<property name="server-war-exploded" value="false"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
@ -14,14 +14,8 @@
|
||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.subsystem.server.extension;
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This service keeps track of the entire Keycloak management model so as to provide
|
* This service keeps track of the entire Keycloak management model so as to provide
|
||||||
* adapter configuration to each deployment at deploy time.
|
* adapter configuration to each deployment at deploy time.
|
||||||
|
@ -30,37 +24,25 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD
|
||||||
*/
|
*/
|
||||||
public final class KeycloakAdapterConfigService {
|
public final class KeycloakAdapterConfigService {
|
||||||
|
|
||||||
private static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
|
static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
|
||||||
|
|
||||||
public static KeycloakAdapterConfigService getInstance() {
|
static final String DEPLOYMENT_NAME = "keycloak-server";
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// key=auth-server deployment name; value=web-context
|
|
||||||
private final Map<String, String> webContexts = new HashMap<String, String>();
|
|
||||||
|
|
||||||
|
private String webContext;
|
||||||
|
|
||||||
|
|
||||||
private KeycloakAdapterConfigService() {
|
private KeycloakAdapterConfigService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addServerDeployment(String deploymentName, String webContext) {
|
void setWebContext(String webContext) {
|
||||||
this.webContexts.put(deploymentName, webContext);
|
this.webContext = webContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWebContext(String deploymentName) {
|
String getWebContext() {
|
||||||
return webContexts.get(deploymentName);
|
return webContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeServerDeployment(String deploymentName) {
|
boolean isKeycloakServerDeployment(String deploymentName) {
|
||||||
this.webContexts.remove(deploymentName);
|
return DEPLOYMENT_NAME.equals(deploymentName);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWebContextUsed(String webContext) {
|
|
||||||
return webContexts.containsValue(webContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isKeycloakServerDeployment(String deploymentName) {
|
|
||||||
return this.webContexts.containsKey(deploymentName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,9 @@ import org.jboss.as.controller.ResourceDefinition;
|
||||||
import org.jboss.as.controller.SubsystemRegistration;
|
import org.jboss.as.controller.SubsystemRegistration;
|
||||||
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
|
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
|
||||||
import org.jboss.as.controller.parsing.ExtensionParsingContext;
|
import org.jboss.as.controller.parsing.ExtensionParsingContext;
|
||||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
|
||||||
import org.keycloak.subsystem.server.extension.authserver.AuthServerDefinition;
|
|
||||||
import org.keycloak.subsystem.server.logging.KeycloakLogger;
|
|
||||||
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
|
||||||
|
import static org.keycloak.subsystem.server.logging.KeycloakLogger.ROOT_LOGGER;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,17 +36,16 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
|
||||||
*/
|
*/
|
||||||
public class KeycloakExtension implements Extension {
|
public class KeycloakExtension implements Extension {
|
||||||
|
|
||||||
public static final String SUBSYSTEM_NAME = "keycloak-server";
|
static final String SUBSYSTEM_NAME = "keycloak-server";
|
||||||
public static final String NAMESPACE = "urn:jboss:domain:keycloak-server:1.1";
|
static final String NAMESPACE = "urn:jboss:domain:keycloak-server:1.1";
|
||||||
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
|
|
||||||
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
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 AuthServerDefinition AUTH_SERVER_DEFINITION = new AuthServerDefinition();
|
|
||||||
|
|
||||||
public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
private static final String RESOURCE_NAME = KeycloakExtension.class.getPackage().getName() + ".LocalDescriptions";
|
||||||
|
private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
|
||||||
|
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
|
||||||
|
private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1,1,0);
|
||||||
|
|
||||||
|
static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||||
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
||||||
for (String kp : keyPrefix) {
|
for (String kp : keyPrefix) {
|
||||||
prefix.append('.').append(kp);
|
prefix.append('.').append(kp);
|
||||||
|
@ -61,7 +58,7 @@ public class KeycloakExtension implements Extension {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initializeParsers(final ExtensionParsingContext context) {
|
public void initializeParsers(final ExtensionParsingContext context) {
|
||||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakExtension.NAMESPACE, PARSER);
|
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, NAMESPACE, PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,11 +66,10 @@ public class KeycloakExtension implements Extension {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize(final ExtensionContext context) {
|
public void initialize(final ExtensionContext context) {
|
||||||
KeycloakLogger.ROOT_LOGGER.debug("Activating Keycloak Extension");
|
ROOT_LOGGER.debug("Activating Keycloak Extension");
|
||||||
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, MGMT_API_VERSION);
|
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, MGMT_API_VERSION);
|
||||||
|
|
||||||
ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
||||||
registration.registerSubModel(AUTH_SERVER_DEFINITION);
|
|
||||||
subsystem.registerXMLElementWriter(PARSER);
|
subsystem.registerXMLElementWriter(PARSER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,13 @@
|
||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.server.extension.authserver;
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
import org.jboss.as.ee.component.EEModuleDescription;
|
import org.jboss.as.ee.component.EEModuleDescription;
|
||||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DUP responsible for setting the web context of a Keycloak auth server.
|
* DUP responsible for setting the web context of a Keycloak auth server.
|
||||||
|
@ -33,22 +32,22 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso
|
||||||
@Override
|
@Override
|
||||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||||
|
KeycloakAdapterConfigService config = KeycloakAdapterConfigService.INSTANCE;
|
||||||
String deploymentName = deploymentUnit.getName();
|
String deploymentName = deploymentUnit.getName();
|
||||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
|
||||||
if (!service.isKeycloakServerDeployment(deploymentName)) {
|
if (!config.isKeycloakServerDeployment(deploymentName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
|
final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
|
||||||
String webContext = service.getWebContext(deploymentName);
|
String webContext = config.getWebContext();
|
||||||
if (webContext == null) {
|
if (webContext == null) {
|
||||||
throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Auth Server");
|
throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Server");
|
||||||
}
|
}
|
||||||
description.setModuleName(webContext);
|
description.setModuleName(webContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undeploy(DeploymentUnit du) {
|
public void undeploy(DeploymentUnit du) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,13 +17,18 @@
|
||||||
package org.keycloak.subsystem.server.extension;
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
|
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
|
||||||
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
import org.jboss.as.controller.OperationContext;
|
import org.jboss.as.controller.OperationContext;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.registry.Resource;
|
||||||
import org.jboss.as.server.AbstractDeploymentChainStep;
|
import org.jboss.as.server.AbstractDeploymentChainStep;
|
||||||
import org.jboss.as.server.DeploymentProcessorTarget;
|
import org.jboss.as.server.DeploymentProcessorTarget;
|
||||||
import org.jboss.as.server.deployment.Phase;
|
import org.jboss.as.server.deployment.Phase;
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
|
|
||||||
import org.keycloak.subsystem.server.extension.authserver.KeycloakServerDeploymentProcessor;
|
import static org.keycloak.subsystem.server.extension.KeycloakExtension.SUBSYSTEM_NAME;
|
||||||
|
import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.ALL_ATTRIBUTES;
|
||||||
|
import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.WEB_CONTEXT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Keycloak subsystem add update handler.
|
* The Keycloak subsystem add update handler.
|
||||||
|
@ -35,15 +40,44 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
|
||||||
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
|
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void performBoottime(final OperationContext context, ModelNode operation, final ModelNode model) {
|
protected void performBoottime(final OperationContext context, final ModelNode operation, final ModelNode model) {
|
||||||
context.addStep(new AbstractDeploymentChainStep() {
|
context.addStep(new AbstractDeploymentChainStep() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(DeploymentProcessorTarget processorTarget) {
|
protected void execute(DeploymentProcessorTarget processorTarget) {
|
||||||
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME,
|
processorTarget.addDeploymentProcessor(SUBSYSTEM_NAME,
|
||||||
Phase.POST_MODULE, // PHASE
|
Phase.POST_MODULE, // PHASE
|
||||||
Phase.POST_MODULE_VALIDATOR_FACTORY - 1, // PRIORITY
|
Phase.POST_MODULE_VALIDATOR_FACTORY - 1, // PRIORITY
|
||||||
new KeycloakServerDeploymentProcessor());
|
new KeycloakServerDeploymentProcessor());
|
||||||
}
|
}
|
||||||
}, OperationContext.Stage.RUNTIME);
|
}, OperationContext.Stage.RUNTIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void populateModel(final OperationContext context, final ModelNode operation, final Resource resource) throws OperationFailedException {
|
||||||
|
ModelNode model = resource.getModel();
|
||||||
|
|
||||||
|
// set attribute values from parsed model
|
||||||
|
for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
|
||||||
|
attrDef.validateAndSet(operation, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns early if on domain controller
|
||||||
|
if (!requiresRuntime(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't want to try to start server on host controller
|
||||||
|
if (!context.isNormalServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode webContextNode = resource.getModel().get(WEB_CONTEXT.getName());
|
||||||
|
if (!webContextNode.isDefined()) {
|
||||||
|
webContextNode = WEB_CONTEXT.getDefaultValue();
|
||||||
|
}
|
||||||
|
String webContext = webContextNode.asString();
|
||||||
|
|
||||||
|
ServerUtil serverUtil = new ServerUtil(operation);
|
||||||
|
serverUtil.addStepToUploadServerWar(context);
|
||||||
|
KeycloakAdapterConfigService.INSTANCE.setWebContext(webContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,25 +14,56 @@
|
||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.subsystem.server.extension;
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||||
import org.jboss.as.controller.SimpleResourceDefinition;
|
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||||
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition of subsystem=keycloak.
|
* Definition of subsystem=keycloak-server.
|
||||||
*
|
*
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||||
*/
|
*/
|
||||||
public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
|
public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
|
||||||
|
|
||||||
|
static final SimpleAttributeDefinition WEB_CONTEXT =
|
||||||
|
new SimpleAttributeDefinitionBuilder("web-context", ModelType.STRING, true)
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode("auth"))
|
||||||
|
.setRestartAllServices()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ALL_ATTRIBUTES.add(WEB_CONTEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 KeycloakSubsystemWriteAttributeHandler attrHandler = new KeycloakSubsystemWriteAttributeHandler(ALL_ATTRIBUTES);
|
||||||
|
|
||||||
protected KeycloakSubsystemDefinition() {
|
protected KeycloakSubsystemDefinition() {
|
||||||
super(KeycloakExtension.SUBSYSTEM_PATH,
|
super(KeycloakExtension.PATH_SUBSYSTEM,
|
||||||
KeycloakExtension.getResourceDescriptionResolver("subsystem"),
|
KeycloakExtension.getResourceDescriptionResolver("subsystem"),
|
||||||
KeycloakSubsystemAdd.INSTANCE,
|
KeycloakSubsystemAdd.INSTANCE,
|
||||||
ReloadRequiredRemoveStepHandler.INSTANCE
|
KeycloakSubsystemRemoveHandler.INSTANCE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,4 +73,15 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
|
||||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.server.extension;
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
import org.keycloak.subsystem.server.extension.authserver.AuthServerDefinition;
|
|
||||||
import org.jboss.as.controller.AttributeDefinition;
|
|
||||||
import org.jboss.as.controller.PathAddress;
|
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.operations.common.Util;
|
||||||
import org.jboss.as.controller.parsing.ParseUtils;
|
import org.jboss.as.controller.parsing.ParseUtils;
|
||||||
import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
|
import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
import org.jboss.dmr.Property;
|
|
||||||
import org.jboss.staxmapper.XMLElementReader;
|
import org.jboss.staxmapper.XMLElementReader;
|
||||||
import org.jboss.staxmapper.XMLElementWriter;
|
import org.jboss.staxmapper.XMLElementWriter;
|
||||||
import org.jboss.staxmapper.XMLExtendedStreamReader;
|
import org.jboss.staxmapper.XMLExtendedStreamReader;
|
||||||
|
@ -34,9 +28,11 @@ import org.jboss.staxmapper.XMLExtendedStreamWriter;
|
||||||
|
|
||||||
import javax.xml.stream.XMLStreamConstants;
|
import javax.xml.stream.XMLStreamConstants;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.keycloak.subsystem.server.extension.KeycloakExtension.PATH_SUBSYSTEM;
|
||||||
|
import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.WEB_CONTEXT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The subsystem parser, which uses stax to read and write to and from xml
|
* The subsystem parser, which uses stax to read and write to and from xml
|
||||||
*/
|
*/
|
||||||
|
@ -49,12 +45,14 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
||||||
public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException {
|
public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException {
|
||||||
// Require no attributes
|
// Require no attributes
|
||||||
ParseUtils.requireNoAttributes(reader);
|
ParseUtils.requireNoAttributes(reader);
|
||||||
ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(KeycloakExtension.PATH_SUBSYSTEM));
|
ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(PATH_SUBSYSTEM));
|
||||||
list.add(addKeycloakSub);
|
list.add(addKeycloakSub);
|
||||||
|
|
||||||
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
||||||
if (reader.getLocalName().equals(AuthServerDefinition.TAG_NAME)) {
|
if (reader.getLocalName().equals(WEB_CONTEXT.getXmlName())) {
|
||||||
readAuthServer(reader, list);
|
WEB_CONTEXT.parseAndSetParameter(reader.getElementText(), addKeycloakSub, reader);
|
||||||
|
} else {
|
||||||
|
throw new XMLStreamException("Unknown keycloak-server subsystem tag: " + reader.getLocalName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,64 +62,21 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
||||||
return reader.nextTag();
|
return reader.nextTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readAuthServer(XMLExtendedStreamReader reader, List<ModelNode> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
|
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
|
||||||
context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
|
context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
|
||||||
writeAuthServers(writer, context);
|
writeWebContext(writer, context);
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAuthServers(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
private void writeWebContext(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||||
if (!context.getModelNode().get(AuthServerDefinition.TAG_NAME).isDefined()) {
|
if (!context.getModelNode().get(WEB_CONTEXT.getName()).isDefined()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (Property authServer : context.getModelNode().get(AuthServerDefinition.TAG_NAME).asPropertyList()) {
|
|
||||||
writer.writeStartElement(AuthServerDefinition.TAG_NAME);
|
|
||||||
writer.writeAttribute("name", authServer.getName());
|
|
||||||
ModelNode authServerElements = authServer.getValue();
|
|
||||||
for (AttributeDefinition element : AuthServerDefinition.ALL_ATTRIBUTES) {
|
|
||||||
element.marshallAsElement(authServerElements, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.writeEndElement();
|
WEB_CONTEXT.marshallAsElement(context.getModelNode(), writer);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,16 @@
|
||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
package org.keycloak.subsystem.server.extension.authserver;
|
|
||||||
|
|
||||||
import org.jboss.as.controller.AbstractRemoveStepHandler;
|
|
||||||
import org.jboss.as.controller.OperationContext;
|
import org.jboss.as.controller.OperationContext;
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
import org.jboss.as.controller.OperationStepHandler;
|
import org.jboss.as.controller.OperationStepHandler;
|
||||||
import org.jboss.as.controller.PathAddress;
|
import org.jboss.as.controller.PathAddress;
|
||||||
import org.jboss.as.controller.PathElement;
|
import org.jboss.as.controller.PathElement;
|
||||||
|
import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
|
||||||
import org.jboss.as.controller.operations.common.Util;
|
import org.jboss.as.controller.operations.common.Util;
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
|
||||||
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
|
||||||
|
@ -36,25 +34,25 @@ import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
||||||
*
|
*
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
*/
|
*/
|
||||||
public final class AuthServerRemoveHandler extends AbstractRemoveStepHandler {
|
public final class KeycloakSubsystemRemoveHandler extends ReloadRequiredRemoveStepHandler {
|
||||||
|
|
||||||
public static AuthServerRemoveHandler INSTANCE = new AuthServerRemoveHandler();
|
static KeycloakSubsystemRemoveHandler INSTANCE = new KeycloakSubsystemRemoveHandler();
|
||||||
|
|
||||||
private AuthServerRemoveHandler() {}
|
private KeycloakSubsystemRemoveHandler() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void performRemove(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
protected void performRemove(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
String deploymentName = ServerUtil.getDeploymentName(operation);
|
||||||
KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
|
KeycloakAdapterConfigService.INSTANCE.setWebContext(null);
|
||||||
|
|
||||||
if (requiresRuntime(context)) { // don't do this on a domain controller
|
if (requiresRuntime(context)) { // don't do this on a domain controller
|
||||||
addStepToRemoveAuthServer(context, deploymentName);
|
addStepToRemoveServerWar(context, deploymentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.performRemove(context, operation, model);
|
super.performRemove(context, operation, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addStepToRemoveAuthServer(OperationContext context, String deploymentName) {
|
private void addStepToRemoveServerWar(OperationContext context, String deploymentName) {
|
||||||
PathAddress deploymentAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
|
PathAddress deploymentAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
|
||||||
ModelNode op = Util.createOperation(REMOVE, deploymentAddress);
|
ModelNode op = Util.createOperation(REMOVE, deploymentAddress);
|
||||||
context.addStep(op, getRemoveHandler(context, deploymentAddress), OperationContext.Stage.MODEL);
|
context.addStep(op, getRemoveHandler(context, deploymentAddress), OperationContext.Stage.MODEL);
|
|
@ -14,8 +14,7 @@
|
||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
package org.keycloak.subsystem.server.extension;
|
||||||
package org.keycloak.subsystem.server.extension.authserver;
|
|
||||||
|
|
||||||
import org.jboss.as.controller.AttributeDefinition;
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
|
@ -26,20 +25,19 @@ import org.jboss.as.controller.OperationContext;
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
import org.jboss.as.controller.registry.Resource;
|
import org.jboss.as.controller.registry.Resource;
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update an attribute on an Auth Server.
|
* Update an attribute on an Auth Server.
|
||||||
*
|
*
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
*/
|
*/
|
||||||
public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHandler { //extends ReloadRequiredWriteAttributeHandler {
|
public class KeycloakSubsystemWriteAttributeHandler extends ModelOnlyWriteAttributeHandler { //extends ReloadRequiredWriteAttributeHandler {
|
||||||
|
|
||||||
public AuthServerWriteAttributeHandler(List<SimpleAttributeDefinition> definitions) {
|
public KeycloakSubsystemWriteAttributeHandler(List<SimpleAttributeDefinition> definitions) {
|
||||||
this(definitions.toArray(new AttributeDefinition[definitions.size()]));
|
this(definitions.toArray(new AttributeDefinition[definitions.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthServerWriteAttributeHandler(AttributeDefinition... definitions) {
|
public KeycloakSubsystemWriteAttributeHandler(AttributeDefinition... definitions) {
|
||||||
super(definitions);
|
super(definitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,34 +48,24 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isEnabled = AuthServerDefinition.ENABLED.resolveModelAttribute(context, model.getModel()).asBoolean();
|
String deploymentName = ServerUtil.getDeploymentName(operation);
|
||||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
|
||||||
|
|
||||||
if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
|
if (attributeName.equals(KeycloakSubsystemDefinition.WEB_CONTEXT.getName())) {
|
||||||
|
KeycloakAdapterConfigService.INSTANCE.setWebContext(newValue.asString());
|
||||||
KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
|
ServerUtil.addStepToRedeployServerWar(context, deploymentName);
|
||||||
KeycloakAdapterConfigService.getInstance().addServerDeployment(deploymentName, newValue.asString());
|
|
||||||
if (isEnabled) {
|
|
||||||
AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributeName.equals(AuthServerDefinition.ENABLED.getName())) {
|
|
||||||
if (!isEnabled) { // we are disabling
|
|
||||||
AuthServerUtil.addStepToUndeployAuthServer(context, deploymentName);
|
|
||||||
} else { // we are enabling
|
|
||||||
AuthServerUtil.addStepToDeployAuthServer(context, deploymentName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.finishModelStage(context, operation, attributeName, newValue, oldValue, model);
|
super.finishModelStage(context, operation, attributeName, newValue, oldValue, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean attribNotChanging(String attributeName, ModelNode newValue, ModelNode oldValue) {
|
private boolean attribNotChanging(String attributeName, ModelNode newValue, ModelNode oldValue) {
|
||||||
SimpleAttributeDefinition attribDef = AuthServerDefinition.lookup(attributeName);
|
SimpleAttributeDefinition attribDef = KeycloakSubsystemDefinition.lookup(attributeName);
|
||||||
if (!oldValue.isDefined()) oldValue = attribDef.getDefaultValue();
|
if (!oldValue.isDefined()) {
|
||||||
if (!newValue.isDefined()) newValue = attribDef.getDefaultValue();
|
oldValue = attribDef.getDefaultValue();
|
||||||
|
}
|
||||||
|
if (!newValue.isDefined()) {
|
||||||
|
newValue = attribDef.getDefaultValue();
|
||||||
|
}
|
||||||
return newValue.equals(oldValue);
|
return newValue.equals(oldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.server.extension.authserver;
|
package org.keycloak.subsystem.server.extension;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -29,50 +29,42 @@ 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.ADDRESS;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARCHIVE;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARCHIVE;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOY;
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
|
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.PERSISTENT;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REDEPLOY;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REDEPLOY;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNTIME_NAME;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNTIME_NAME;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UNDEPLOY;
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
|
||||||
import org.jboss.as.controller.operations.common.Util;
|
import org.jboss.as.controller.operations.common.Util;
|
||||||
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
||||||
import org.jboss.as.controller.registry.Resource;
|
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
import org.jboss.modules.Module;
|
import org.jboss.modules.Module;
|
||||||
import org.jboss.modules.ModuleIdentifier;
|
import org.jboss.modules.ModuleIdentifier;
|
||||||
import org.jboss.modules.ModuleLoadException;
|
import org.jboss.modules.ModuleLoadException;
|
||||||
import org.keycloak.subsystem.server.extension.KeycloakExtension;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods that help assemble and start an auth server.
|
* Utility methods that help assemble and start an auth server.
|
||||||
*
|
*
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
*/
|
*/
|
||||||
public class AuthServerUtil {
|
public class ServerUtil {
|
||||||
|
|
||||||
private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-server-subsystem");
|
private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-server-subsystem");
|
||||||
|
|
||||||
private final String deploymentName;
|
private final String deploymentName;
|
||||||
private final Module subsysModule;
|
private final Module subsysModule;
|
||||||
private final String keycloakVersion;
|
private final String keycloakVersion;
|
||||||
private final boolean isAuthServerExploded;
|
private final boolean isServerWarExploded;
|
||||||
private final URI authServerUri;
|
private final URI serverWar;
|
||||||
|
|
||||||
AuthServerUtil(ModelNode operation) {
|
ServerUtil(ModelNode operation) {
|
||||||
this.deploymentName = getDeploymentName(operation);
|
this.deploymentName = getDeploymentName(operation);
|
||||||
this.subsysModule = findSubsysModule();
|
this.subsysModule = findSubsysModule();
|
||||||
this.keycloakVersion = subsysModule.getProperty("keycloak-version");
|
this.keycloakVersion = subsysModule.getProperty("keycloak-version");
|
||||||
this.isAuthServerExploded = Boolean.parseBoolean(subsysModule.getProperty("auth-server-exploded"));
|
this.isServerWarExploded = Boolean.parseBoolean(subsysModule.getProperty("server-war-exploded"));
|
||||||
this.authServerUri = findAuthServerUri();
|
this.serverWar = findServerWarUri();
|
||||||
}
|
|
||||||
|
|
||||||
String getDeploymentName() {
|
|
||||||
return this.deploymentName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Module findSubsysModule() {
|
private Module findSubsysModule() {
|
||||||
|
@ -83,15 +75,15 @@ public class AuthServerUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private URI findAuthServerUri() throws IllegalStateException {
|
private URI findServerWarUri() throws IllegalStateException {
|
||||||
try {
|
try {
|
||||||
URL subsysResource = this.subsysModule.getExportedResource("module.xml");
|
URL subsysResource = this.subsysModule.getExportedResource("module.xml");
|
||||||
File subsysDir = new File(subsysResource.toURI()).getParentFile();
|
File subsysDir = new File(subsysResource.toURI()).getParentFile();
|
||||||
File authServerDir = new File(subsysDir, "auth-server");
|
File serverWarDir = new File(subsysDir, "server-war");
|
||||||
if (this.isAuthServerExploded) {
|
if (this.isServerWarExploded) {
|
||||||
return authServerDir.toURI();
|
return serverWarDir.toURI();
|
||||||
} else {
|
} else {
|
||||||
return new File(authServerDir, "keycloak-server-" + keycloakVersion + ".war").toURI();
|
return new File(serverWarDir, "keycloak-server-" + keycloakVersion + ".war").toURI();
|
||||||
}
|
}
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
|
@ -100,17 +92,21 @@ public class AuthServerUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addStepToUploadAuthServer(OperationContext context, boolean isEnabled) throws OperationFailedException {
|
void addStepToUploadServerWar(OperationContext context) throws OperationFailedException {
|
||||||
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
||||||
ModelNode op = Util.createOperation(ADD, deploymentAddress);
|
ModelNode op = Util.createOperation(ADD, deploymentAddress);
|
||||||
op.get(ENABLED).set(isEnabled);
|
|
||||||
op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml
|
// this is required for deployment to take place
|
||||||
|
op.get(ENABLED).set(true);
|
||||||
|
|
||||||
|
// prevents writing this deployment out to standalone.xml
|
||||||
|
op.get(PERSISTENT).set(false);
|
||||||
|
|
||||||
// Owner attribute is valid starting with WidlFly 9. Ignored in WildFly 8
|
// Owner attribute is valid starting with WidlFly 9. Ignored in WildFly 8
|
||||||
op.get("owner").set(new ModelNode().add("subsystem", KeycloakExtension.SUBSYSTEM_NAME));
|
op.get("owner").set(new ModelNode().add("subsystem", KeycloakExtension.SUBSYSTEM_NAME));
|
||||||
|
|
||||||
if (authServerUri == null) {
|
if (serverWar == null) {
|
||||||
throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-server-subsystem module");
|
throw new OperationFailedException("Keycloak Server WAR not found in keycloak-server-subsystem module");
|
||||||
}
|
}
|
||||||
|
|
||||||
op.get(CONTENT).add(makeContentItem());
|
op.get(CONTENT).add(makeContentItem());
|
||||||
|
@ -121,32 +117,26 @@ public class AuthServerUtil {
|
||||||
private ModelNode makeContentItem() throws OperationFailedException {
|
private ModelNode makeContentItem() throws OperationFailedException {
|
||||||
ModelNode contentItem = new ModelNode();
|
ModelNode contentItem = new ModelNode();
|
||||||
|
|
||||||
if (this.isAuthServerExploded) {
|
if (this.isServerWarExploded) {
|
||||||
String urlString = new File(authServerUri).getAbsolutePath();
|
String urlString = new File(serverWar).getAbsolutePath();
|
||||||
contentItem.get(PATH).set(urlString);
|
contentItem.get(PATH).set(urlString);
|
||||||
contentItem.get(ARCHIVE).set(false);
|
contentItem.get(ARCHIVE).set(false);
|
||||||
} else {
|
} else {
|
||||||
String urlString = authServerUri.toString();
|
String urlString = serverWar.toString();
|
||||||
contentItem.get(URL).set(urlString);
|
contentItem.get(URL).set(urlString);
|
||||||
}
|
}
|
||||||
|
|
||||||
return contentItem;
|
return contentItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addStepToRedeployAuthServer(OperationContext context, String deploymentName) {
|
static void addStepToRedeployServerWar(OperationContext context, String deploymentName) {
|
||||||
addDeploymentAction(context, REDEPLOY, deploymentName);
|
addDeploymentAction(context, REDEPLOY, deploymentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addStepToUndeployAuthServer(OperationContext context, String deploymentName) {
|
|
||||||
addDeploymentAction(context, UNDEPLOY, deploymentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addStepToDeployAuthServer(OperationContext context, String deploymentName) {
|
|
||||||
addDeploymentAction(context, DEPLOY, deploymentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addDeploymentAction(OperationContext context, String operation, String deploymentName) {
|
private static void addDeploymentAction(OperationContext context, String operation, String deploymentName) {
|
||||||
if (!context.isNormalServer()) return;
|
if (!context.isNormalServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
||||||
ModelNode op = Util.createOperation(operation, deploymentAddress);
|
ModelNode op = Util.createOperation(operation, deploymentAddress);
|
||||||
op.get(RUNTIME_NAME).set(deploymentName);
|
op.get(RUNTIME_NAME).set(deploymentName);
|
||||||
|
@ -170,27 +160,4 @@ public class AuthServerUtil {
|
||||||
|
|
||||||
return deploymentName;
|
return deploymentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getAuthServerName(ModelNode operation) {
|
|
||||||
PathAddress pathAddr = getPathAddress(operation);
|
|
||||||
return pathAddr.getElement(pathAddr.size() - 1).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
static PathAddress getPathAddress(ModelNode operation) {
|
|
||||||
return PathAddress.pathAddress(operation.get(ADDRESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
static PathAddress getOverlayAddress(String overlayName) {
|
|
||||||
return PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT_OVERLAY, overlayName));
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getOverlayName(ModelNode operation) {
|
|
||||||
return AuthServerUtil.getAuthServerName(operation) + "-keycloak-overlay";
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isOverlayExists(OperationContext context, String overlayName, PathAddress address) {
|
|
||||||
Resource resource = context.readResourceFromRoot(address);
|
|
||||||
return resource.getChildrenNames(DEPLOYMENT_OVERLAY).contains(overlayName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,206 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.extension.authserver;
|
|
||||||
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jboss.as.controller.AbstractAddStepHandler;
|
|
||||||
import org.jboss.as.controller.OperationContext;
|
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
|
||||||
import org.jboss.as.controller.PathAddress;
|
|
||||||
import org.jboss.as.controller.ProcessType;
|
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
|
||||||
import org.jboss.as.controller.operations.common.Util;
|
|
||||||
import org.jboss.as.controller.registry.Resource;
|
|
||||||
import org.jboss.dmr.ModelNode;
|
|
||||||
import org.jboss.dmr.ModelType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for operations that create overlays for an auth server.
|
|
||||||
*
|
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractAddOverlayHandler extends AbstractAddStepHandler{
|
|
||||||
|
|
||||||
protected static final String UPLOADED_FILE_OP_NAME = "uploaded-file-name";
|
|
||||||
protected static final SimpleAttributeDefinition UPLOADED_FILE_NAME =new SimpleAttributeDefinitionBuilder(UPLOADED_FILE_OP_NAME, ModelType.STRING, false)
|
|
||||||
.setAllowExpression(false)
|
|
||||||
.setAllowNull(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
protected static final SimpleAttributeDefinition BYTES_TO_UPLOAD= new SimpleAttributeDefinitionBuilder("bytes-to-upload", ModelType.BYTES, false)
|
|
||||||
.setAllowExpression(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
static final SimpleAttributeDefinition REDEPLOY_SERVER =
|
|
||||||
new SimpleAttributeDefinitionBuilder("redeploy", ModelType.BOOLEAN, true)
|
|
||||||
.setAllowExpression(true)
|
|
||||||
.setDefaultValue(new ModelNode(false))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
protected static final SimpleAttributeDefinition OVERWRITE =
|
|
||||||
new SimpleAttributeDefinitionBuilder("overwrite", ModelType.BOOLEAN, true)
|
|
||||||
.setAllowExpression(true)
|
|
||||||
.setDefaultValue(new ModelNode(false))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public AbstractAddOverlayHandler() {
|
|
||||||
super(AddProviderHandler.DEFINITION.getParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
|
||||||
final String uploadFileName = UPLOADED_FILE_NAME.resolveModelAttribute(context, model).asString();
|
|
||||||
final boolean isRedeploy = isRedeploy(context, operation);
|
|
||||||
final boolean isOverwrite = OVERWRITE.resolveModelAttribute(context, model).asBoolean();
|
|
||||||
|
|
||||||
String overlayPath = getOverlayPath(uploadFileName);
|
|
||||||
String overlayName = AuthServerUtil.getOverlayName(operation);
|
|
||||||
PathAddress overlayAddress = AuthServerUtil.getOverlayAddress(overlayName);
|
|
||||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
|
||||||
|
|
||||||
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
|
||||||
if (!isOverlayExists) {
|
|
||||||
addOverlay(context, overlayAddress);
|
|
||||||
if (!isHostController(context)) {
|
|
||||||
addDeploymentToOverlay(context, overlayAddress, deploymentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isHostController(context)) {
|
|
||||||
addOverlayToServerGroups(context, overlayAddress, operation, overlayName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isOverlayExists && isContentExists(context, overlayAddress, overlayPath)) {
|
|
||||||
if (isOverwrite) {
|
|
||||||
removeContent(context, overlayAddress, overlayPath);
|
|
||||||
} else {
|
|
||||||
throw new OperationFailedException(pathExistsMessage(overlayAddress, overlayPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addContent(context, overlayAddress, BYTES_TO_UPLOAD.resolveModelAttribute(context, model).asBytes(), overlayPath);
|
|
||||||
|
|
||||||
if (isRedeploy) { AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName); }
|
|
||||||
if (!isRedeploy) { context.restartRequired(); }
|
|
||||||
context.completeStep(OperationContext.ResultHandler.NOOP_RESULT_HANDLER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeContent(OperationContext context, PathAddress overlayAddress, String overlayPath) {
|
|
||||||
PathAddress contentAddress = overlayAddress.append("content", overlayPath);
|
|
||||||
ModelNode operation = Util.createRemoveOperation(contentAddress);
|
|
||||||
context.addStep(operation, AuthServerUtil.getHandler(context, contentAddress, REMOVE), OperationContext.Stage.MODEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isRedeploy(OperationContext context, ModelNode model) throws OperationFailedException {
|
|
||||||
return isAuthServerEnabled(context) && REDEPLOY_SERVER.resolveModelAttribute(context, model).asBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isHostController(OperationContext context) {
|
|
||||||
return context.getProcessType() == ProcessType.HOST_CONTROLLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String pathExistsMessage(PathAddress overlayAddress, String overlayPath) {
|
|
||||||
PathAddress contentAddress = overlayAddress.append("content", overlayPath);
|
|
||||||
String msg = "Can not update overlay at " + contentAddress.toCLIStyleString();
|
|
||||||
msg += " You may try your request again using the " + OVERWRITE.getName() + " attribute.";
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isContentExists(OperationContext context, PathAddress overlayAddress, String overlayPath) {
|
|
||||||
Resource resource = context.readResourceFromRoot(overlayAddress);
|
|
||||||
return resource.getChildrenNames("content").contains(overlayPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addOverlay(OperationContext context, PathAddress overlayAddress) {
|
|
||||||
ModelNode op = Util.createAddOperation(overlayAddress);
|
|
||||||
doAddStep(context, overlayAddress, op);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addDeploymentToOverlay(OperationContext context, PathAddress overlayAddress, String deploymentName) {
|
|
||||||
PathAddress deploymentAddress = overlayAddress.append("deployment", deploymentName);
|
|
||||||
ModelNode op = Util.createAddOperation(deploymentAddress);
|
|
||||||
doAddStep(context, deploymentAddress, op);
|
|
||||||
}
|
|
||||||
|
|
||||||
// only call this if context.getProcessType() == ProcessType.HOST_CONTROLLER
|
|
||||||
private void addOverlayToServerGroups(OperationContext context, PathAddress overlayAddress, ModelNode operation, String overlayName) {
|
|
||||||
String myProfile = context.getCurrentAddressValue();
|
|
||||||
for (String serverGroup : getServerGroupNames(context)) {
|
|
||||||
PathAddress address = PathAddress.pathAddress("server-group", serverGroup);
|
|
||||||
ModelNode serverGroupModel = context.readResourceFromRoot(address).getModel();
|
|
||||||
if (serverGroupModel.get("profile").asString().equals(myProfile)) {
|
|
||||||
PathAddress serverGroupOverlayAddress = address.append(overlayAddress);
|
|
||||||
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, address);
|
|
||||||
if (!isOverlayExists) {
|
|
||||||
addOverlay(context, serverGroupOverlayAddress);
|
|
||||||
addDeploymentToOverlay(context, serverGroupOverlayAddress, AuthServerUtil.getDeploymentName(operation));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> getServerGroupNames(OperationContext context) {
|
|
||||||
return context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS).getChildrenNames("server-group");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addContent(OperationContext context, PathAddress overlayAddress, byte[] bytes, String overlayPath) throws OperationFailedException {
|
|
||||||
PathAddress contentAddress = overlayAddress.append("content", overlayPath);
|
|
||||||
ModelNode op = Util.createAddOperation(contentAddress);
|
|
||||||
|
|
||||||
ModelNode content = new ModelNode();
|
|
||||||
content.get("bytes").set(bytes);
|
|
||||||
op.get("content").set(content);
|
|
||||||
|
|
||||||
doAddStep(context, contentAddress, op);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doAddStep(OperationContext context, PathAddress address, ModelNode operation) {
|
|
||||||
//System.out.println("**** Adding Add Step ****");
|
|
||||||
//System.out.println(scrub(operation).toString());
|
|
||||||
context.addStep(operation, AuthServerUtil.getHandler(context, address, ADD), OperationContext.Stage.MODEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isAuthServerEnabled(OperationContext context) throws OperationFailedException {
|
|
||||||
ModelNode authServerModel = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().clone();
|
|
||||||
return AuthServerDefinition.ENABLED.resolveModelAttribute(context, authServerModel).asBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
// used for debugging
|
|
||||||
private ModelNode scrub(ModelNode op) {
|
|
||||||
ModelNode scrubbed = op.clone();
|
|
||||||
if (scrubbed.has("content")) {
|
|
||||||
scrubbed.get("content").set("BYTES REMOVED FOR DISPLAY");
|
|
||||||
}
|
|
||||||
if (scrubbed.has("bytes-to-upload")) {
|
|
||||||
scrubbed.get("bytes-to-upload").set("BYTES REMOVED FOR DISPLAY");
|
|
||||||
}
|
|
||||||
return scrubbed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the WAR path where the overlay will live.
|
|
||||||
*
|
|
||||||
* @param fileName The name of the file being uploaded.
|
|
||||||
* @return The overlay path as a String.
|
|
||||||
*/
|
|
||||||
abstract String getOverlayPath(String fileName);
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.extension.authserver;
|
|
||||||
|
|
||||||
import org.jboss.as.controller.OperationDefinition;
|
|
||||||
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Operation to add a provider jar to WEB-INF/lib.
|
|
||||||
*
|
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
|
||||||
*/
|
|
||||||
public class AddProviderHandler extends AbstractAddOverlayHandler {
|
|
||||||
|
|
||||||
public static final String OP = "add-provider";
|
|
||||||
|
|
||||||
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
|
||||||
.addParameter(BYTES_TO_UPLOAD)
|
|
||||||
.addParameter(UPLOADED_FILE_NAME)
|
|
||||||
.addParameter(REDEPLOY_SERVER)
|
|
||||||
.addParameter(OVERWRITE)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public static final AddProviderHandler INSTANCE = new AddProviderHandler();
|
|
||||||
|
|
||||||
private AddProviderHandler() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
String getOverlayPath(String fileName) {
|
|
||||||
if (!fileName.toLowerCase().endsWith(".jar")) {
|
|
||||||
throw new IllegalArgumentException("Uploaded file name must end with .jar");
|
|
||||||
}
|
|
||||||
return "/WEB-INF/lib/" + fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.extension.authserver;
|
|
||||||
|
|
||||||
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;
|
|
||||||
import org.jboss.as.controller.registry.Resource;
|
|
||||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an auth server.
|
|
||||||
*
|
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
|
||||||
*/
|
|
||||||
public final class AuthServerAddHandler extends AbstractAddStepHandler {
|
|
||||||
|
|
||||||
public static AuthServerAddHandler INSTANCE = new AuthServerAddHandler();
|
|
||||||
|
|
||||||
private AuthServerAddHandler() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void populateModel(OperationContext context, ModelNode operation, Resource resource) throws OperationFailedException {
|
|
||||||
// TODO: localize exception. get id number
|
|
||||||
if (!operation.get(OP).asString().equals(ADD)) {
|
|
||||||
throw new OperationFailedException("Unexpected operation for add Auth Server. operation=" + operation.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode model = resource.getModel();
|
|
||||||
for (AttributeDefinition attr : AuthServerDefinition.ALL_ATTRIBUTES) {
|
|
||||||
attr.validateAndSet(operation, model);
|
|
||||||
}
|
|
||||||
model = context.resolveExpressions(model);
|
|
||||||
|
|
||||||
// returns early if on domain controller
|
|
||||||
if (!requiresRuntime(context)) return;
|
|
||||||
|
|
||||||
// don't want to try to start server on host controller
|
|
||||||
if (!context.isNormalServer()) return;
|
|
||||||
|
|
||||||
|
|
||||||
ModelNode webContextNode = model.get(AuthServerDefinition.WEB_CONTEXT.getName());
|
|
||||||
if (!webContextNode.isDefined()) webContextNode = AuthServerDefinition.WEB_CONTEXT.getDefaultValue();
|
|
||||||
String webContext = webContextNode.asString();
|
|
||||||
|
|
||||||
ModelNode isEnabled = model.get("enabled");
|
|
||||||
boolean enabled = isEnabled.isDefined() && isEnabled.asBoolean();
|
|
||||||
|
|
||||||
AuthServerUtil authServerUtil = new AuthServerUtil(operation);
|
|
||||||
authServerUtil.addStepToUploadAuthServer(context, enabled);
|
|
||||||
KeycloakAdapterConfigService.getInstance().addServerDeployment(authServerUtil.getDeploymentName(), webContext);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.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.descriptions.ResourceDescriptionResolver;
|
|
||||||
import org.jboss.as.controller.operations.validation.ParameterValidator;
|
|
||||||
import org.jboss.as.controller.registry.OperationEntry;
|
|
||||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
|
||||||
import org.keycloak.subsystem.server.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)
|
|
||||||
.setAllowExpression(true)
|
|
||||||
.setDefaultValue(new ModelNode(false))
|
|
||||||
.setRestartAllServices()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
protected static final SimpleAttributeDefinition WEB_CONTEXT =
|
|
||||||
new SimpleAttributeDefinitionBuilder("web-context", ModelType.STRING, true)
|
|
||||||
.setAllowExpression(true)
|
|
||||||
.setDefaultValue(new ModelNode("auth"))
|
|
||||||
.setValidator(new WebContextValidator())
|
|
||||||
.setRestartAllServices()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
protected static final ResourceDescriptionResolver rscDescriptionResolver = KeycloakExtension.getResourceDescriptionResolver(TAG_NAME);
|
|
||||||
|
|
||||||
public static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
|
||||||
static {
|
|
||||||
ALL_ATTRIBUTES.add(ENABLED);
|
|
||||||
ALL_ATTRIBUTES.add(WEB_CONTEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 AuthServerWriteAttributeHandler attrHandler = new AuthServerWriteAttributeHandler(ALL_ATTRIBUTES);
|
|
||||||
|
|
||||||
public AuthServerDefinition() {
|
|
||||||
super(PathElement.pathElement(TAG_NAME),
|
|
||||||
rscDescriptionResolver,
|
|
||||||
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);
|
|
||||||
resourceRegistration.registerOperationHandler(AddProviderHandler.DEFINITION, AddProviderHandler.INSTANCE);
|
|
||||||
resourceRegistration.registerOperationHandler(OverlayKeycloakServerJsonHandler.DEFINITION, OverlayKeycloakServerJsonHandler.INSTANCE);
|
|
||||||
resourceRegistration.registerOperationHandler(ListOverlaysHandler.DEFINITION, ListOverlaysHandler.INSTANCE);
|
|
||||||
resourceRegistration.registerOperationHandler(RemoveOverlayHandler.DEFINITION, RemoveOverlayHandler.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.getInstance().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.getInstance().isWebContextUsed(strValue)) {
|
|
||||||
throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.extension.authserver;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import org.jboss.as.controller.OperationContext;
|
|
||||||
import org.jboss.as.controller.OperationDefinition;
|
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
|
||||||
import org.jboss.as.controller.OperationStepHandler;
|
|
||||||
import org.jboss.as.controller.PathAddress;
|
|
||||||
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
|
|
||||||
import org.jboss.as.controller.registry.Resource;
|
|
||||||
import org.jboss.dmr.ModelNode;
|
|
||||||
import org.jboss.dmr.ModelType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Operation to list all of the provider jars, theme jars, and keycloak-server.json that
|
|
||||||
* have been uploaded to the auth server.
|
|
||||||
*
|
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
|
||||||
*/
|
|
||||||
public class ListOverlaysHandler implements OperationStepHandler {
|
|
||||||
static final String LIST_OVERLAYS_OPERATION = "list-overlays";
|
|
||||||
|
|
||||||
static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(LIST_OVERLAYS_OPERATION, AuthServerDefinition.rscDescriptionResolver)
|
|
||||||
.setReadOnly()
|
|
||||||
.setRuntimeOnly()
|
|
||||||
.setReplyType(ModelType.LIST)
|
|
||||||
.setReplyValueType(ModelType.STRING)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
static final OperationStepHandler INSTANCE = new ListOverlaysHandler();
|
|
||||||
|
|
||||||
private ListOverlaysHandler() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
|
|
||||||
final ModelNode result = context.getResult();
|
|
||||||
result.setEmptyList();
|
|
||||||
|
|
||||||
String overlayName = AuthServerUtil.getOverlayName(operation);
|
|
||||||
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
|
||||||
if (isOverlayExists) {
|
|
||||||
Set<String> overlays = new TreeSet<String>(getOverlayNames(context, overlayName));
|
|
||||||
for (final String key : overlays) {
|
|
||||||
result.add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> getOverlayNames(OperationContext context, String overlayName) {
|
|
||||||
PathAddress overlayAddr = PathAddress.pathAddress(DEPLOYMENT_OVERLAY, overlayName);
|
|
||||||
Resource resource = context.readResourceFromRoot(overlayAddr);
|
|
||||||
return resource.getChildrenNames(CONTENT);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.extension.authserver;
|
|
||||||
|
|
||||||
import org.jboss.as.controller.OperationDefinition;
|
|
||||||
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Operation to overlay keycloak-server.json.
|
|
||||||
*
|
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
|
||||||
*/
|
|
||||||
public class OverlayKeycloakServerJsonHandler extends AbstractAddOverlayHandler {
|
|
||||||
|
|
||||||
public static final String OP = "update-server-config";
|
|
||||||
|
|
||||||
public static final OverlayKeycloakServerJsonHandler INSTANCE = new OverlayKeycloakServerJsonHandler();
|
|
||||||
|
|
||||||
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
|
||||||
.addParameter(BYTES_TO_UPLOAD)
|
|
||||||
.addParameter(REDEPLOY_SERVER)
|
|
||||||
.addParameter(OVERWRITE)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private OverlayKeycloakServerJsonHandler() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
String getOverlayPath(String fileName) {
|
|
||||||
return "/WEB-INF/classes/META-INF/keycloak-server.json";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.server.extension.authserver;
|
|
||||||
|
|
||||||
import static org.keycloak.subsystem.server.extension.authserver.AbstractAddOverlayHandler.REDEPLOY_SERVER;
|
|
||||||
|
|
||||||
import org.jboss.as.controller.OperationContext;
|
|
||||||
import org.jboss.as.controller.OperationDefinition;
|
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
|
||||||
import org.jboss.as.controller.OperationStepHandler;
|
|
||||||
import org.jboss.as.controller.PathAddress;
|
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
|
||||||
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
|
|
||||||
import org.jboss.dmr.ModelNode;
|
|
||||||
import org.jboss.dmr.ModelType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Operation to remove a provider jars, theme jars, or keycloak-server.json that
|
|
||||||
* has been uploaded to the auth server.
|
|
||||||
*
|
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
|
||||||
*/
|
|
||||||
public class RemoveOverlayHandler implements OperationStepHandler {
|
|
||||||
static final String REMOVE_OVERLAY_OPERATION = "remove-overlay";
|
|
||||||
|
|
||||||
protected static final SimpleAttributeDefinition OVERLAY_FILE_PATH =
|
|
||||||
new SimpleAttributeDefinitionBuilder("overlay-file-path", ModelType.STRING, false)
|
|
||||||
.setAllowExpression(true)
|
|
||||||
.setAllowNull(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(REMOVE_OVERLAY_OPERATION, AuthServerDefinition.rscDescriptionResolver)
|
|
||||||
.addParameter(OVERLAY_FILE_PATH)
|
|
||||||
.addParameter(REDEPLOY_SERVER)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
static final OperationStepHandler INSTANCE = new RemoveOverlayHandler();
|
|
||||||
|
|
||||||
private RemoveOverlayHandler() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
|
|
||||||
final ModelNode model = new ModelNode();
|
|
||||||
OVERLAY_FILE_PATH.validateAndSet(operation, model);
|
|
||||||
REDEPLOY_SERVER.validateAndSet(operation, model);
|
|
||||||
String overlayName = AuthServerUtil.getOverlayName(operation);
|
|
||||||
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
|
||||||
String overlayPath = OVERLAY_FILE_PATH.resolveModelAttribute(context, model).asString();
|
|
||||||
if (isOverlayExists) {
|
|
||||||
PathAddress overlayAddress = AuthServerUtil.getOverlayAddress(overlayName);
|
|
||||||
AbstractAddOverlayHandler.removeContent(context, overlayAddress, overlayPath);
|
|
||||||
} else {
|
|
||||||
context.setRollbackOnly();
|
|
||||||
throw new OperationFailedException("Overlay path " + overlayPath + " not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isRedeploy = AbstractAddOverlayHandler.isRedeploy(context, operation);
|
|
||||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
|
||||||
if (isRedeploy) AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
|
|
||||||
if (!isRedeploy) context.restartRequired();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +1,4 @@
|
||||||
keycloak-server.subsystem=Keycloak subsystem
|
keycloak-server.subsystem=Keycloak subsystem
|
||||||
keycloak-server.subsystem.add=Operation Adds Keycloak subsystem
|
keycloak-server.subsystem.add=Operation Adds Keycloak subsystem
|
||||||
keycloak-server.subsystem.remove=Operation removes Keycloak subsystem
|
keycloak-server.subsystem.remove=Operation removes Keycloak subsystem
|
||||||
keycloak-server.subsystem.auth-server=Keycloak Auth Server
|
keycloak-server.subsystem.web-context=Web context where Keycloak server is bound. Default value is 'auth'.
|
||||||
keycloak-server.subsystem.realm=A Keycloak realm.
|
|
||||||
keycloak-server.subsystem.secure-deployment=A deployment secured by Keycloak.
|
|
||||||
|
|
||||||
|
|
||||||
keycloak-server.auth-server=A Keycloak Auth Server
|
|
||||||
keycloak-server.auth-server.add=Add an Auth Server to the subsystem.
|
|
||||||
keycloak-server.auth-server.remove=Remove an Auth Server from the subsystem.
|
|
||||||
keycloak-server.auth-server.add-provider=Add a provider service jar to the Keycloak auth server.
|
|
||||||
keycloak-server.auth-server.add-provider.uploaded-file-name=The file name of the provider service jar to be added or updated.
|
|
||||||
keycloak-server.auth-server.add-provider.bytes-to-upload=The bytes of the provider service jar to be added or updated.
|
|
||||||
keycloak-server.auth-server.add-provider.redeploy=Redeploy the auth server after adding the provider. Ignored if auth server is disabled.
|
|
||||||
keycloak-server.auth-server.add-provider.overwrite=Overwrite even if the uploaded-file-name already exists as an overlay.
|
|
||||||
keycloak-server.auth-server.list-overlays=List the overlays uploaded for this auth server.
|
|
||||||
keycloak-server.auth-server.remove-overlay=Remove a provider jar, theme jar, or keycloak-server.json that has been uploaded to the auth server.
|
|
||||||
keycloak-server.auth-server.remove-overlay.overlay-file-path=The uploaded path and file name of the overlay to be removed.
|
|
||||||
keycloak-server.auth-server.remove-overlay.redeploy=Redeploy the auth server after removing the overlay.
|
|
||||||
keycloak-server.auth-server.update-server-config=Upload a new keycloak-server.json configuration file for the Keycloak auth server.
|
|
||||||
keycloak-server.auth-server.update-server-config.bytes-to-upload=The bytes of the keycloak-server.json file to be added or updated.
|
|
||||||
keycloak-server.auth-server.update-server-config.redeploy=Redeploy the auth server after updating the server config.
|
|
||||||
keycloak-server.auth-server.update-server-config.overwrite=Overwrite even if keycloak-server.json already exitss as an overlay.
|
|
||||||
keycloak-server.auth-server.enabled=Enable or disable the Auth Server.
|
|
||||||
keycloak-server.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment.
|
|
||||||
|
|
|
@ -18,21 +18,8 @@
|
||||||
]]>
|
]]>
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
<xs:choice minOccurs="0" maxOccurs="1">
|
||||||
<xs:element name="auth-server" maxOccurs="1" minOccurs="0" type="auth-server-type"/>
|
<xs:element name="web-context" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||||
</xs:choice>
|
</xs:choice>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="auth-server-type">
|
|
||||||
<xs:all>
|
|
||||||
<xs:element name="web-context" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
|
||||||
<xs:element name="enabled" 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 war archive containing the Keycloak server web application.</xs:documentation>
|
|
||||||
</xs:annotation>
|
|
||||||
</xs:attribute>
|
|
||||||
</xs:complexType>
|
|
||||||
|
|
||||||
</xs:schema>
|
</xs:schema>
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
<config>
|
<config>
|
||||||
<extension-module>org.keycloak.keycloak-server-subsystem</extension-module>
|
<extension-module>org.keycloak.keycloak-server-subsystem</extension-module>
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
|
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
|
||||||
<auth-server name="main-auth-server">
|
<web-context>auth</web-context>
|
||||||
<enabled>true</enabled>
|
|
||||||
<web-context>auth</web-context>
|
|
||||||
</auth-server>
|
|
||||||
</subsystem>
|
</subsystem>
|
||||||
</config>
|
</config>
|
||||||
|
|
|
@ -41,7 +41,6 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
||||||
@Test
|
@Test
|
||||||
public void testJson() throws Exception {
|
public void testJson() throws Exception {
|
||||||
ModelNode node = new ModelNode();
|
ModelNode node = new ModelNode();
|
||||||
node.get("enabled").set(true);
|
|
||||||
node.get("web-context").set("auth");
|
node.get("web-context").set("auth");
|
||||||
|
|
||||||
System.out.println("json=" + node.toJSONString(false));
|
System.out.println("json=" + node.toJSONString(false));
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
|
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
|
||||||
<auth-server name="main-auth-server">
|
<web-context>auth</web-context>
|
||||||
<enabled>true</enabled>
|
|
||||||
<web-context>auth</web-context>
|
|
||||||
</auth-server>
|
|
||||||
</subsystem>
|
</subsystem>
|
Loading…
Reference in a new issue