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>
|
||||
<type>war</type>
|
||||
<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>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-server-subsystem">
|
||||
<properties>
|
||||
<property name="keycloak-version" value="${project.version}"/>
|
||||
<property name="auth-server-exploded" value="false"/>
|
||||
<property name="server-war-exploded" value="false"/>
|
||||
</properties>
|
||||
|
||||
<resources>
|
||||
|
|
|
@ -14,14 +14,8 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
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
|
||||
* 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 {
|
||||
|
||||
private static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
|
||||
static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
|
||||
|
||||
public static KeycloakAdapterConfigService getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
// key=auth-server deployment name; value=web-context
|
||||
private final Map<String, String> webContexts = new HashMap<String, String>();
|
||||
static final String DEPLOYMENT_NAME = "keycloak-server";
|
||||
|
||||
private String webContext;
|
||||
|
||||
|
||||
private KeycloakAdapterConfigService() {
|
||||
}
|
||||
|
||||
public void addServerDeployment(String deploymentName, String webContext) {
|
||||
this.webContexts.put(deploymentName, webContext);
|
||||
void setWebContext(String webContext) {
|
||||
this.webContext = webContext;
|
||||
}
|
||||
|
||||
public String getWebContext(String deploymentName) {
|
||||
return webContexts.get(deploymentName);
|
||||
String getWebContext() {
|
||||
return webContext;
|
||||
}
|
||||
|
||||
public void removeServerDeployment(String deploymentName) {
|
||||
this.webContexts.remove(deploymentName);
|
||||
}
|
||||
|
||||
public boolean isWebContextUsed(String webContext) {
|
||||
return webContexts.containsValue(webContext);
|
||||
}
|
||||
|
||||
public boolean isKeycloakServerDeployment(String deploymentName) {
|
||||
return this.webContexts.containsKey(deploymentName);
|
||||
boolean isKeycloakServerDeployment(String deploymentName) {
|
||||
return DEPLOYMENT_NAME.equals(deploymentName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,9 @@ import org.jboss.as.controller.ResourceDefinition;
|
|||
import org.jboss.as.controller.SubsystemRegistration;
|
||||
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
|
||||
import org.jboss.as.controller.parsing.ExtensionParsingContext;
|
||||
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||
import org.keycloak.subsystem.server.extension.authserver.AuthServerDefinition;
|
||||
import org.keycloak.subsystem.server.logging.KeycloakLogger;
|
||||
|
||||
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 static final String SUBSYSTEM_NAME = "keycloak-server";
|
||||
public static final String NAMESPACE = "urn:jboss:domain:keycloak-server:1.1";
|
||||
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
|
||||
static final String SUBSYSTEM_NAME = "keycloak-server";
|
||||
static final String NAMESPACE = "urn:jboss:domain:keycloak-server:1.1";
|
||||
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);
|
||||
for (String kp : keyPrefix) {
|
||||
prefix.append('.').append(kp);
|
||||
|
@ -61,7 +58,7 @@ public class KeycloakExtension implements Extension {
|
|||
*/
|
||||
@Override
|
||||
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
|
||||
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);
|
||||
|
||||
ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
||||
registration.registerSubModel(AUTH_SERVER_DEFINITION);
|
||||
subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
||||
subsystem.registerXMLElementWriter(PARSER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,14 +14,13 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* 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.server.deployment.DeploymentPhaseContext;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
||||
|
||||
/**
|
||||
* DUP responsible for setting the web context of a Keycloak auth server.
|
||||
|
@ -33,22 +32,22 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso
|
|||
@Override
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
KeycloakAdapterConfigService config = KeycloakAdapterConfigService.INSTANCE;
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
if (!service.isKeycloakServerDeployment(deploymentName)) {
|
||||
|
||||
if (!config.isKeycloakServerDeployment(deploymentName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undeploy(DeploymentUnit du) {
|
||||
|
||||
}
|
||||
}
|
|
@ -17,13 +17,18 @@
|
|||
package org.keycloak.subsystem.server.extension;
|
||||
|
||||
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
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.DeploymentProcessorTarget;
|
||||
import org.jboss.as.server.deployment.Phase;
|
||||
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.
|
||||
|
@ -35,15 +40,44 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
|
|||
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
|
||||
|
||||
@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() {
|
||||
@Override
|
||||
protected void execute(DeploymentProcessorTarget processorTarget) {
|
||||
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME,
|
||||
processorTarget.addDeploymentProcessor(SUBSYSTEM_NAME,
|
||||
Phase.POST_MODULE, // PHASE
|
||||
Phase.POST_MODULE_VALIDATOR_FACTORY - 1, // PRIORITY
|
||||
new KeycloakServerDeploymentProcessor());
|
||||
}
|
||||
}, 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
|
||||
* the License.
|
||||
*/
|
||||
|
||||
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.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;
|
||||
|
||||
/**
|
||||
* Definition of subsystem=keycloak.
|
||||
* Definition of subsystem=keycloak-server.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||
*/
|
||||
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() {
|
||||
super(KeycloakExtension.SUBSYSTEM_PATH,
|
||||
KeycloakExtension.getResourceDescriptionResolver("subsystem"),
|
||||
KeycloakSubsystemAdd.INSTANCE,
|
||||
ReloadRequiredRemoveStepHandler.INSTANCE
|
||||
super(KeycloakExtension.PATH_SUBSYSTEM,
|
||||
KeycloakExtension.getResourceDescriptionResolver("subsystem"),
|
||||
KeycloakSubsystemAdd.INSTANCE,
|
||||
KeycloakSubsystemRemoveHandler.INSTANCE
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -42,4 +73,15 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
|
|||
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;
|
||||
|
||||
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.PathElement;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
|
||||
import org.jboss.as.controller.operations.common.Util;
|
||||
import org.jboss.as.controller.parsing.ParseUtils;
|
||||
import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.dmr.Property;
|
||||
import org.jboss.staxmapper.XMLElementReader;
|
||||
import org.jboss.staxmapper.XMLElementWriter;
|
||||
import org.jboss.staxmapper.XMLExtendedStreamReader;
|
||||
|
@ -34,9 +28,11 @@ import org.jboss.staxmapper.XMLExtendedStreamWriter;
|
|||
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.util.Collections;
|
||||
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
|
||||
*/
|
||||
|
@ -49,12 +45,14 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException {
|
||||
// Require no attributes
|
||||
ParseUtils.requireNoAttributes(reader);
|
||||
ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(KeycloakExtension.PATH_SUBSYSTEM));
|
||||
ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(PATH_SUBSYSTEM));
|
||||
list.add(addKeycloakSub);
|
||||
|
||||
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
||||
if (reader.getLocalName().equals(AuthServerDefinition.TAG_NAME)) {
|
||||
readAuthServer(reader, list);
|
||||
if (reader.getLocalName().equals(WEB_CONTEXT.getXmlName())) {
|
||||
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();
|
||||
}
|
||||
|
||||
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}
|
||||
*/
|
||||
@Override
|
||||
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
|
||||
writeAuthServers(writer, context);
|
||||
writeWebContext(writer, context);
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
private void writeAuthServers(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
if (!context.getModelNode().get(AuthServerDefinition.TAG_NAME).isDefined()) {
|
||||
private void writeWebContext(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||
if (!context.getModelNode().get(WEB_CONTEXT.getName()).isDefined()) {
|
||||
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
|
||||
* 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.OperationFailedException;
|
||||
import org.jboss.as.controller.OperationStepHandler;
|
||||
import org.jboss.as.controller.PathAddress;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
|
||||
import org.jboss.as.controller.operations.common.Util;
|
||||
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.REMOVE;
|
||||
|
@ -36,25 +34,25 @@ import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
|||
*
|
||||
* @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
|
||||
protected void performRemove(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||
KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
|
||||
String deploymentName = ServerUtil.getDeploymentName(operation);
|
||||
KeycloakAdapterConfigService.INSTANCE.setWebContext(null);
|
||||
|
||||
if (requiresRuntime(context)) { // don't do this on a domain controller
|
||||
addStepToRemoveAuthServer(context, deploymentName);
|
||||
addStepToRemoveServerWar(context, deploymentName);
|
||||
}
|
||||
|
||||
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));
|
||||
ModelNode op = Util.createOperation(REMOVE, deploymentAddress);
|
||||
context.addStep(op, getRemoveHandler(context, deploymentAddress), OperationContext.Stage.MODEL);
|
|
@ -14,8 +14,7 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.server.extension.authserver;
|
||||
package org.keycloak.subsystem.server.extension;
|
||||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
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.registry.Resource;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.keycloak.subsystem.server.extension.KeycloakAdapterConfigService;
|
||||
|
||||
/**
|
||||
* Update an attribute on an Auth Server.
|
||||
*
|
||||
* @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()]));
|
||||
}
|
||||
|
||||
public AuthServerWriteAttributeHandler(AttributeDefinition... definitions) {
|
||||
public KeycloakSubsystemWriteAttributeHandler(AttributeDefinition... definitions) {
|
||||
super(definitions);
|
||||
}
|
||||
|
||||
|
@ -50,34 +48,24 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand
|
|||
return;
|
||||
}
|
||||
|
||||
boolean isEnabled = AuthServerDefinition.ENABLED.resolveModelAttribute(context, model.getModel()).asBoolean();
|
||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||
String deploymentName = ServerUtil.getDeploymentName(operation);
|
||||
|
||||
if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
|
||||
|
||||
KeycloakAdapterConfigService.getInstance().removeServerDeployment(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);
|
||||
}
|
||||
if (attributeName.equals(KeycloakSubsystemDefinition.WEB_CONTEXT.getName())) {
|
||||
KeycloakAdapterConfigService.INSTANCE.setWebContext(newValue.asString());
|
||||
ServerUtil.addStepToRedeployServerWar(context, deploymentName);
|
||||
}
|
||||
|
||||
super.finishModelStage(context, operation, attributeName, newValue, oldValue, model);
|
||||
}
|
||||
|
||||
private boolean attribNotChanging(String attributeName, ModelNode newValue, ModelNode oldValue) {
|
||||
SimpleAttributeDefinition attribDef = AuthServerDefinition.lookup(attributeName);
|
||||
if (!oldValue.isDefined()) oldValue = attribDef.getDefaultValue();
|
||||
if (!newValue.isDefined()) newValue = attribDef.getDefaultValue();
|
||||
SimpleAttributeDefinition attribDef = KeycloakSubsystemDefinition.lookup(attributeName);
|
||||
if (!oldValue.isDefined()) {
|
||||
oldValue = attribDef.getDefaultValue();
|
||||
}
|
||||
if (!newValue.isDefined()) {
|
||||
newValue = attribDef.getDefaultValue();
|
||||
}
|
||||
return newValue.equals(oldValue);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.keycloak.subsystem.server.extension.authserver;
|
||||
package org.keycloak.subsystem.server.extension;
|
||||
|
||||
import java.io.File;
|
||||
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.ARCHIVE;
|
||||
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_OVERLAY;
|
||||
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.PATH;
|
||||
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.UNDEPLOY;
|
||||
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.as.controller.registry.Resource;
|
||||
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.modules.Module;
|
||||
import org.jboss.modules.ModuleIdentifier;
|
||||
import org.jboss.modules.ModuleLoadException;
|
||||
import org.keycloak.subsystem.server.extension.KeycloakExtension;
|
||||
|
||||
/**
|
||||
* Utility methods that help assemble and start an auth server.
|
||||
*
|
||||
* @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 final String deploymentName;
|
||||
private final Module subsysModule;
|
||||
private final String keycloakVersion;
|
||||
private final boolean isAuthServerExploded;
|
||||
private final URI authServerUri;
|
||||
private final boolean isServerWarExploded;
|
||||
private final URI serverWar;
|
||||
|
||||
AuthServerUtil(ModelNode operation) {
|
||||
ServerUtil(ModelNode operation) {
|
||||
this.deploymentName = getDeploymentName(operation);
|
||||
this.subsysModule = findSubsysModule();
|
||||
this.keycloakVersion = subsysModule.getProperty("keycloak-version");
|
||||
this.isAuthServerExploded = Boolean.parseBoolean(subsysModule.getProperty("auth-server-exploded"));
|
||||
this.authServerUri = findAuthServerUri();
|
||||
}
|
||||
|
||||
String getDeploymentName() {
|
||||
return this.deploymentName;
|
||||
this.isServerWarExploded = Boolean.parseBoolean(subsysModule.getProperty("server-war-exploded"));
|
||||
this.serverWar = findServerWarUri();
|
||||
}
|
||||
|
||||
private Module findSubsysModule() {
|
||||
|
@ -83,15 +75,15 @@ public class AuthServerUtil {
|
|||
}
|
||||
}
|
||||
|
||||
private URI findAuthServerUri() throws IllegalStateException {
|
||||
private URI findServerWarUri() throws IllegalStateException {
|
||||
try {
|
||||
URL subsysResource = this.subsysModule.getExportedResource("module.xml");
|
||||
File subsysDir = new File(subsysResource.toURI()).getParentFile();
|
||||
File authServerDir = new File(subsysDir, "auth-server");
|
||||
if (this.isAuthServerExploded) {
|
||||
return authServerDir.toURI();
|
||||
File serverWarDir = new File(subsysDir, "server-war");
|
||||
if (this.isServerWarExploded) {
|
||||
return serverWarDir.toURI();
|
||||
} else {
|
||||
return new File(authServerDir, "keycloak-server-" + keycloakVersion + ".war").toURI();
|
||||
return new File(serverWarDir, "keycloak-server-" + keycloakVersion + ".war").toURI();
|
||||
}
|
||||
} catch (URISyntaxException 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);
|
||||
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
|
||||
op.get("owner").set(new ModelNode().add("subsystem", KeycloakExtension.SUBSYSTEM_NAME));
|
||||
|
||||
if (authServerUri == null) {
|
||||
throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-server-subsystem module");
|
||||
if (serverWar == null) {
|
||||
throw new OperationFailedException("Keycloak Server WAR not found in keycloak-server-subsystem module");
|
||||
}
|
||||
|
||||
op.get(CONTENT).add(makeContentItem());
|
||||
|
@ -121,32 +117,26 @@ public class AuthServerUtil {
|
|||
private ModelNode makeContentItem() throws OperationFailedException {
|
||||
ModelNode contentItem = new ModelNode();
|
||||
|
||||
if (this.isAuthServerExploded) {
|
||||
String urlString = new File(authServerUri).getAbsolutePath();
|
||||
if (this.isServerWarExploded) {
|
||||
String urlString = new File(serverWar).getAbsolutePath();
|
||||
contentItem.get(PATH).set(urlString);
|
||||
contentItem.get(ARCHIVE).set(false);
|
||||
} else {
|
||||
String urlString = authServerUri.toString();
|
||||
String urlString = serverWar.toString();
|
||||
contentItem.get(URL).set(urlString);
|
||||
}
|
||||
|
||||
return contentItem;
|
||||
}
|
||||
|
||||
static void addStepToRedeployAuthServer(OperationContext context, String deploymentName) {
|
||||
static void addStepToRedeployServerWar(OperationContext context, String 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) {
|
||||
if (!context.isNormalServer()) return;
|
||||
if (!context.isNormalServer()) {
|
||||
return;
|
||||
}
|
||||
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
||||
ModelNode op = Util.createOperation(operation, deploymentAddress);
|
||||
op.get(RUNTIME_NAME).set(deploymentName);
|
||||
|
@ -170,27 +160,4 @@ public class AuthServerUtil {
|
|||
|
||||
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.add=Operation Adds Keycloak subsystem
|
||||
keycloak-server.subsystem.remove=Operation removes Keycloak subsystem
|
||||
keycloak-server.subsystem.auth-server=Keycloak Auth Server
|
||||
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.
|
||||
keycloak-server.subsystem.web-context=Web context where Keycloak server is bound. Default value is 'auth'.
|
||||
|
|
|
@ -18,21 +18,8 @@
|
|||
]]>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="auth-server" maxOccurs="1" minOccurs="0" type="auth-server-type"/>
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="web-context" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:choice>
|
||||
</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>
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
<config>
|
||||
<extension-module>org.keycloak.keycloak-server-subsystem</extension-module>
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
|
||||
<auth-server name="main-auth-server">
|
||||
<enabled>true</enabled>
|
||||
<web-context>auth</web-context>
|
||||
</auth-server>
|
||||
<web-context>auth</web-context>
|
||||
</subsystem>
|
||||
</config>
|
||||
|
|
|
@ -41,7 +41,6 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
|||
@Test
|
||||
public void testJson() throws Exception {
|
||||
ModelNode node = new ModelNode();
|
||||
node.get("enabled").set(true);
|
||||
node.get("web-context").set("auth");
|
||||
|
||||
System.out.println("json=" + node.toJSONString(false));
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
|
||||
<auth-server name="main-auth-server">
|
||||
<enabled>true</enabled>
|
||||
<web-context>auth</web-context>
|
||||
</auth-server>
|
||||
<web-context>auth</web-context>
|
||||
</subsystem>
|
Loading…
Reference in a new issue