Merge pull request #855 from ssilvert/subsys-enhancements
KEYCLOAK-839 Auth Server overlay enhancements
|
@ -1,27 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2010, Red Hat, Inc., and individual contributors
|
||||
~ as indicated by the @author tags. See the copyright.txt file in the
|
||||
~ distribution for a full listing of individual contributors.
|
||||
~
|
||||
~ This is free software; you can redistribute it and/or modify it
|
||||
~ under the terms of the GNU Lesser General Public License as
|
||||
~ published by the Free Software Foundation; either version 2.1 of
|
||||
~ the License, or (at your option) any later version.
|
||||
~
|
||||
~ This software is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
~ Lesser General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Lesser General Public
|
||||
~ License along with this software; if not, write to the Free
|
||||
~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
@ -86,7 +64,6 @@
|
|||
<dependency>
|
||||
<groupId>org.wildfly.core</groupId>
|
||||
<artifactId>wildfly-cli</artifactId>
|
||||
<version>${wildfly.core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</properties>
|
||||
|
||||
<resources>
|
||||
<artifact name="org.jboss.aesh:aesh:0.33.12"/>
|
||||
<!-- Insert resources here -->
|
||||
</resources>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<main-class name="org.jboss.as.cli.CommandLineMain"/>
|
||||
|
||||
<resources>
|
||||
<resource-root path="wildfly-cli-1.0.0.Alpha11-SNAPSHOT.jar"/>
|
||||
<!-- Insert resources here -->
|
||||
</resources>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -799,7 +799,7 @@ keycloak-war-dist-all-&project.version;/
|
|||
<title>Using CLI and CLI GUI with the Keycloak Subsystem</title>
|
||||
<para>
|
||||
Servers can also be added/removed or enabled/disabled at runtime using the <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> tool. These are tools that ship with WildFly and also with
|
||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> tool. These are tools that ship with WildFly/EAP and also with
|
||||
the Keycloak Appliance installation. See <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> documentation to learn more about how to start the tools,
|
||||
issue commands, and create CLI scripts.
|
||||
|
@ -812,7 +812,7 @@ cd <APPLIANCE_INSTALL_DIR>/keycloak/bin
|
|||
or
|
||||
./jboss.cli.bat --gui]]>
|
||||
</programlisting>
|
||||
<note>Your Keycloak server must be running to start in --gui mode.</note>
|
||||
<note>Your server must be running to start in --gui mode.</note>
|
||||
</para>
|
||||
<section>
|
||||
<title>Basic CLI Commands</title>
|
||||
|
@ -842,7 +842,7 @@ The Keycloak server will be immediately deployed or undeployed, but not deleted.
|
|||
<title>Uploading extra configuration using CLI</title>
|
||||
<para>
|
||||
The WildFly Keycloak subsystem allows you to upload keycloak-server.json, provider jars, and theme jars to a Keycloak server instance. The
|
||||
CLI operations for this are "update-server-config" and "add-provider". You may use plain or CLI scripts for these operations. The following
|
||||
CLI operations for this are "update-server-config" and "add-provider". You may use CLI, CLI GUI, or CLI scripts for these operations. The following
|
||||
examples are shown using <ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> for clarity.
|
||||
</para>
|
||||
<para>
|
||||
|
@ -874,6 +874,39 @@ The Keycloak server will be immediately deployed or undeployed, but not deleted.
|
|||
<imagedata fileref="images/add-provider-dialog.png"/>
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Working with overlays</title>
|
||||
<para>
|
||||
When you upload a provider jar, theme jar, or keycloak-server.json file, you are creating an overlay. That is, the file is "overlayed"
|
||||
onto the Keycloak server at deploy time. There are two additional operations that help you manage these overlays. They are "list-overlays" and
|
||||
"remove-overlay". Here are CLI examples of these operations.
|
||||
</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
/subsystem=keycloak/auth-server=my-auth-server/:list-overlays
|
||||
{
|
||||
"outcome" => "success",
|
||||
"result" => [
|
||||
"/WEB-INF/classes/META-INF/keycloak-server.json",
|
||||
"/WEB-INF/lib/federation-properties-example.jar"
|
||||
],
|
||||
}</programlisting>
|
||||
<programlisting>
|
||||
/subsystem=keycloak/auth-server=my-auth-server/:remove-overlay(overlay-file-path=/WEB-INF/lib/federation-properties-example.jar,redeploy=true)
|
||||
{
|
||||
"outcome" => "success",
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
<note>
|
||||
Notice in the "list-overlays" operation, the full path to the server config is
|
||||
/WEB-INF/classes/META-INF/keycloak-server.json. This is always the uploaded path for an "update-server-config" operation.
|
||||
If you remove this overlay, the Keycloak server will revert to its default keycloak-server.json. If you have a
|
||||
keycloak-server.json file in your <WILDFLY_HOME>/standalone/configuration directory, it will always take precedence
|
||||
over both the default and the overlay.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Adding a Keycloak server in Domain Mode</title>
|
||||
|
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 80 KiB |
|
@ -21,12 +21,11 @@ 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.ProcessType;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
|
||||
import org.jboss.as.controller.operations.common.Util;
|
||||
import org.jboss.as.controller.registry.Resource;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
|
@ -48,21 +47,39 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
|||
.setAllowNull(false)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition REDEPLOY_SERVER =
|
||||
new SimpleAttributeDefinitionBuilder("redeploy", ModelType.BOOLEAN, true)
|
||||
.setXmlName("redeploy")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition OVERWRITE =
|
||||
new SimpleAttributeDefinitionBuilder("overwrite", ModelType.BOOLEAN, true)
|
||||
.setXmlName("overwrite")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException {
|
||||
//System.out.println("*** execute operation ***");
|
||||
//System.out.println(scrub(operation));
|
||||
|
||||
String uploadFileName = operation.get(UPLOADED_FILE_OP_NAME).asString();
|
||||
String overlayPath = getOverlayPath(uploadFileName);
|
||||
String overlayName = AuthServerUtil.getAuthServerName(operation) + "-keycloak-overlay";
|
||||
PathAddress overlayAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT_OVERLAY, overlayName));
|
||||
boolean isRedeploy = isRedeploy(context, operation);
|
||||
boolean isOverwrite = getBooleanFromOperation(operation, OVERWRITE);
|
||||
|
||||
boolean isOverlayExists = isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
||||
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, AuthServerUtil.getDeploymentName(operation));
|
||||
addDeploymentToOverlay(context, overlayAddress, deploymentName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,36 +87,42 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
|||
addOverlayToServerGroups(context, overlayAddress, operation, overlayName);
|
||||
}
|
||||
|
||||
// There is no way to do an overwrite of content from here because it involves
|
||||
// removing the overlay service in the runtime phase. You have to remove
|
||||
// the content in a seperate operation.
|
||||
if (isOverlayExists && isContentExists(context, overlayAddress, overlayPath)) {
|
||||
throw new OperationFailedException(pathExistsMessage(overlayAddress, overlayPath));
|
||||
if (isOverwrite) {
|
||||
removeContent(context, overlayAddress, overlayPath);
|
||||
} else {
|
||||
throw new OperationFailedException(pathExistsMessage(overlayAddress, overlayPath));
|
||||
}
|
||||
}
|
||||
|
||||
addContent(context, overlayAddress, operation.get(BYTES_TO_UPLOAD.getName()).asBytes(), overlayPath);
|
||||
|
||||
context.restartRequired();
|
||||
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, getHandler(context, contentAddress, REMOVE), OperationContext.Stage.MODEL);
|
||||
}
|
||||
|
||||
static boolean isRedeploy(OperationContext context, ModelNode operation) {
|
||||
return isAuthServerEnabled(context) && getBooleanFromOperation(operation, REDEPLOY_SERVER);
|
||||
}
|
||||
|
||||
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. ";
|
||||
msg += "First remove the overlay with CLI using the following command with the content path in double quotes: ";
|
||||
msg += contentAddress.toCLIStyleString() + ":remove";
|
||||
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 isOverlayExists(OperationContext context, String overlayName, PathAddress address) {
|
||||
Resource resource = context.readResourceFromRoot(address);
|
||||
return resource.getChildrenNames("deployment-overlay").contains(overlayName);
|
||||
}
|
||||
|
||||
private boolean isContentExists(OperationContext context, PathAddress overlayAddress, String overlayPath) {
|
||||
Resource resource = context.readResourceFromRoot(overlayAddress);
|
||||
return resource.getChildrenNames("content").contains(overlayPath);
|
||||
|
@ -124,7 +147,7 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
|||
ModelNode serverGroupModel = context.readResourceFromRoot(address).getModel();
|
||||
if (serverGroupModel.get("profile").asString().equals(myProfile)) {
|
||||
PathAddress serverGroupOverlayAddress = address.append(overlayAddress);
|
||||
boolean isOverlayExists = isOverlayExists(context, overlayName, address);
|
||||
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, address);
|
||||
if (!isOverlayExists) {
|
||||
addOverlay(context, serverGroupOverlayAddress);
|
||||
addDeploymentToOverlay(context, serverGroupOverlayAddress, AuthServerUtil.getDeploymentName(operation));
|
||||
|
@ -160,6 +183,23 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
|||
context.addStep(operation, getHandler(context, address, ADD), OperationContext.Stage.MODEL);
|
||||
}
|
||||
|
||||
private static boolean isAuthServerEnabled(OperationContext context) {
|
||||
boolean defaultValue = AuthServerDefinition.ENABLED.getDefaultValue().asBoolean();
|
||||
ModelNode authServerModel = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().clone();
|
||||
String attrName = AuthServerDefinition.ENABLED.getName();
|
||||
if (!authServerModel.get(attrName).isDefined()) return defaultValue;
|
||||
return authServerModel.get(attrName).asBoolean();
|
||||
}
|
||||
|
||||
private static boolean getBooleanFromOperation(ModelNode operation, SimpleAttributeDefinition definition) {
|
||||
boolean defaultValue = definition.getDefaultValue().asBoolean();
|
||||
if (!operation.get(definition.getName()).isDefined()) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
return operation.get(definition.getName()).asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
// used for debugging
|
||||
private ModelNode scrub(ModelNode op) {
|
||||
ModelNode scrubbed = op.clone();
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.keycloak.subsystem.extension.authserver;
|
||||
|
||||
import java.io.File;
|
||||
import org.jboss.as.controller.OperationDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
|
@ -46,8 +45,12 @@ public class AddProviderHandler extends AbstractAddOverlayHandler {
|
|||
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
||||
.addParameter(BYTES_TO_UPLOAD)
|
||||
.addParameter(UPLOADED_FILE_NAME)
|
||||
.addParameter(REDEPLOY_SERVER)
|
||||
.addParameter(OVERWRITE)
|
||||
.build();
|
||||
|
||||
private AddProviderHandler() {}
|
||||
|
||||
@Override
|
||||
String getOverlayPath(String fileName) {
|
||||
if (!fileName.toLowerCase().endsWith(".jar")) {
|
||||
|
|
|
@ -95,6 +95,8 @@ public class AuthServerDefinition extends SimpleResourceDefinition {
|
|||
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
|
||||
|
|
|
@ -31,6 +31,7 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARC
|
|||
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;
|
||||
|
@ -40,6 +41,7 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UND
|
|||
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;
|
||||
|
@ -108,7 +110,7 @@ public class AuthServerUtil {
|
|||
}
|
||||
|
||||
void addStepToUploadAuthServer(OperationContext context, boolean isEnabled) throws OperationFailedException {
|
||||
PathAddress deploymentAddress = deploymentAddress();
|
||||
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
|
||||
|
@ -137,26 +139,27 @@ public class AuthServerUtil {
|
|||
return contentItem;
|
||||
}
|
||||
|
||||
void addStepToRedeployAuthServer(OperationContext context) {
|
||||
addDeploymentAction(context, REDEPLOY);
|
||||
static void addStepToRedeployAuthServer(OperationContext context, String deploymentName) {
|
||||
addDeploymentAction(context, REDEPLOY, deploymentName);
|
||||
}
|
||||
|
||||
void addStepToUndeployAuthServer(OperationContext context) {
|
||||
addDeploymentAction(context, UNDEPLOY);
|
||||
static void addStepToUndeployAuthServer(OperationContext context, String deploymentName) {
|
||||
addDeploymentAction(context, UNDEPLOY, deploymentName);
|
||||
}
|
||||
|
||||
void addStepToDeployAuthServer(OperationContext context) {
|
||||
addDeploymentAction(context, DEPLOY);
|
||||
static void addStepToDeployAuthServer(OperationContext context, String deploymentName) {
|
||||
addDeploymentAction(context, DEPLOY, deploymentName);
|
||||
}
|
||||
|
||||
private void addDeploymentAction(OperationContext context, String operation) {
|
||||
PathAddress deploymentAddress = deploymentAddress();
|
||||
private static void addDeploymentAction(OperationContext context, String operation, String deploymentName) {
|
||||
if (!context.isNormalServer()) return;
|
||||
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
||||
ModelNode op = Util.createOperation(operation, deploymentAddress);
|
||||
op.get(RUNTIME_NAME).set(deploymentName);
|
||||
context.addStep(op, getHandler(context, deploymentAddress, operation), OperationContext.Stage.MODEL);
|
||||
}
|
||||
|
||||
private PathAddress deploymentAddress() {
|
||||
private static PathAddress deploymentAddress(String deploymentName) {
|
||||
return PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
|
||||
}
|
||||
|
||||
|
@ -183,4 +186,17 @@ public class AuthServerUtil {
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,23 +50,23 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand
|
|||
return;
|
||||
}
|
||||
|
||||
AuthServerUtil authServerUtil = new AuthServerUtil(operation);
|
||||
boolean isEnabled = isEnabled(model); // is server currently enabled?
|
||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||
|
||||
if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
|
||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||
|
||||
KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName);
|
||||
KeycloakAdapterConfigService.INSTANCE.addServerDeployment(deploymentName, newValue.asString());
|
||||
if (isEnabled) {
|
||||
authServerUtil.addStepToRedeployAuthServer(context);
|
||||
AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
|
||||
}
|
||||
}
|
||||
|
||||
if (attributeName.equals(AuthServerDefinition.ENABLED.getName())) {
|
||||
if (!isEnabled) { // we are disabling
|
||||
authServerUtil.addStepToUndeployAuthServer(context);
|
||||
AuthServerUtil.addStepToUndeployAuthServer(context, deploymentName);
|
||||
} else { // we are enabling
|
||||
authServerUtil.addStepToDeployAuthServer(context);
|
||||
AuthServerUtil.addStepToDeployAuthServer(context, deploymentName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.extension.authserver;
|
||||
|
||||
import java.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);
|
||||
}
|
||||
}
|
||||
|
||||
context.stepCompleted();
|
||||
}
|
||||
|
||||
private Set<String> getOverlayNames(OperationContext context, String overlayName) {
|
||||
PathAddress overlayAddr = PathAddress.pathAddress(DEPLOYMENT_OVERLAY, overlayName);
|
||||
Resource resource = context.readResourceFromRoot(overlayAddr);
|
||||
return resource.getChildrenNames(CONTENT);
|
||||
}
|
||||
}
|
|
@ -33,8 +33,12 @@ public class OverlayKeycloakServerJsonHandler extends AbstractAddOverlayHandler
|
|||
|
||||
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";
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.subsystem.extension.authserver;
|
||||
|
||||
import org.jboss.as.controller.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)
|
||||
.setDefaultValue(new ModelNode().set("/WEB-INF/lib/myprovider.jar"))
|
||||
.build();
|
||||
|
||||
static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(REMOVE_OVERLAY_OPERATION, AuthServerDefinition.rscDescriptionResolver)
|
||||
.addParameter(OVERLAY_FILE_PATH)
|
||||
.addParameter(AbstractAddOverlayHandler.REDEPLOY_SERVER)
|
||||
.build();
|
||||
|
||||
static final OperationStepHandler INSTANCE = new RemoveOverlayHandler();
|
||||
|
||||
private RemoveOverlayHandler() {}
|
||||
|
||||
@Override
|
||||
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
|
||||
String overlayName = AuthServerUtil.getOverlayName(operation);
|
||||
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
||||
String overlayPath = operation.get(OVERLAY_FILE_PATH.getName()).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();
|
||||
|
||||
context.stepCompleted();
|
||||
}
|
||||
}
|
|
@ -12,9 +12,16 @@ keycloak.auth-server.remove=Remove an Auth Server from the subsystem.
|
|||
keycloak.auth-server.add-provider=Add a provider service jar to the Keycloak auth server.
|
||||
keycloak.auth-server.add-provider.uploaded-file-name=The file name of the provider service jar to be added or updated.
|
||||
keycloak.auth-server.add-provider.bytes-to-upload=The bytes of the provider service jar to be added or updated.
|
||||
keycloak.auth-server.add-provider.redeploy=Redeploy the auth server after adding the provider. Ignored if auth server is disabled.
|
||||
keycloak.auth-server.add-provider.overwrite=Overwrite even if the uploaded-file-name already exists as an overlay.
|
||||
keycloak.auth-server.list-overlays=List the overlays uploaded for this auth server.
|
||||
keycloak.auth-server.remove-overlay=Remove a provider jar, theme jar, or keycloak-server.json that has been uploaded to the auth server.
|
||||
keycloak.auth-server.remove-overlay.overlay-file-path=The uploaded path and file name of the overlay to be removed.
|
||||
keycloak.auth-server.remove-overlay.redeploy=Redeploy the auth server after removing the overlay.
|
||||
keycloak.auth-server.update-server-config=Upload a new keycloak-server.json configuration file for the Keycloak auth server.
|
||||
keycloak.auth-server.update-server-config.uploaded-file-name=Should be the name keycloak-server.json.
|
||||
keycloak.auth-server.update-server-config.bytes-to-upload=The bytes of the keycloak-server.json file to be added or updated.
|
||||
keycloak.auth-server.update-server-config.redeploy=Redeploy the auth server after updating the server config.
|
||||
keycloak.auth-server.update-server-config.overwrite=Overwrite even if keycloak-server.json already exitss as an overlay.
|
||||
keycloak.auth-server.enabled=Enable or disable the Auth Server.
|
||||
keycloak.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment.
|
||||
|
||||
|
|
7
pom.xml
|
@ -36,7 +36,7 @@
|
|||
<slf4j.version>1.5.10</slf4j.version>
|
||||
<jboss.version>7.1.1.Final</jboss.version>
|
||||
<wildfly.version>8.1.0.Final</wildfly.version>
|
||||
<wildfly.core.version>1.0.0.Alpha9</wildfly.core.version>
|
||||
<wildfly.core.version>1.0.0.Alpha12</wildfly.core.version>
|
||||
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
||||
<google.zxing.version>2.2</google.zxing.version>
|
||||
<google.client.version>1.14.1-beta</google.client.version>
|
||||
|
@ -470,6 +470,11 @@
|
|||
<type>pom</type>
|
||||
<version>${wildfly.core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.core</groupId>
|
||||
<artifactId>wildfly-cli</artifactId>
|
||||
<version>${wildfly.core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.core</groupId>
|
||||
<artifactId>wildfly-core-feature-pack</artifactId>
|
||||
|
|