KEYCLOAK-4210: Added Fuse admin tests
This commit is contained in:
parent
c4cce147e2
commit
3d9f11168e
17 changed files with 589 additions and 11 deletions
|
@ -23,7 +23,7 @@ do
|
|||
fi
|
||||
|
||||
if "$UPDATE_CONFIG" == "true"; then
|
||||
echo "Updating Config - org.ops4j.pax.url.mvn"
|
||||
echo "Updating Config"
|
||||
./client $CLIENT_AUTH -f update-config.cli
|
||||
if [ $? -ne 0 ]; then
|
||||
RESULT=1;
|
||||
|
@ -36,6 +36,14 @@ do
|
|||
./client $CLIENT_AUTH -f install-features.cli
|
||||
if [ $? -ne 0 ]; then RESULT=1; fi
|
||||
|
||||
if "$UPDATE_CONFIG" == "true"; then
|
||||
echo "Updating Config - Keycloak authentication"
|
||||
./client $CLIENT_AUTH -f update-config-auth.cli
|
||||
if [ $? -ne 0 ]; then
|
||||
RESULT=1;
|
||||
fi
|
||||
fi
|
||||
|
||||
./stop
|
||||
rm -rf ../data/log
|
||||
rm -rf ../data/tmp
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<properties>
|
||||
<app.server.karaf>fuse63</app.server.karaf>
|
||||
<app.server.karaf.groupId>org.jboss.fuse</app.server.karaf.groupId>
|
||||
<app.server.karaf.artifactId>jboss-fuse-full</app.server.karaf.artifactId>
|
||||
<app.server.karaf.artifactId>jboss-fuse-karaf</app.server.karaf.artifactId>
|
||||
<app.server.karaf.version>${fuse63.version}</app.server.karaf.version>
|
||||
<app.server.karaf.unpacked.folder.name>jboss-fuse-${fuse63.version}</app.server.karaf.unpacked.folder.name>
|
||||
<app.server.karaf.client.auth>-u admin -p admin</app.server.karaf.client.auth>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "ssh-jmx-admin-client",
|
||||
"ssl-required" : "external",
|
||||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "hawtio-client",
|
||||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-required" : "external",
|
||||
"public-client" : true
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "jaas",
|
||||
"bearer-only" : true,
|
||||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-required" : "external",
|
||||
"use-resource-role-mappings": false,
|
||||
"principal-attribute": "preferred_username"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
config:edit org.apache.karaf.shell
|
||||
config:propset sshRealm keycloak
|
||||
config:update
|
||||
system-property -p hawtio.roles admin,user
|
||||
system-property -p hawtio.keycloakEnabled true
|
||||
system-property -p hawtio.realm keycloak
|
||||
system-property -p hawtio.keycloakClientConfig \$\{karaf.base\}/etc/keycloak-hawtio-client.json
|
||||
system-property -p hawtio.rolePrincipalClasses org.keycloak.adapters.jaas.RolePrincipal,org.apache.karaf.jaas.boot.principal.RolePrincipal
|
|
@ -3,3 +3,8 @@ config:propset org.ops4j.pax.url.mvn.localRepository ${maven.repo.local}
|
|||
config:propset org.ops4j.pax.url.mvn.settings ${maven.local.settings}
|
||||
config:propappend org.ops4j.pax.url.mvn.repositories ${repositories}
|
||||
config:update
|
||||
config:edit jmx.acl.org.apache.karaf.security.jmx
|
||||
config:propappend list* viewer
|
||||
config:propappend set* jmxAdmin
|
||||
config:propappend * jmxAdmin,admin
|
||||
config:update
|
|
@ -117,6 +117,7 @@
|
|||
<includes>
|
||||
<include>install-features.cli</include>
|
||||
<include>update-config.cli</include>
|
||||
<include>update-config-auth.cli</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
|
@ -124,7 +125,7 @@
|
|||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-users-properties</id>
|
||||
<id>copy-configs</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
|
@ -137,6 +138,9 @@
|
|||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>users.properties</include>
|
||||
<include>keycloak-direct-access.json</include>
|
||||
<include>keycloak-hawtio-client.json</include>
|
||||
<include>keycloak-hawtio.json</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
|
|
@ -81,6 +81,26 @@
|
|||
<artifactId>greenmail</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.arquillian.container</groupId>
|
||||
<artifactId>arquillian-container-karaf-managed</artifactId>
|
||||
<version>2.1.0.CR18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.arquillian.container</groupId>
|
||||
<artifactId>arquillian-container-osgi</artifactId>
|
||||
<version>2.1.0.CR18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.enterprise</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
|
||||
import org.jboss.arquillian.container.test.impl.enricher.resource.URLResourceProvider;
|
||||
import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
|
||||
import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator;
|
||||
|
@ -26,6 +27,7 @@ import org.jboss.arquillian.graphene.location.CustomizableURLResourceProvider;
|
|||
import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
|
||||
import org.jboss.arquillian.test.spi.execution.TestExecutionDecider;
|
||||
import org.keycloak.testsuite.arquillian.h2.H2TestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.karaf.CustomKarafContainer;
|
||||
import org.keycloak.testsuite.arquillian.migration.MigrationTestExecutionDecider;
|
||||
import org.keycloak.testsuite.arquillian.provider.AdminClientProvider;
|
||||
import org.keycloak.testsuite.arquillian.provider.OAuthClientProvider;
|
||||
|
@ -51,10 +53,10 @@ public class KeycloakArquillianExtension implements LoadableExtension {
|
|||
builder
|
||||
.service(DeploymentScenarioGenerator.class, DeploymentTargetModifier.class)
|
||||
.service(ApplicationArchiveProcessor.class, DeploymentArchiveProcessor.class)
|
||||
.service(DeployableContainer.class, CustomKarafContainer.class)
|
||||
.observer(AuthServerTestEnricher.class)
|
||||
.observer(AppServerTestEnricher.class)
|
||||
.observer(H2TestEnricher.class);
|
||||
|
||||
builder
|
||||
.service(TestExecutionDecider.class, MigrationTestExecutionDecider.class);
|
||||
|
||||
|
|
|
@ -0,0 +1,231 @@
|
|||
package org.keycloak.testsuite.arquillian.karaf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.jboss.arquillian.container.osgi.jmx.JMXDeployableContainer;
|
||||
import org.jboss.arquillian.container.osgi.jmx.ObjectNameFactory;
|
||||
import org.jboss.arquillian.container.osgi.karaf.managed.KarafManagedContainerConfiguration;
|
||||
import org.jboss.arquillian.container.spi.client.container.LifecycleException;
|
||||
import org.osgi.jmx.framework.BundleStateMBean;
|
||||
import org.osgi.jmx.framework.FrameworkMBean;
|
||||
import org.osgi.jmx.framework.ServiceStateMBean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* KarafManagedDeployableContainer
|
||||
*
|
||||
* @author thomas.diesler@jboss.com
|
||||
*/
|
||||
public class CustomKarafContainer<T extends KarafManagedContainerConfiguration> extends JMXDeployableContainer<T> {
|
||||
|
||||
static final Logger _logger = LoggerFactory.getLogger(CustomKarafContainer.class.getPackage().getName());
|
||||
|
||||
private KarafManagedContainerConfiguration config;
|
||||
private Process process;
|
||||
|
||||
@Override
|
||||
public Class<T> getConfigurationClass() {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> clazz = (Class<T>) KarafManagedContainerConfiguration.class;
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(T config) {
|
||||
super.setup(config);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws LifecycleException {
|
||||
|
||||
// Try to connect to an already running server
|
||||
MBeanServerConnection mbeanServer = null;
|
||||
try {
|
||||
mbeanServer = getMBeanServerConnection(500, TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (mbeanServer != null && !config.isAllowConnectingToRunningServer()) {
|
||||
throw new LifecycleException(
|
||||
"The server is already running! Managed containers does not support connecting to running server instances due to the " +
|
||||
"possible harmful effect of connecting to the wrong server. Please stop server before running or change to another type of container.\n" +
|
||||
"To disable this check and allow Arquillian to connect to a running server, set allowConnectingToRunningServer to true in the container configuration");
|
||||
}
|
||||
|
||||
// Start the Karaf process
|
||||
if (mbeanServer == null) {
|
||||
String karafHome = config.getKarafHome();
|
||||
if (karafHome == null)
|
||||
throw new IllegalStateException("karafHome cannot be null");
|
||||
|
||||
File karafHomeDir = new File(karafHome).getAbsoluteFile();
|
||||
if (!karafHomeDir.isDirectory())
|
||||
throw new IllegalStateException("Not a valid Karaf home dir: " + karafHomeDir);
|
||||
|
||||
String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
|
||||
_logger.info(String.format("Using java: %s", java));
|
||||
|
||||
List<String> cmd = new ArrayList<String>();
|
||||
cmd.add(java);
|
||||
|
||||
// JavaVM args
|
||||
String javaArgs = config.getJavaVmArguments();
|
||||
if (!javaArgs.contains("-Xmx")) {
|
||||
javaArgs = KarafManagedContainerConfiguration.DEFAULT_JAVAVM_ARGUMENTS + " " + javaArgs;
|
||||
}
|
||||
cmd.addAll(Arrays.asList(javaArgs.split("\\s")));
|
||||
|
||||
// Karaf properties
|
||||
cmd.add("-Dkaraf.home=" + karafHomeDir);
|
||||
cmd.add("-Dkaraf.base=" + karafHomeDir);
|
||||
cmd.add("-Dkaraf.etc=" + karafHomeDir + "/etc");
|
||||
cmd.add("-Dkaraf.data=" + karafHomeDir + "/data");
|
||||
cmd.add("-Dkaraf.instances=" + karafHomeDir + "/instances");
|
||||
cmd.add("-Dkaraf.startLocalConsole=false");
|
||||
cmd.add("-Dkaraf.startRemoteShell=true");
|
||||
|
||||
// Java properties
|
||||
cmd.add("-Djava.io.tmpdir=" + new File(karafHomeDir, "data/tmp"));
|
||||
cmd.add("-Djava.util.logging.config.file=" + new File(karafHomeDir, "etc/java.util.logging.properties"));
|
||||
cmd.add("-Djava.endorsed.dirs=" + new File(karafHomeDir, "lib/endorsed"));
|
||||
|
||||
// Classpath
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
File karafLibDir = new File(karafHomeDir, "lib");
|
||||
String[] libs = karafLibDir.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.startsWith("karaf");
|
||||
}
|
||||
});
|
||||
for (String lib : libs) {
|
||||
String separator = classPath.length() > 0 ? File.pathSeparator : "";
|
||||
classPath.append(separator).append(new File(karafHomeDir, "lib/" + lib));
|
||||
}
|
||||
cmd.add("-classpath");
|
||||
cmd.add(classPath.toString());
|
||||
|
||||
// Main class
|
||||
cmd.add("org.apache.karaf.main.Main");
|
||||
|
||||
// Output the startup command
|
||||
StringBuffer cmdstr = new StringBuffer();
|
||||
for (String tok : cmd) {
|
||||
cmdstr.append(tok).append(" ");
|
||||
}
|
||||
_logger.debug("Starting Karaf with: {}", cmdstr);
|
||||
|
||||
try {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
|
||||
processBuilder.directory(karafHomeDir);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
process = processBuilder.start();
|
||||
new Thread(new ConsoleConsumer()).start();
|
||||
} catch (Exception ex) {
|
||||
throw new LifecycleException("Cannot start managed Karaf container", ex);
|
||||
}
|
||||
|
||||
// Get the MBeanServerConnection
|
||||
try {
|
||||
mbeanServer = getMBeanServerConnection(30, TimeUnit.SECONDS);
|
||||
} catch (Exception ex) {
|
||||
destroyKarafProcess();
|
||||
throw new LifecycleException("Cannot obtain MBean server connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
mbeanServerInstance.set(mbeanServer);
|
||||
|
||||
try {
|
||||
// Get the FrameworkMBean
|
||||
ObjectName oname = ObjectNameFactory.create("osgi.core:type=framework,*");
|
||||
frameworkMBean = getMBeanProxy(mbeanServer, oname, FrameworkMBean.class, 30, TimeUnit.SECONDS);
|
||||
|
||||
// Get the BundleStateMBean
|
||||
oname = ObjectNameFactory.create("osgi.core:type=bundleState,*");
|
||||
bundleStateMBean = getMBeanProxy(mbeanServer, oname, BundleStateMBean.class, 30, TimeUnit.SECONDS);
|
||||
|
||||
// Get the BundleStateMBean
|
||||
oname = ObjectNameFactory.create("osgi.core:type=serviceState,*");
|
||||
serviceStateMBean = getMBeanProxy(mbeanServer, oname, ServiceStateMBean.class, 30, TimeUnit.SECONDS);
|
||||
|
||||
// Install the arquillian bundle to become active
|
||||
installArquillianBundle();
|
||||
|
||||
// Await the arquillian bundle to become active
|
||||
awaitArquillianBundleActive(30, TimeUnit.SECONDS);
|
||||
|
||||
// Await the beginning start level
|
||||
Integer beginningStartLevel = config.getKarafBeginningStartLevel();
|
||||
if (beginningStartLevel != null)
|
||||
awaitBeginningStartLevel(beginningStartLevel, 30, TimeUnit.SECONDS);
|
||||
|
||||
// Await bootsrap complete services
|
||||
awaitBootstrapCompleteServices();
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
destroyKarafProcess();
|
||||
throw rte;
|
||||
} catch (Exception ex) {
|
||||
destroyKarafProcess();
|
||||
throw new LifecycleException("Cannot start Karaf container", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws LifecycleException {
|
||||
super.stop();
|
||||
destroyKarafProcess();
|
||||
}
|
||||
|
||||
private void destroyKarafProcess() throws LifecycleException {
|
||||
if (process != null) {
|
||||
process.destroy();
|
||||
try {
|
||||
process.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
throw new LifecycleException("Cannot start Karaf container", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable that consumes the output of the process. If nothing consumes the output the AS will hang on some platforms
|
||||
*
|
||||
* @author Stuart Douglas
|
||||
*/
|
||||
private class ConsoleConsumer implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final InputStream stream = process.getInputStream();
|
||||
final boolean writeOutput = config.isOutputToConsole();
|
||||
try {
|
||||
byte[] buf = new byte[32];
|
||||
int num;
|
||||
// Do not try reading a line cos it considers '\r' end of line
|
||||
while ((num = stream.read(buf)) != -1) {
|
||||
if (writeOutput)
|
||||
System.out.write(buf, 0, num);
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
package org.keycloak.testsuite.adapter.example;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
|
||||
import static org.keycloak.testsuite.util.IOUtil.loadRealm;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.apache.sshd.client.SshClient;
|
||||
import org.apache.sshd.client.channel.ClientChannel;
|
||||
import org.apache.sshd.client.channel.ClientChannelEvent;
|
||||
import org.apache.sshd.client.future.ConnectFuture;
|
||||
import org.apache.sshd.client.session.ClientSession;
|
||||
import org.apache.sshd.client.session.ClientSession.ClientSessionEvent;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.page.HawtioPage;
|
||||
|
||||
public abstract class AbstractFuseAdminAdapterTest extends AbstractExampleAdapterTest {
|
||||
|
||||
@Page
|
||||
private HawtioPage hawtioPage;
|
||||
|
||||
private SshClient client;
|
||||
|
||||
private ClientChannel channel;
|
||||
|
||||
private ClientSession session;
|
||||
|
||||
enum Result { OK, NOT_FOUND, NO_CREDENTIALS, NO_ROLES };
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation fuseRealm = loadRealm(new File(EXAMPLES_HOME_DIR + "/fuse/demorealm.json"));
|
||||
testRealms.add(fuseRealm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
testRealmPage.setAuthRealm(DEMO);
|
||||
testRealmLoginPage.setAuthRealm(DEMO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hawtioLoginTest() throws Exception {
|
||||
hawtioPage.navigateTo();
|
||||
testRealmLoginPage.form().login("user", "invalid-password");
|
||||
assertCurrentUrlDoesntStartWith(hawtioPage);
|
||||
|
||||
testRealmLoginPage.form().login("invalid-user", "password");
|
||||
assertCurrentUrlDoesntStartWith(hawtioPage);
|
||||
|
||||
testRealmLoginPage.form().login("root", "password");
|
||||
assertCurrentUrlStartsWith(hawtioPage.getDriver(), hawtioPage.toString() + "/welcome");
|
||||
hawtioPage.logout();
|
||||
assertCurrentUrlStartsWith(testRealmLoginPage);
|
||||
|
||||
hawtioPage.navigateTo();
|
||||
testRealmLoginPage.form().login("mary", "password");
|
||||
assertTrue(!driver.getPageSource().contains("welcome"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void sshLoginTest() throws Exception {
|
||||
assertCommand("mary", "password", "shell:date", Result.NO_ROLES);
|
||||
assertCommand("john", "password", "shell:info", Result.NO_CREDENTIALS);
|
||||
assertCommand("john", "password", "shell:date", Result.OK);
|
||||
assertCommand("root", "password", "shell:info", Result.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jmxLoginTest() throws Exception {
|
||||
setJMXAuthentication("keycloak", "password");
|
||||
ObjectName mbean = new ObjectName("org.apache.karaf:type=config,name=root");
|
||||
//invalid credentials
|
||||
try {
|
||||
getJMXConnector("mary", "password1").getMBeanServerConnection();
|
||||
Assert.fail();
|
||||
} catch (SecurityException se) {}
|
||||
//no role
|
||||
MBeanServerConnection connection = getJMXConnector("mary", "password").getMBeanServerConnection();
|
||||
assertJmxInvoke(false, connection, mbean, "listProperties", new Object [] {""}, new String [] {String.class.getName()});
|
||||
assertJmxInvoke(false, connection, mbean, "setProperty", new Object [] {"", "x", "y"}, new String [] {String.class.getName(), String.class.getName(), String.class.getName()});
|
||||
//read only role
|
||||
connection = getJMXConnector("john", "password").getMBeanServerConnection();
|
||||
assertJmxInvoke(true, connection, mbean, "listProperties", new Object [] {""}, new String [] {String.class.getName()});
|
||||
assertJmxInvoke(false, connection, mbean, "setProperty", new Object [] {"", "x", "y"}, new String [] {String.class.getName(), String.class.getName(), String.class.getName()});
|
||||
//read write role
|
||||
connection = getJMXConnector("root", "password").getMBeanServerConnection();
|
||||
assertJmxInvoke(true, connection, mbean, "listProperties", new Object [] {""}, new String [] {String.class.getName()});
|
||||
assertJmxInvoke(true, connection, mbean, "setProperty", new Object [] {"", "x", "y"}, new String [] {String.class.getName(), String.class.getName(), String.class.getName()});
|
||||
setJMXAuthentication("karaf", "admin");
|
||||
}
|
||||
|
||||
private String assertCommand(String user, String password, String command, Result result) throws Exception, IOException {
|
||||
if (!command.endsWith("\n"))
|
||||
command += "\n";
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutputStream pipe = openSshChannel(user, password, out, out);
|
||||
pipe.write(command.getBytes());
|
||||
pipe.flush();
|
||||
|
||||
closeSshChannel(pipe);
|
||||
String output = new String(out.toByteArray());
|
||||
|
||||
switch(result) {
|
||||
case OK:
|
||||
Assert.assertFalse("Should not contain 'Insufficient credentials' or 'Command not found': " + output,
|
||||
output.contains("Insufficient credentials") || output.contains("Command not found"));
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
Assert.assertTrue("Should contain 'Command not found': " + output,
|
||||
output.contains("Command not found"));
|
||||
break;
|
||||
case NO_CREDENTIALS:
|
||||
Assert.assertTrue("Should contain 'Insufficient credentials': " + output,
|
||||
output.contains("Insufficient credentials"));
|
||||
break;
|
||||
case NO_ROLES:
|
||||
Assert.assertTrue("Should contain 'Current user has no associated roles': " + output,
|
||||
output.contains("Current user has no associated roles"));
|
||||
break;
|
||||
default:
|
||||
Assert.fail("Unexpected enum value: " + result);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
private OutputStream openSshChannel(String username, String password, OutputStream ... outputs) throws Exception {
|
||||
client = SshClient.setUpDefaultClient();
|
||||
client.start();
|
||||
ConnectFuture future = client.connect(username, "localhost", 8101);
|
||||
future.await();
|
||||
session = future.getSession();
|
||||
|
||||
Set<ClientSessionEvent> ret = EnumSet.of(ClientSessionEvent.WAIT_AUTH);
|
||||
while (ret.contains(ClientSessionEvent.WAIT_AUTH)) {
|
||||
session.addPasswordIdentity(password);
|
||||
session.auth().verify();
|
||||
ret = session.waitFor(EnumSet.of(ClientSessionEvent.WAIT_AUTH, ClientSessionEvent.CLOSED, ClientSessionEvent.AUTHED), 0);
|
||||
}
|
||||
if (ret.contains(ClientSessionEvent.CLOSED)) {
|
||||
throw new Exception("Could not open SSH channel");
|
||||
}
|
||||
channel = session.createChannel("shell");
|
||||
PipedOutputStream pipe = new PipedOutputStream();
|
||||
channel.setIn(new PipedInputStream(pipe));
|
||||
|
||||
OutputStream out;
|
||||
if (outputs.length >= 1) {
|
||||
out = outputs[0];
|
||||
} else {
|
||||
out = new ByteArrayOutputStream();
|
||||
}
|
||||
channel.setOut(out);
|
||||
|
||||
OutputStream err;
|
||||
if (outputs.length >= 2) {
|
||||
err = outputs[1];
|
||||
} else {
|
||||
err = new ByteArrayOutputStream();
|
||||
}
|
||||
channel.setErr(err);
|
||||
channel.open();
|
||||
|
||||
return pipe;
|
||||
}
|
||||
|
||||
private void setJMXAuthentication(String realm, String password) throws Exception {
|
||||
assertCommand("admin", "password", "config:edit org.apache.karaf.management; config:propset jmxRealm " + realm + "; config:update", Result.OK);
|
||||
getMBeanServerConnection(10000, TimeUnit.MILLISECONDS, "admin", password);
|
||||
}
|
||||
|
||||
private void closeSshChannel(OutputStream pipe) throws IOException {
|
||||
pipe.write("logout\n".getBytes());
|
||||
pipe.flush();
|
||||
|
||||
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
|
||||
session.close(true);
|
||||
client.stop();
|
||||
|
||||
client = null;
|
||||
channel = null;
|
||||
session = null;
|
||||
}
|
||||
|
||||
private Object assertJmxInvoke(boolean expectSuccess, MBeanServerConnection connection, ObjectName mbean, String method,
|
||||
Object[] params, String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException {
|
||||
try {
|
||||
Object result = connection.invoke(mbean, method, params, signature);
|
||||
assertTrue(expectSuccess);
|
||||
return result;
|
||||
} catch (SecurityException se) {
|
||||
assertTrue(!expectSuccess);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private MBeanServerConnection getMBeanServerConnection(long timeout, final TimeUnit unit, String username, String password) throws Exception {
|
||||
Exception lastException = null;
|
||||
long timeoutMillis = System.currentTimeMillis() + unit.toMillis(timeout);
|
||||
while (System.currentTimeMillis() < timeoutMillis) {
|
||||
try {
|
||||
return getJMXConnector(username, password).getMBeanServerConnection();
|
||||
} catch (Exception ex) {
|
||||
lastException = ex;
|
||||
Thread.sleep(500);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
TimeoutException timeoutException = new TimeoutException();
|
||||
timeoutException.initCause(lastException);
|
||||
throw timeoutException;
|
||||
}
|
||||
|
||||
private JMXConnector getJMXConnector(String userName, String password) throws Exception {
|
||||
JMXServiceURL url = new JMXServiceURL(getJmxServiceUrl());
|
||||
String[] credentials = new String[] { userName, password };
|
||||
Map<String, ?> env = Collections.singletonMap(JMXConnector.CREDENTIALS, credentials);
|
||||
JMXConnector connector = JMXConnectorFactory.connect(url, env);
|
||||
return connector;
|
||||
}
|
||||
|
||||
private String getJmxServiceUrl() throws Exception {
|
||||
return "service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root";
|
||||
}
|
||||
|
||||
}
|
|
@ -59,7 +59,7 @@ public abstract class AbstractFuseExampleAdapterTest extends AbstractExampleAdap
|
|||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation fuseRealm = loadRealm(new File(EXAMPLES_HOME_DIR + "/fuse/testrealm.json"));
|
||||
RealmRepresentation fuseRealm = loadRealm(new File(EXAMPLES_HOME_DIR + "/fuse/demorealm.json"));
|
||||
testRealms.add(fuseRealm);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,21 +31,19 @@
|
|||
<container qualifier="app-server-${{app.server}}" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">true</property>
|
||||
<property name="adapterImplClass">org.jboss.arquillian.container.osgi.karaf.managed.KarafManagedDeployableContainer</property>
|
||||
<!--<property name="adapterImplClass">org.keycloak.testsuite.arquillian.karaf.CustomKarafContainer</property>-->
|
||||
<!-- <property name="adapterImplClass">org.jboss.arquillian.container.osgi.karaf.managed.KarafManagedDeployableContainer</property> -->
|
||||
<property name="adapterImplClass">org.keycloak.testsuite.arquillian.karaf.CustomKarafContainer</property>
|
||||
<property name="autostartBundle">false</property>
|
||||
<property name="karafHome">${app.server.home}</property>
|
||||
<property name="javaHome">${app.server.java.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n
|
||||
${adapter.test.props}
|
||||
</property>
|
||||
<property name="jmxServiceURL">service:jmx:rmi://127.0.0.1:44444/jndi/rmi://127.0.0.1:1099/karaf-root</property>
|
||||
<property name="jmxUsername">${app.server.management.user}</property>
|
||||
<property name="jmxPassword">${app.server.management.password}</property>
|
||||
<property name="jmxPassword">${app.server.management.password}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package org.keycloak.testsuite.adapter.example;
|
||||
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
|
||||
@AppServerContainer("app-server-fuse63")
|
||||
public class Fuse63AdminAdapterTest extends AbstractFuseAdminAdapterTest {
|
||||
|
||||
}
|
|
@ -86,7 +86,12 @@
|
|||
<groupId>org.apache.karaf</groupId>
|
||||
<artifactId>org.apache.karaf.client</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.sshd</groupId>
|
||||
<artifactId>sshd-core</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -719,6 +719,12 @@
|
|||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.sshd</groupId>
|
||||
<artifactId>sshd-core</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Email Test Server -->
|
||||
<dependency>
|
||||
<groupId>com.icegreen</groupId>
|
||||
|
|
Loading…
Reference in a new issue