Old experiment with keycloak-server.json embedded into standalone.xml
This commit is contained in:
parent
875e9ba513
commit
4776582a6a
18 changed files with 768 additions and 17 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -9,10 +9,11 @@
|
||||||
.settings
|
.settings
|
||||||
.classpath
|
.classpath
|
||||||
|
|
||||||
|
|
||||||
# NetBeans #
|
# NetBeans #
|
||||||
############
|
############
|
||||||
|
nbactions.xml
|
||||||
nb-configuration.xml
|
nb-configuration.xml
|
||||||
|
catalog.xml
|
||||||
|
|
||||||
# Compiled source #
|
# Compiled source #
|
||||||
###################
|
###################
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
<module name="javax.api"/>
|
<module name="javax.api"/>
|
||||||
<module name="org.jboss.staxmapper"/>
|
<module name="org.jboss.staxmapper"/>
|
||||||
<module name="org.jboss.as.controller"/>
|
<module name="org.jboss.as.controller"/>
|
||||||
|
<module name="org.jboss.as.ee"/>
|
||||||
<module name="org.jboss.as.server"/>
|
<module name="org.jboss.as.server"/>
|
||||||
<module name="org.jboss.modules"/>
|
<module name="org.jboss.modules"/>
|
||||||
<module name="org.jboss.msc"/>
|
<module name="org.jboss.msc"/>
|
||||||
|
|
|
@ -42,11 +42,9 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>2.8.1</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<redirectTestOutputToFile>false</redirectTestOutputToFile>
|
<redirectTestOutputToFile>false</redirectTestOutputToFile>
|
||||||
<enableAssertions>true</enableAssertions>
|
<enableAssertions>true</enableAssertions>
|
||||||
<argLine>-Xmx512m</argLine>
|
|
||||||
<systemProperties>
|
<systemProperties>
|
||||||
<property>
|
<property>
|
||||||
<name>jboss.home</name>
|
<name>jboss.home</name>
|
||||||
|
@ -56,9 +54,34 @@
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*TestCase.java</include>
|
<include>**/*TestCase.java</include>
|
||||||
</includes>
|
</includes>
|
||||||
<forkMode>once</forkMode>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>war</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<outputDirectory>${project.build.directory}/classes/deployments</outputDirectory>
|
||||||
|
<destFileName>auth-server.war</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.keycloak.subsystem.logging.KeycloakLogger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.jboss.as.ee.component.EEModuleDescription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass authentication data (keycloak.json) as a servlet context param so it can be read by the KeycloakServletExtension.
|
* Pass authentication data (keycloak.json) as a servlet context param so it can be read by the KeycloakServletExtension.
|
||||||
|
@ -45,9 +46,9 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||||
// two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
|
// two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
|
||||||
public static final String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
|
public static final String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
|
||||||
|
|
||||||
public static final Phase PHASE = Phase.INSTALL;
|
public static final Phase PHASE = Phase.POST_MODULE;
|
||||||
// Seems wise to have this run after INSTALL_WAR_DEPLOYMENT
|
// This needs to run just before bean validator factory
|
||||||
public static final int PRIORITY = Phase.INSTALL_WAR_DEPLOYMENT - 1;
|
public static final int PRIORITY = Phase.POST_MODULE_VALIDATOR_FACTORY - 1;
|
||||||
|
|
||||||
// not sure if we need this yet, keeping here just in case
|
// not sure if we need this yet, keeping here just in case
|
||||||
protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) {
|
protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) {
|
||||||
|
@ -73,6 +74,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||||
|
|
||||||
String deploymentName = deploymentUnit.getName();
|
String deploymentName = deploymentUnit.getName();
|
||||||
|
System.out.println(">>>>> deploymentName=" + deploymentName);
|
||||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
|
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
|
||||||
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName);
|
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName);
|
||||||
if (service.isKeycloakDeployment(deploymentName)) {
|
if (service.isKeycloakDeployment(deploymentName)) {
|
||||||
|
@ -99,6 +101,15 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||||
webMetaData = new JBossWebMetaData();
|
webMetaData = new JBossWebMetaData();
|
||||||
warMetaData.setMergedJBossWebMetaData(webMetaData);
|
warMetaData.setMergedJBossWebMetaData(webMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (service.isKeycloakServerDeployment(deploymentName)) {
|
||||||
|
final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
|
||||||
|
String webContext = service.getWebContext(deploymentName);
|
||||||
|
if (webContext == null) throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Auth Server");
|
||||||
|
description.setModuleName(webContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
||||||
if (loginConfig == null) {
|
if (loginConfig == null) {
|
||||||
loginConfig = new LoginConfigMetaData();
|
loginConfig = new LoginConfigMetaData();
|
||||||
|
|
|
@ -53,6 +53,11 @@ public final class KeycloakAdapterConfigService implements Service<KeycloakAdapt
|
||||||
private Map<String, ModelNode> realms = new HashMap<String, ModelNode>();
|
private Map<String, ModelNode> realms = new HashMap<String, ModelNode>();
|
||||||
private Map<String, ModelNode> deployments = new HashMap<String, ModelNode>();
|
private Map<String, ModelNode> deployments = new HashMap<String, ModelNode>();
|
||||||
|
|
||||||
|
// key=server deployment name; value=json
|
||||||
|
private Map<String, String> serverDeployments = new HashMap<String, String>();
|
||||||
|
// key=server deployment name; value=web-context
|
||||||
|
private Map<String, String> webContexts = new HashMap<String, String>();
|
||||||
|
|
||||||
private KeycloakAdapterConfigService() {
|
private KeycloakAdapterConfigService() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -72,6 +77,24 @@ public final class KeycloakAdapterConfigService implements Service<KeycloakAdapt
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addServerDeployment(String deploymentName, String json, String webContext) {
|
||||||
|
this.serverDeployments.put(deploymentName, json);
|
||||||
|
this.webContexts.put(deploymentName, webContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWebContext(String deploymentName) {
|
||||||
|
return webContexts.get(deploymentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeServerDeployment(String deploymentName) {
|
||||||
|
this.serverDeployments.remove(deploymentName);
|
||||||
|
this.webContexts.remove(deploymentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWebContextUsed(String webContext) {
|
||||||
|
return webContexts.containsValue(webContext);
|
||||||
|
}
|
||||||
|
|
||||||
public void addRealm(ModelNode operation, ModelNode model) {
|
public void addRealm(ModelNode operation, ModelNode model) {
|
||||||
this.realms.put(realmNameFromOp(operation), model.clone());
|
this.realms.put(realmNameFromOp(operation), model.clone());
|
||||||
}
|
}
|
||||||
|
@ -170,6 +193,10 @@ public final class KeycloakAdapterConfigService implements Service<KeycloakAdapt
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getJSON(String deploymentName) {
|
public String getJSON(String deploymentName) {
|
||||||
|
if (serverDeployments.containsKey(deploymentName)) {
|
||||||
|
return serverDeployments.get(deploymentName);
|
||||||
|
}
|
||||||
|
|
||||||
ModelNode deployment = this.deployments.get(deploymentName);
|
ModelNode deployment = this.deployments.get(deploymentName);
|
||||||
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||||
ModelNode realm = this.realms.get(realmName);
|
ModelNode realm = this.realms.get(realmName);
|
||||||
|
@ -196,7 +223,11 @@ public final class KeycloakAdapterConfigService implements Service<KeycloakAdapt
|
||||||
public boolean isKeycloakDeployment(String deploymentName) {
|
public boolean isKeycloakDeployment(String deploymentName) {
|
||||||
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: deployments.size()" + deployments.size());
|
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: deployments.size()" + deployments.size());
|
||||||
|
|
||||||
return this.deployments.containsKey(deploymentName);
|
return this.serverDeployments.containsKey(deploymentName) || this.deployments.containsKey(deploymentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isKeycloakServerDeployment(String deploymentName) {
|
||||||
|
return this.serverDeployments.containsKey(deploymentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static KeycloakAdapterConfigService find(ServiceRegistry registry) {
|
static KeycloakAdapterConfigService find(ServiceRegistry registry) {
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
|
|
||||||
package org.keycloak.subsystem.extension;
|
package org.keycloak.subsystem.extension;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import org.jboss.as.server.deployment.Attachments;
|
import org.jboss.as.server.deployment.Attachments;
|
||||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
|
@ -24,9 +28,14 @@ import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||||
import org.jboss.as.server.deployment.module.ModuleDependency;
|
import org.jboss.as.server.deployment.module.ModuleDependency;
|
||||||
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
||||||
|
import org.jboss.as.server.deployment.module.MountHandle;
|
||||||
|
import org.jboss.as.server.deployment.module.ResourceRoot;
|
||||||
|
import org.jboss.as.server.deployment.module.TempFileProviderService;
|
||||||
import org.jboss.modules.Module;
|
import org.jboss.modules.Module;
|
||||||
import org.jboss.modules.ModuleIdentifier;
|
import org.jboss.modules.ModuleIdentifier;
|
||||||
import org.jboss.modules.ModuleLoader;
|
import org.jboss.modules.ModuleLoader;
|
||||||
|
import org.jboss.vfs.VFS;
|
||||||
|
import org.jboss.vfs.VirtualFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -44,10 +53,39 @@ public class KeycloakDependencyProcessor implements DeploymentUnitProcessor {
|
||||||
@Override
|
@Override
|
||||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||||
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||||
addModules(deploymentUnit);
|
|
||||||
|
String deploymentName = deploymentUnit.getName();
|
||||||
|
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
|
||||||
|
|
||||||
|
if (service.isKeycloakDeployment(deploymentName)) {
|
||||||
|
addModules(deploymentUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ResourceRoot root : deploymentUnit.getAttachment(Attachments.RESOURCE_ROOTS)) {
|
||||||
|
System.out.println("*** resource root=" + root);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProvider(DeploymentUnit deploymentUnit) throws IOException, URISyntaxException {
|
||||||
|
System.out.println("#2");
|
||||||
|
deploymentUnit.addToAttachmentList(Attachments.RESOURCE_ROOTS, providerRoot());
|
||||||
|
System.out.println("#4");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResourceRoot providerRoot() throws IOException, URISyntaxException {
|
||||||
|
System.out.println("#3");
|
||||||
|
URI uri = new URI("file:/C:/GitHub/keycloak-temp/keycloak-appliance-dist-all-1.1.0-Alpha1-SNAPSHOT/keycloak/modules/system/layers/base/org/keycloak/keycloak-auth-server/main/./federation-properties-example.jar");
|
||||||
|
VirtualFile archive = VFS.getChild(uri);
|
||||||
|
Closeable closeable = VFS.mountZip(archive.getPhysicalFile(), archive, TempFileProviderService.provider());
|
||||||
|
return new ResourceRoot(archive.getName(), archive, new MountHandle(closeable));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addModules(DeploymentUnit deploymentUnit) {
|
private void addModules(DeploymentUnit deploymentUnit) {
|
||||||
|
System.out.println("**************************");
|
||||||
|
System.out.println("* Adding Keycloak dependencies to " + deploymentUnit.getName());
|
||||||
|
System.out.println("**************************");
|
||||||
final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
|
final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
|
||||||
final ModuleLoader moduleLoader = Module.getBootModuleLoader();
|
final ModuleLoader moduleLoader = Module.getBootModuleLoader();
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.extension;
|
package org.keycloak.subsystem.extension;
|
||||||
|
|
||||||
|
import org.keycloak.subsystem.extension.authserver.AuthServerDefinition;
|
||||||
import org.jboss.as.controller.Extension;
|
import org.jboss.as.controller.Extension;
|
||||||
import org.jboss.as.controller.ExtensionContext;
|
import org.jboss.as.controller.ExtensionContext;
|
||||||
import org.jboss.as.controller.PathElement;
|
import org.jboss.as.controller.PathElement;
|
||||||
|
@ -46,11 +47,12 @@ public class KeycloakExtension implements Extension {
|
||||||
private static final int MANAGEMENT_API_MICRO_VERSION = 0;
|
private static final int MANAGEMENT_API_MICRO_VERSION = 0;
|
||||||
protected static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
protected static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||||
private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
|
private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
|
||||||
|
static final AuthServerDefinition AUTH_SERVER_DEFINITION = new AuthServerDefinition();
|
||||||
static final RealmDefinition REALM_DEFINITION = new RealmDefinition();
|
static final RealmDefinition REALM_DEFINITION = new RealmDefinition();
|
||||||
static final SecureDeploymentDefinition SECURE_DEPLOYMENT_DEFINITION = new SecureDeploymentDefinition();
|
static final SecureDeploymentDefinition SECURE_DEPLOYMENT_DEFINITION = new SecureDeploymentDefinition();
|
||||||
static final CredentialDefinition CREDENTIAL_DEFINITION = new CredentialDefinition();
|
static final CredentialDefinition CREDENTIAL_DEFINITION = new CredentialDefinition();
|
||||||
|
|
||||||
static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||||
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
||||||
for (String kp : keyPrefix) {
|
for (String kp : keyPrefix) {
|
||||||
prefix.append('.').append(kp);
|
prefix.append('.').append(kp);
|
||||||
|
@ -76,7 +78,8 @@ public class KeycloakExtension implements Extension {
|
||||||
MANAGEMENT_API_MINOR_VERSION, MANAGEMENT_API_MICRO_VERSION);
|
MANAGEMENT_API_MINOR_VERSION, MANAGEMENT_API_MICRO_VERSION);
|
||||||
|
|
||||||
ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
|
||||||
ManagementResourceRegistration realmRegistration = registration.registerSubModel(REALM_DEFINITION);
|
registration.registerSubModel(AUTH_SERVER_DEFINITION);
|
||||||
|
registration.registerSubModel(REALM_DEFINITION);
|
||||||
ManagementResourceRegistration secureDeploymentRegistration = registration.registerSubModel(SECURE_DEPLOYMENT_DEFINITION);
|
ManagementResourceRegistration secureDeploymentRegistration = registration.registerSubModel(SECURE_DEPLOYMENT_DEFINITION);
|
||||||
secureDeploymentRegistration.registerSubModel(CREDENTIAL_DEFINITION);
|
secureDeploymentRegistration.registerSubModel(CREDENTIAL_DEFINITION);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.subsystem.extension;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.jboss.as.server.deployment.Attachments;
|
||||||
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
|
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||||
|
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
|
||||||
|
import org.jboss.as.server.deployment.module.ModuleDependency;
|
||||||
|
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
||||||
|
import org.jboss.as.server.deployment.module.MountHandle;
|
||||||
|
import org.jboss.as.server.deployment.module.ResourceRoot;
|
||||||
|
import org.jboss.as.server.deployment.module.TempFileProviderService;
|
||||||
|
import org.jboss.modules.Module;
|
||||||
|
import org.jboss.modules.ModuleIdentifier;
|
||||||
|
import org.jboss.modules.ModuleLoader;
|
||||||
|
import org.jboss.vfs.VFS;
|
||||||
|
import org.jboss.vfs.VirtualFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class KeycloakStructureProcessor implements DeploymentUnitProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||||
|
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||||
|
|
||||||
|
String deploymentName = deploymentUnit.getName();
|
||||||
|
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
|
||||||
|
|
||||||
|
System.out.println("#0");
|
||||||
|
if (service.isKeycloakServerDeployment(deploymentName)) {
|
||||||
|
try {
|
||||||
|
System.out.println("#1");
|
||||||
|
addProvider(deploymentUnit);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new DeploymentUnitProcessingException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProvider(DeploymentUnit deploymentUnit) throws IOException {
|
||||||
|
System.out.println("#2");
|
||||||
|
deploymentUnit.addToAttachmentList(Attachments.RESOURCE_ROOTS, providerRoot());
|
||||||
|
System.out.println("#4");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResourceRoot providerRoot() throws IOException {
|
||||||
|
System.out.println("#3");
|
||||||
|
VirtualFile archive = VFS.getChild("C:\\GitHub\\keycloak-temp\\keycloak-appliance-dist-all-1.1.0-Alpha1-SNAPSHOT\\keycloak\\modules\\system\\layers\\base\\org\\keycloak\\keycloak-auth-server\\main\\federation-properties-example.jar");
|
||||||
|
Closeable closeable = VFS.mountZip(archive.getPhysicalFile(), archive, TempFileProviderService.provider());
|
||||||
|
return new ResourceRoot(archive.getName(), archive, new MountHandle(closeable));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undeploy(DeploymentUnit du) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.extension;
|
package org.keycloak.subsystem.extension;
|
||||||
|
|
||||||
|
|
||||||
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
|
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
|
||||||
import org.jboss.as.controller.OperationContext;
|
import org.jboss.as.controller.OperationContext;
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
@ -27,6 +28,7 @@ import org.jboss.dmr.ModelNode;
|
||||||
import org.jboss.msc.service.ServiceController;
|
import org.jboss.msc.service.ServiceController;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.jboss.as.controller.registry.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Keycloak subsystem add update handler.
|
* The Keycloak subsystem add update handler.
|
||||||
|
@ -38,8 +40,10 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
|
||||||
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
|
static final KeycloakSubsystemAdd INSTANCE = new KeycloakSubsystemAdd();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
|
protected void populateModel(OperationContext context, ModelNode operation, Resource resource) throws OperationFailedException {
|
||||||
model.setEmptyObject();
|
resource.getModel().setEmptyObject();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,11 +51,12 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
|
||||||
context.addStep(new AbstractDeploymentChainStep() {
|
context.addStep(new AbstractDeploymentChainStep() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(DeploymentProcessorTarget processorTarget) {
|
protected void execute(DeploymentProcessorTarget processorTarget) {
|
||||||
|
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME, Phase.STRUCTURE, 0, new KeycloakStructureProcessor());
|
||||||
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME, Phase.DEPENDENCIES, 0, new KeycloakDependencyProcessor());
|
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME, Phase.DEPENDENCIES, 0, new KeycloakDependencyProcessor());
|
||||||
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME,
|
processorTarget.addDeploymentProcessor(KeycloakExtension.SUBSYSTEM_NAME,
|
||||||
KeycloakAdapterConfigDeploymentProcessor.PHASE,
|
KeycloakAdapterConfigDeploymentProcessor.PHASE,
|
||||||
KeycloakAdapterConfigDeploymentProcessor.PRIORITY,
|
KeycloakAdapterConfigDeploymentProcessor.PRIORITY,
|
||||||
new KeycloakAdapterConfigDeploymentProcessor());
|
new KeycloakAdapterConfigDeploymentProcessor());
|
||||||
}
|
}
|
||||||
}, OperationContext.Stage.RUNTIME);
|
}, OperationContext.Stage.RUNTIME);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.extension;
|
package org.keycloak.subsystem.extension;
|
||||||
|
|
||||||
|
import org.keycloak.subsystem.extension.authserver.AuthServerDefinition;
|
||||||
import org.jboss.as.controller.AttributeDefinition;
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
import org.jboss.as.controller.PathAddress;
|
import org.jboss.as.controller.PathAddress;
|
||||||
import org.jboss.as.controller.PathElement;
|
import org.jboss.as.controller.PathElement;
|
||||||
|
@ -58,6 +59,8 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
||||||
}
|
}
|
||||||
else if (reader.getLocalName().equals(SecureDeploymentDefinition.TAG_NAME)) {
|
else if (reader.getLocalName().equals(SecureDeploymentDefinition.TAG_NAME)) {
|
||||||
readDeployment(reader, list);
|
readDeployment(reader, list);
|
||||||
|
} else if (reader.getLocalName().equals(AuthServerDefinition.TAG_NAME)) {
|
||||||
|
readAuthServer(reader, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +70,24 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
||||||
return reader.nextTag();
|
return reader.nextTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readAuthServer(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
|
||||||
|
String authServerName = readNameAttribute(reader);
|
||||||
|
ModelNode addAuthServer = new ModelNode();
|
||||||
|
addAuthServer.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
|
||||||
|
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
|
||||||
|
PathElement.pathElement(AuthServerDefinition.TAG_NAME, authServerName));
|
||||||
|
addAuthServer.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
|
||||||
|
|
||||||
|
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
|
||||||
|
String tagName = reader.getLocalName();
|
||||||
|
SimpleAttributeDefinition def = AuthServerDefinition.lookup(tagName);
|
||||||
|
if (def == null) throw new XMLStreamException("Unknown auth-server tag " + tagName);
|
||||||
|
def.parseAndSetParameter(reader.getElementText(), addAuthServer, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.add(addAuthServer);
|
||||||
|
}
|
||||||
|
|
||||||
private void readRealm(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
|
private void readRealm(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
|
||||||
String realmName = readNameAttribute(reader);
|
String realmName = readNameAttribute(reader);
|
||||||
ModelNode addRealm = new ModelNode();
|
ModelNode addRealm = new ModelNode();
|
||||||
|
@ -157,11 +178,28 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
||||||
@Override
|
@Override
|
||||||
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
|
public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
|
||||||
context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
|
context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
|
||||||
|
writeAuthServers(writer, context);
|
||||||
writeRealms(writer, context);
|
writeRealms(writer, context);
|
||||||
writeSecureDeployments(writer, context);
|
writeSecureDeployments(writer, context);
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeAuthServers(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||||
|
if (!context.getModelNode().get(AuthServerDefinition.TAG_NAME).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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void writeRealms(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
private void writeRealms(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
|
||||||
if (!context.getModelNode().get(RealmDefinition.TAG_NAME).isDefined()) {
|
if (!context.getModelNode().get(RealmDefinition.TAG_NAME).isDefined()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.AbstractAddStepHandler;
|
||||||
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
|
import org.jboss.as.controller.OperationContext;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.ServiceVerificationHandler;
|
||||||
|
import org.jboss.dmr.ModelNode;
|
||||||
|
import org.jboss.msc.service.ServiceController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* String serverJsonAttrName = AuthServerDefinition.KEYCLOAK_SERVER_JSON.getName();
|
||||||
|
ModelNode keycloakServerJson = model.get(serverJsonAttrName);
|
||||||
|
if (!keycloakServerJson.isDefined()) {
|
||||||
|
model.get(serverJsonAttrName).set(AuthServerUtil.getDefaultAuthServerJson());
|
||||||
|
} */
|
||||||
|
|
||||||
|
System.out.println("**************************");
|
||||||
|
System.out.println("operation");
|
||||||
|
System.out.println(operation.toString());
|
||||||
|
System.out.println("**************************");
|
||||||
|
System.out.println("model");
|
||||||
|
System.out.println(model.toString());
|
||||||
|
System.out.println("**************************");
|
||||||
|
|
||||||
|
if (!requiresRuntime(context)) return; // not sure I really need this
|
||||||
|
|
||||||
|
ModelNode isEnabled = model.get("enabled");
|
||||||
|
if (!isEnabled.isDefined() || isEnabled.asBoolean()) {
|
||||||
|
String deploymentName = AuthServerUtil.addStepToStartAuthServer(context, operation);
|
||||||
|
//String json = model.get(serverJsonAttrName).asString();
|
||||||
|
ModelNode webContextNode = model.get(AuthServerDefinition.WEB_CONTEXT.getName());
|
||||||
|
if (!webContextNode.isDefined()) webContextNode = AuthServerDefinition.WEB_CONTEXT.getDefaultValue();
|
||||||
|
String webContext = webContextNode.asString();
|
||||||
|
KeycloakAdapterConfigService.INSTANCE.addServerDeployment(deploymentName, json, webContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
|
import org.jboss.as.controller.PathElement;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||||
|
import org.jboss.as.controller.SimpleResourceDefinition;
|
||||||
|
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
|
||||||
|
import org.jboss.as.controller.registry.ManagementResourceRegistration;
|
||||||
|
import org.jboss.dmr.ModelNode;
|
||||||
|
import org.jboss.dmr.ModelType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.operations.validation.ParameterValidator;
|
||||||
|
import org.jboss.as.controller.registry.OperationEntry;
|
||||||
|
import org.keycloak.subsystem.extension.KeycloakAdapterConfigService;
|
||||||
|
import org.keycloak.subsystem.extension.KeycloakExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines attributes and operations for an Auth Server
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class AuthServerDefinition extends SimpleResourceDefinition {
|
||||||
|
|
||||||
|
public static final String TAG_NAME = "auth-server";
|
||||||
|
|
||||||
|
protected static final SimpleAttributeDefinition ENABLED =
|
||||||
|
new SimpleAttributeDefinitionBuilder("enabled", ModelType.BOOLEAN, true)
|
||||||
|
.setXmlName("enabled")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode(true))
|
||||||
|
.setRestartAllServices()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
protected static final SimpleAttributeDefinition WEB_CONTEXT =
|
||||||
|
new SimpleAttributeDefinitionBuilder("web-context", ModelType.STRING, true)
|
||||||
|
.setXmlName("web-context")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode("auth"))
|
||||||
|
.setValidator(new WebContextValidator())
|
||||||
|
.setRestartAllServices()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/* protected static final SimpleAttributeDefinition KEYCLOAK_SERVER_JSON =
|
||||||
|
new SimpleAttributeDefinitionBuilder("keycloak-server-json", ModelType.STRING, true)
|
||||||
|
.setXmlName("keycloak-server-json")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setRestartAllServices()
|
||||||
|
.build(); */
|
||||||
|
|
||||||
|
public static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
|
static {
|
||||||
|
ALL_ATTRIBUTES.add(ENABLED);
|
||||||
|
ALL_ATTRIBUTES.add(WEB_CONTEXT);
|
||||||
|
//ALL_ATTRIBUTES.add(KEYCLOAK_SERVER_JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
|
||||||
|
AuthServerAddHandler.INSTANCE,
|
||||||
|
AuthServerRemoveHandler.INSTANCE,
|
||||||
|
null,
|
||||||
|
OperationEntry.Flag.RESTART_ALL_SERVICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
|
||||||
|
super.registerOperations(resourceRegistration);
|
||||||
|
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
|
||||||
|
super.registerAttributes(resourceRegistration);
|
||||||
|
for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
|
||||||
|
resourceRegistration.registerReadWriteAttribute(attrDef, null, attrHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SimpleAttributeDefinition lookup(String name) {
|
||||||
|
return DEFINITION_LOOKUP.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WebContextValidator implements ParameterValidator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateParameter(String paramName, ModelNode value) throws OperationFailedException {
|
||||||
|
String strValue = value.asString();
|
||||||
|
if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) {
|
||||||
|
throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateResolvedParameter(String paramName, ModelNode value) throws OperationFailedException {
|
||||||
|
String strValue = value.asString();
|
||||||
|
if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) {
|
||||||
|
throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
|
import org.jboss.as.controller.AbstractRemoveStepHandler;
|
||||||
|
import org.jboss.as.controller.OperationContext;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.operations.common.Util;
|
||||||
|
import org.jboss.dmr.ModelNode;
|
||||||
|
import org.keycloak.subsystem.extension.KeycloakAdapterConfigService;
|
||||||
|
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an auth-server from a realm.
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public final class AuthServerRemoveHandler extends AbstractRemoveStepHandler {
|
||||||
|
|
||||||
|
public static AuthServerRemoveHandler INSTANCE = new AuthServerRemoveHandler();
|
||||||
|
|
||||||
|
private AuthServerRemoveHandler() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
|
||||||
|
//KeycloakAdapterConfigService.INSTANCE.removeAuthServer()
|
||||||
|
System.out.println("*** performRuntime ** operation");
|
||||||
|
System.out.println(operation.toString());
|
||||||
|
System.out.println("*** performRuntime ** model");
|
||||||
|
System.out.println(model.toString());
|
||||||
|
String deploymentName = Util.getNameFromAddress(operation.get(ADDRESS));
|
||||||
|
System.out.println("*** authServerName=" + deploymentName);
|
||||||
|
if (!deploymentName.toLowerCase().endsWith(".war")) {
|
||||||
|
deploymentName += ".war";
|
||||||
|
}
|
||||||
|
KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarInputStream;
|
||||||
|
import org.jboss.as.controller.OperationContext;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.OperationStepHandler;
|
||||||
|
import org.jboss.as.controller.PathAddress;
|
||||||
|
import org.jboss.as.controller.PathElement;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PERSISTENT;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
|
||||||
|
import org.jboss.as.controller.operations.common.Util;
|
||||||
|
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
||||||
|
import org.jboss.dmr.ModelNode;
|
||||||
|
import org.jboss.modules.Module;
|
||||||
|
import org.jboss.modules.ModuleIdentifier;
|
||||||
|
import org.jboss.modules.ModuleLoadException;
|
||||||
|
import org.jboss.modules.Resource;
|
||||||
|
import org.jboss.modules.filter.PathFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class AuthServerUtil {
|
||||||
|
|
||||||
|
private static final ModuleIdentifier KEYCLOAK_SUBSYSTEM = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-subsystem");
|
||||||
|
|
||||||
|
private static URL authServerUrl = null;
|
||||||
|
|
||||||
|
private static String defaultAuthServerJson = "";
|
||||||
|
|
||||||
|
static String getDefaultAuthServerJson() {
|
||||||
|
if (authServerUrl == null) getWarUrl();
|
||||||
|
return defaultAuthServerJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can return the URL, null, or throw IllegalStateException
|
||||||
|
// This also finds the defaultAuthServerJson and sets the instance var for it.
|
||||||
|
private static URL getWarUrl() throws IllegalStateException {
|
||||||
|
if (authServerUrl != null) { // only need to find this once
|
||||||
|
return authServerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module module;
|
||||||
|
try {
|
||||||
|
module = Module.getModuleFromCallerModuleLoader(KEYCLOAK_AUTH_SERVER);
|
||||||
|
} catch (ModuleLoadException e) {
|
||||||
|
throw new IllegalStateException("Keycloak Auth Server not installed as a module.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
URL warUrl = null;
|
||||||
|
try {
|
||||||
|
java.util.Iterator<org.jboss.modules.Resource> rscIterator = module.iterateResources(new PathFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(String string) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// There should be only one war resource, the auth server
|
||||||
|
while (rscIterator.hasNext()) {
|
||||||
|
Resource rsc = rscIterator.next();
|
||||||
|
System.out.println("rsc.getName()=" + rsc.getName());
|
||||||
|
URL url = rsc.getURL();
|
||||||
|
if (url.toExternalForm().toLowerCase().endsWith(".war")) {
|
||||||
|
warUrl = url;
|
||||||
|
setDefaultAuthServerJson(rsc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ModuleLoadException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
authServerUrl = warUrl;
|
||||||
|
System.out.println("&&&&& authServerUrl=" + authServerUrl);
|
||||||
|
return authServerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return deploymentName this will be started under
|
||||||
|
static String addStepToStartAuthServer(OperationContext context, ModelNode operation) throws OperationFailedException {
|
||||||
|
|
||||||
|
PathAddress authServerAddr = PathAddress.pathAddress(operation.get(ADDRESS));
|
||||||
|
String deploymentName = authServerAddr.getElement(1).getValue();
|
||||||
|
if (!deploymentName.toLowerCase().endsWith(".war")) {
|
||||||
|
deploymentName += ".war";
|
||||||
|
}
|
||||||
|
|
||||||
|
PathAddress deploymentAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
|
||||||
|
ModelNode op = Util.createOperation(ADD, deploymentAddress);
|
||||||
|
op.get(ENABLED).set(true);
|
||||||
|
op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml
|
||||||
|
|
||||||
|
URL warUrl = null;
|
||||||
|
try {
|
||||||
|
warUrl = getWarUrl();
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
throw new OperationFailedException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warUrl == null) {
|
||||||
|
throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-auth-server module");
|
||||||
|
}
|
||||||
|
|
||||||
|
String urlString = warUrl.toExternalForm();
|
||||||
|
System.out.println(warUrl);
|
||||||
|
ModelNode contentItem = new ModelNode();
|
||||||
|
contentItem.get(URL).set(urlString);
|
||||||
|
op.get(CONTENT).add(contentItem);
|
||||||
|
System.out.println("****** operation ************");
|
||||||
|
System.out.println(op.toString());
|
||||||
|
ImmutableManagementResourceRegistration rootResourceRegistration = context.getRootResourceRegistration();
|
||||||
|
OperationStepHandler handler = rootResourceRegistration.getOperationHandler(deploymentAddress, ADD);
|
||||||
|
context.addStep(op, handler, OperationContext.Stage.MODEL);
|
||||||
|
|
||||||
|
return deploymentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setDefaultAuthServerJson(Resource rsc) throws IOException {
|
||||||
|
JarInputStream jarStream = null;
|
||||||
|
try {
|
||||||
|
jarStream = new JarInputStream(rsc.openStream());
|
||||||
|
JarEntry je;
|
||||||
|
while ((je = jarStream.getNextJarEntry()) != null) {
|
||||||
|
if (!je.getName().equals("WEB-INF/classes/META-INF/keycloak-server.json")) continue;
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
while ((len = jarStream.read(buffer)) != -1) {
|
||||||
|
baos.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultAuthServerJson = baos.toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
jarStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
|
import org.jboss.as.controller.AttributeDefinition;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an attribute on an Auth Server.
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class AuthServerWriteAttributeHandler extends ReloadRequiredWriteAttributeHandler {
|
||||||
|
|
||||||
|
public AuthServerWriteAttributeHandler(List<SimpleAttributeDefinition> definitions) {
|
||||||
|
this(definitions.toArray(new AttributeDefinition[definitions.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthServerWriteAttributeHandler(AttributeDefinition... definitions) {
|
||||||
|
super(definitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,18 @@
|
||||||
keycloak.subsystem=Keycloak subsystem
|
keycloak.subsystem=Keycloak subsystem
|
||||||
keycloak.subsystem.add=Operation Adds Keycloak subsystem
|
keycloak.subsystem.add=Operation Adds Keycloak subsystem
|
||||||
keycloak.subsystem.remove=Operation removes Keycloak subsystem
|
keycloak.subsystem.remove=Operation removes Keycloak subsystem
|
||||||
|
keycloak.subsystem.auth-server=Keycloak Auth Server
|
||||||
keycloak.subsystem.realm=A Keycloak realm.
|
keycloak.subsystem.realm=A Keycloak realm.
|
||||||
keycloak.subsystem.secure-deployment=A deployment secured by Keycloak.
|
keycloak.subsystem.secure-deployment=A deployment secured by Keycloak.
|
||||||
|
|
||||||
|
|
||||||
|
keycloak.auth-server=A Keycloak Auth Server
|
||||||
|
keycloak.auth-server.add=Add an Auth Server to the subsystem.
|
||||||
|
keycloak.auth-server.remove=Remove an Auth Server from the subsystem.
|
||||||
|
keycloak.auth-server.enabled=Enable or disable the Auth Server.
|
||||||
|
keycloak.auth-server.keycloak-server-json=Externalized version of keycloak-server.json
|
||||||
|
keycloak.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment.
|
||||||
|
|
||||||
keycloak.realm=A Keycloak realm.
|
keycloak.realm=A Keycloak realm.
|
||||||
keycloak.realm.add=Add a realm definition to the subsystem.
|
keycloak.realm.add=Add a realm definition to the subsystem.
|
||||||
keycloak.realm.remove=Remove a realm from the subsystem.
|
keycloak.realm.remove=Remove a realm from the subsystem.
|
||||||
|
|
5
pom.xml
5
pom.xml
|
@ -485,6 +485,11 @@
|
||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.8</version>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
|
|
@ -41,6 +41,7 @@ import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import org.keycloak.adapters.AdapterConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -57,7 +58,7 @@ public class KeycloakApplication extends Application {
|
||||||
protected String contextPath;
|
protected String contextPath;
|
||||||
|
|
||||||
public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) {
|
public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) {
|
||||||
loadConfig();
|
loadConfig(context);
|
||||||
|
|
||||||
this.sessionFactory = createSessionFactory();
|
this.sessionFactory = createSessionFactory();
|
||||||
|
|
||||||
|
@ -102,6 +103,26 @@ public class KeycloakApplication extends Application {
|
||||||
return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build();
|
return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void loadConfig(ServletContext context) {
|
||||||
|
String json = context.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||||
|
if (json == null) {
|
||||||
|
loadConfig(); // from file
|
||||||
|
} else {
|
||||||
|
loadConfig(json); // from ServletContext/Keycloak subsystem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void loadConfig(String json) {
|
||||||
|
try {
|
||||||
|
JsonNode node = new ObjectMapper().readTree(json);
|
||||||
|
Config.init(new JsonConfigProvider(node));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to load config", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Loaded config from Keycloak subsystem");
|
||||||
|
}
|
||||||
|
|
||||||
public static void loadConfig() {
|
public static void loadConfig() {
|
||||||
try {
|
try {
|
||||||
URL config = null;
|
URL config = null;
|
||||||
|
|
Loading…
Reference in a new issue