Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
0d20e3c7ff
35 changed files with 1141 additions and 253 deletions
|
@ -1,18 +1,5 @@
|
|||
package org.keycloak.connections.jpa;
|
||||
|
||||
import org.hibernate.ejb.AvailableSettings;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
|
||||
import org.keycloak.connections.jpa.util.JpaUtils;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.DriverManager;
|
||||
|
@ -22,10 +9,25 @@ import java.util.HashMap;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.ejb.AvailableSettings;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
|
||||
import org.keycloak.connections.jpa.util.JpaUtils;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
|
||||
public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory, ServerInfoAwareProviderFactory {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.keycloak.connections.jpa;
|
||||
|
||||
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory<JpaConnectionProvider> {
|
||||
public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package org.keycloak.connections.mongo;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientOptions;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
|
@ -15,18 +16,19 @@ import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocati
|
|||
import org.keycloak.connections.mongo.updater.MongoUpdaterProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientOptions;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
|
||||
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory, ServerInfoAwareProviderFactory {
|
||||
|
||||
// TODO Make it dynamic
|
||||
private String[] entities = new String[]{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package org.keycloak.connections.mongo;
|
||||
|
||||
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory<MongoConnectionProvider> {
|
||||
public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
|
||||
}
|
||||
|
|
|
@ -114,6 +114,10 @@
|
|||
<name>picketlink.version</name>
|
||||
<value>${picketlink.version}</value>
|
||||
</injection>
|
||||
<injection>
|
||||
<name>wildfly.version</name>
|
||||
<value>${wildfly.version}</value>
|
||||
</injection>
|
||||
</injections>
|
||||
<options>
|
||||
<xmlTransformerType>saxon</xmlTransformerType>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</para>
|
||||
<para>
|
||||
For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory:
|
||||
<programlisting><![CDATA[{
|
||||
<programlisting><![CDATA[
|
||||
package org.acme.provider;
|
||||
|
||||
import ...
|
||||
|
@ -43,7 +43,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
|
|||
}
|
||||
|
||||
}
|
||||
}]]></programlisting>
|
||||
]]></programlisting>
|
||||
The example uses an imagined MaxList which has a maximum size and is concurrency safe. When the maximum size is reached
|
||||
and new entries are added the oldest entry is removed. Keycloak creates a single instance of
|
||||
EventListenerProviderFactory which makes it possible to store state for multiple requests. EventListenerProvider
|
||||
|
@ -51,7 +51,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
|
|||
</para>
|
||||
<para>
|
||||
Next you would implement EventListenerProvider:
|
||||
<programlisting><![CDATA[{
|
||||
<programlisting><![CDATA[
|
||||
package org.acme.provider;
|
||||
|
||||
import ...
|
||||
|
@ -75,13 +75,61 @@ public class MyEventListenerProvider implements EventListenerProvider {
|
|||
}
|
||||
|
||||
}
|
||||
}]]></programlisting>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The file <literal>META-INF/services/org.keycloak.events.EventListenerProviderFactory</literal> should
|
||||
contain the full name of your ProviderFactory implementation:
|
||||
<programlisting><![CDATA[org.acme.provider.MyEventListenerProviderFactory]]></programlisting>
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Show info from you SPI implementation in Keycloak admin console</title>
|
||||
<para>
|
||||
Sometimes it is useful to show additional info about your Provider to a Keycloak administrator.
|
||||
You can show provider build time informations (eg. version of custom provider currently installed),
|
||||
current configuration of the provider (eg. url of remote system your provider talks to) or some operational
|
||||
info (average time of response from remote system your provider talks to).
|
||||
Keycloak admin console provides Server Info page to show this kind of information.
|
||||
</para>
|
||||
<para>
|
||||
To show info from your provider it is enough to implement
|
||||
<literal>org.keycloak.provider.ServerInfoAwareProviderFactory</literal> interface in your ProviderFactory.
|
||||
Example implementation for MyEventListenerProviderFactory from previous example:
|
||||
<programlisting><![CDATA[
|
||||
package org.acme.provider;
|
||||
|
||||
import ...
|
||||
|
||||
public class MyEventListenerProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory {
|
||||
|
||||
private List<Event> events;
|
||||
private int max;
|
||||
|
||||
...
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
max = config.getInt("max");
|
||||
events = new MaxList(max);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
@Override
|
||||
public Map<String, String> getOperationalInfo() {
|
||||
Map<String, String> ret = new LinkedHashMap<>();
|
||||
ret.put("version", "1.0");
|
||||
ret.put("listSizeMax", max + "");
|
||||
ret.put("listSizeCurrent", events.size() + "");
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
]]></programlisting>
|
||||
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
@ -98,13 +146,13 @@ public class MyEventListenerProvider implements EventListenerProvider {
|
|||
To register a provider using Modules first create a module. To do this you can either use the jboss-cli
|
||||
script or manually create a folder inside KEYCLOAK_HOME/modules and add your jar and a <literal>module.xml</literal>.
|
||||
For example to add the event listener sysout example provider using the jboss-cli script execute:
|
||||
<programlisting><![CDATA[{
|
||||
<programlisting><![CDATA[
|
||||
KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-sysout --resources=target/event-listener-sysout-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-model-api,org.keycloak.keycloak-events-api"
|
||||
}]]></programlisting>
|
||||
]]></programlisting>
|
||||
Or to manually create it start by creating the folder <literal>KEYCLOAK_HOME/modules/org/keycloak/examples/event-sysout/main</literal>.
|
||||
Then copy <literal>event-listener-sysout-example.jar</literal> to this folder and create <literal>module.xml</literal>
|
||||
with the following content:
|
||||
<programlisting><![CDATA[{
|
||||
<programlisting><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.examples.event-sysout">
|
||||
<resources>
|
||||
|
@ -116,7 +164,7 @@ public class MyEventListenerProvider implements EventListenerProvider {
|
|||
<module name="org.keycloak.keycloak-events-api"/>
|
||||
</dependencies>
|
||||
</module>
|
||||
}]]></programlisting>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Once you've created the module you need to register this module with Keycloak. This is done by editing
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
|
||||
|
||||
<section id="overlay_install">
|
||||
<title>Install on existing WildFly 9.0.1.Final</title>
|
||||
<title>Install on existing WildFly &wildfly.version;</title>
|
||||
<para>
|
||||
Keycloak can be installed into an existing WildFly 9.0.0.Final server. To do this download
|
||||
Keycloak can be installed into an existing WildFly &wildfly.version; server. To do this download
|
||||
<literal>keycloak-overlay-&project.version;.zip</literal> or <literal>keycloak-overlay-&project.version;.tar.gz</literal>.
|
||||
Once downloaded extract into the root directory of your WildFly installation. To start WildFly with Keycloak
|
||||
run:
|
||||
|
@ -62,11 +62,15 @@
|
|||
<para>
|
||||
To add Keycloak to other sever configurations (standalone.xml, standalone-ha.xml, etc.) start the server with
|
||||
the desired server-config. If you are running the server in standalone mode run:
|
||||
<programlisting>cd <WILDFLY_HOME>/bin
|
||||
./jboss-cli.sh -c --file=keycloak-install.cli</programlisting>
|
||||
<programlisting>
|
||||
cd <WILDFLY_HOME>/bin
|
||||
./jboss-cli.sh -c --file=keycloak-install.cli
|
||||
</programlisting>
|
||||
Or if you are running in clustering (HA) mode (by having used -c standalone-ha.xml) then run:
|
||||
<programlisting>cd <WILDFLY_HOME>/bin
|
||||
./jboss-cli.sh -c --file=keycloak-install-ha.cli</programlisting>
|
||||
<programlisting>
|
||||
cd <WILDFLY_HOME>/bin
|
||||
./jboss-cli.sh -c --file=keycloak-install-ha.cli
|
||||
</programlisting>
|
||||
You may see exceptions in the server log, but after restarting the server they should be gone.
|
||||
You can restart the server with:
|
||||
<programlisting><WILDFLY_HOME>/bin/jboss-cli.sh -c :reload</programlisting>
|
||||
|
@ -75,7 +79,7 @@
|
|||
<section>
|
||||
<title>Install on existing JBoss EAP 6.4.0.GA</title>
|
||||
<para>
|
||||
Same procedure as WildFly 9.0.1.Final, but download <literal>keycloak-overlay-eap6-&project.version;.zip</literal> or <literal>keycloak-overlay-eap6-&project.version;.tar.gz</literal>.
|
||||
Same procedure as WildFly &wildfly.version;, but download <literal>keycloak-overlay-eap6-&project.version;.zip</literal> or <literal>keycloak-overlay-eap6-&project.version;.tar.gz</literal>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -85,7 +89,7 @@
|
|||
To install it first download <literal>keycloak-demo-&project.version;.zip</literal> or
|
||||
<literal>keycloak-demo-&project.version;.tar.gz</literal>. Once downloaded extract it inside
|
||||
<literal>keycloak-demo-&project.version;</literal> you'll find <literal>keycloak</literal> which contains
|
||||
a full WildFly 9.0.0.Final server with Keycloak Server and Adapters included. You'll also find <literal>docs</literal>
|
||||
a full WildFly &wildfly.version; server with Keycloak Server and Adapters included. You'll also find <literal>docs</literal>
|
||||
and <literal>examples</literal> which contains everything you need to get started developing applications that use Keycloak.
|
||||
</para>
|
||||
<para>
|
||||
|
@ -437,12 +441,12 @@ All configuration options are optional. Default value for directory is <literal>
|
|||
settings you can specify before boot time. This is configured in the
|
||||
<literal>standalone/configuration/keycloak-server.json</literal>.
|
||||
By default the setting is like this:
|
||||
<programlisting><![CDATA[
|
||||
"connectionsHttpClient": {
|
||||
"default": {
|
||||
"disable-trust-manager": true
|
||||
}
|
||||
},
|
||||
<programlisting><![CDATA[
|
||||
"connectionsHttpClient": {
|
||||
"default": {
|
||||
"disable-trust-manager": true
|
||||
}
|
||||
},
|
||||
]]></programlisting>
|
||||
Possible configuration options are:
|
||||
<variablelist>
|
||||
|
@ -659,25 +663,25 @@ All configuration options are optional. Default value for directory is <literal>
|
|||
to do with the <literal>keytool</literal> utility that comes with the Java jdk.
|
||||
</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
|
||||
Enter keystore password: secret
|
||||
Re-enter new password: secret
|
||||
What is your first and last name?
|
||||
[Unknown]: localhost
|
||||
What is the name of your organizational unit?
|
||||
[Unknown]: Keycloak
|
||||
What is the name of your organization?
|
||||
[Unknown]: Red Hat
|
||||
What is the name of your City or Locality?
|
||||
[Unknown]: Westford
|
||||
What is the name of your State or Province?
|
||||
[Unknown]: MA
|
||||
What is the two-letter country code for this unit?
|
||||
[Unknown]: US
|
||||
Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
|
||||
[no]: yes
|
||||
</programlisting>
|
||||
<programlisting>
|
||||
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
|
||||
Enter keystore password: secret
|
||||
Re-enter new password: secret
|
||||
What is your first and last name?
|
||||
[Unknown]: localhost
|
||||
What is the name of your organizational unit?
|
||||
[Unknown]: Keycloak
|
||||
What is the name of your organization?
|
||||
[Unknown]: Red Hat
|
||||
What is the name of your City or Locality?
|
||||
[Unknown]: Westford
|
||||
What is the name of your State or Province?
|
||||
[Unknown]: MA
|
||||
What is the two-letter country code for this unit?
|
||||
[Unknown]: US
|
||||
Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
|
||||
[no]: yes
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
You should answer <literal>What is your first and last name ?</literal> question with
|
||||
|
@ -693,44 +697,44 @@ All configuration options are optional. Default value for directory is <literal>
|
|||
</para>
|
||||
<para>
|
||||
The first thing to do is generate a Certificate Request:
|
||||
<programlisting>
|
||||
$ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
|
||||
</programlisting>
|
||||
<programlisting>
|
||||
$ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Where <literal>yourdomain</literal> is a DNS name for which this certificate is generated for.
|
||||
Keytool generates the request:
|
||||
<programlisting>
|
||||
-----BEGIN NEW CERTIFICATE REQUEST-----
|
||||
MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
|
||||
ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
|
||||
Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
|
||||
29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
|
||||
H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
|
||||
Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
|
||||
2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
|
||||
n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
|
||||
PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
|
||||
9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
|
||||
MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
|
||||
vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
|
||||
-----END NEW CERTIFICATE REQUEST-----
|
||||
</programlisting>
|
||||
<programlisting>
|
||||
-----BEGIN NEW CERTIFICATE REQUEST-----
|
||||
MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
|
||||
ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
|
||||
Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
|
||||
29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
|
||||
H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
|
||||
Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
|
||||
2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
|
||||
n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
|
||||
PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
|
||||
9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
|
||||
MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
|
||||
vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
|
||||
-----END NEW CERTIFICATE REQUEST-----
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Send this ca request to your CA. The CA will issue you a signed certificate and send it to you.
|
||||
Before you import your new cert, you must obtain and import the root certificate of the CA.
|
||||
You can download the cert from CA (ie.: root.crt) and import as follows:
|
||||
<programlisting>
|
||||
$ keytool -import -keystore keycloak.jks -file root.crt -alias root
|
||||
</programlisting>
|
||||
<programlisting>
|
||||
$ keytool -import -keystore keycloak.jks -file root.crt -alias root
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Last step is import your new CA generated certificate to your keystore:
|
||||
<programlisting>
|
||||
$ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
|
||||
</programlisting>
|
||||
<programlisting>
|
||||
$ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
|
||||
</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -744,18 +748,19 @@ All configuration options are optional. Default value for directory is <literal>
|
|||
</para>
|
||||
<para>
|
||||
To the <literal>security-realms</literal> element add:
|
||||
<programlisting><![CDATA[<security-realm name="UndertowRealm">
|
||||
<server-identities>
|
||||
<ssl>
|
||||
<keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
|
||||
</ssl>
|
||||
</server-identities>
|
||||
</security-realm>]]></programlisting>
|
||||
<programlisting><![CDATA[
|
||||
<security-realm name="UndertowRealm">
|
||||
<server-identities>
|
||||
<ssl>
|
||||
<keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
|
||||
</ssl>
|
||||
</server-identities>
|
||||
</security-realm>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Find the element <literal><server name="default-server"></literal> (it's a child element of <literal><subsystem xmlns="urn:jboss:domain:undertow:1.0"></literal>) and add:
|
||||
<programlisting><![CDATA[<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>
|
||||
]]></programlisting>
|
||||
<programlisting><![CDATA[<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Check the <ulink url="https://docs.jboss.org/author/display/WFLY8/Undertow+(web)+subsystem+configuration">Wildfly Undertow</ulink> documentation for more information on fine tuning the socket connections.
|
||||
|
@ -865,12 +870,12 @@ All configuration options are optional. Default value for directory is <literal>
|
|||
</para>
|
||||
<para>
|
||||
To do this, add the <literal>default-web-module</literal> attribute in the Undertow subystem in standalone.xml.
|
||||
<programlisting><![CDATA[
|
||||
<programlisting><![CDATA[
|
||||
<subsystem xmlns="urn:jboss:domain:undertow:2.0">
|
||||
<server name="default-server">
|
||||
<host name="default-host" alias="localhost" default-web-module="keycloak-server.war">
|
||||
<location name="/" handler="welcome-content"/>
|
||||
</host>
|
||||
<server name="default-server">
|
||||
<host name="default-host" alias="localhost" default-web-module="keycloak-server.war">
|
||||
<location name="/" handler="welcome-content"/>
|
||||
</host>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
|
|
|
@ -877,7 +877,7 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, $route, se
|
|||
$scope.viewImportDetails = function() {
|
||||
$modal.open({
|
||||
templateUrl: resourceUrl + '/partials/modal/view-object.html',
|
||||
controller: 'JsonModalCtrl',
|
||||
controller: 'ObjectModalCtrl',
|
||||
resolve: {
|
||||
object: function () {
|
||||
return $scope.client;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<td>{{mapper.name}}</td>
|
||||
<td>{{mapperTypes[mapper.protocolMapper].category}}</td>
|
||||
<td>{{mapperTypes[mapper.protocolMapper].name}}</td>
|
||||
<td><input type="checkbox" ng-model="mapper.isChecked"></td>
|
||||
<td><input type="checkbox" ng-model="mapper.isChecked" id="{{mapper.protocolMapper}}"></td>
|
||||
</tr>
|
||||
<tr data-ng-show="mappers.length == 0">
|
||||
<td>{{:: 'no-mappers-available' | translate}}</td>
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<div class="form-group" data-ng-show="realm.otpPolicyType == 'hotp'">
|
||||
<label class="col-md-2 control-label" for="counter">Initial Counter</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" type="text" id="counter" name="counter" data-ng-model="realm.otpPolicyInitialCounter" autofocus>
|
||||
<input class="form-control" type="number" required min="1" max="120" id="counter" name="counter" data-ng-model="realm.otpPolicyInitialCounter" autofocus>
|
||||
</div>
|
||||
<kc-tooltip>What should the initial counter value be?</kc-tooltip>
|
||||
</div>
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
<tbody>
|
||||
<tr ng-repeat="requiredAction in requiredActions" data-ng-show="requiredActions.length > 0">
|
||||
<td>{{requiredAction.name}}</td>
|
||||
<td><input type="checkbox" ng-model="requiredAction.enabled" ng-change="updateRequiredAction(requiredAction)"></td>
|
||||
<td><input type="checkbox" ng-model="requiredAction.defaultAction" ng-change="updateRequiredAction(requiredAction)"></td>
|
||||
<td><input type="checkbox" ng-model="requiredAction.enabled" ng-change="updateRequiredAction(requiredAction)" id="{{requiredAction.alias}}.enabled"></td>
|
||||
<td><input type="checkbox" ng-model="requiredAction.defaultAction" ng-change="updateRequiredAction(requiredAction)" id="{{requiredAction.alias}}.defaultAction"></td>
|
||||
</tr>
|
||||
<tr data-ng-show="requiredActions.length == 0">
|
||||
<td>No required actions configured</td>
|
||||
|
|
|
@ -43,21 +43,21 @@
|
|||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -153,23 +153,23 @@
|
|||
+ '&response_type=code';
|
||||
|
||||
if (options && options.prompt) {
|
||||
url += '&prompt=' + options.prompt;
|
||||
url += '&prompt=' + encodeURIComponent(options.prompt);
|
||||
}
|
||||
|
||||
if (options && options.loginHint) {
|
||||
url += '&login_hint=' + options.loginHint;
|
||||
url += '&login_hint=' + encodeURIComponent(options.loginHint);
|
||||
}
|
||||
|
||||
if (options && options.idpHint) {
|
||||
url += '&kc_idp_hint=' + options.idpHint;
|
||||
url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint);
|
||||
}
|
||||
|
||||
if (options && options.scope) {
|
||||
url += '&scope=' + options.scope;
|
||||
url += '&scope=' + encodeURIComponent(options.scope);
|
||||
}
|
||||
|
||||
if (options && options.locale) {
|
||||
url += '&ui_locales=' + options.locale;
|
||||
url += '&ui_locales=' + encodeURIComponent(options.locale);
|
||||
}
|
||||
|
||||
return url;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package org.keycloak.adapters.osgi;
|
||||
|
||||
import java.net.URL;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
|
@ -133,7 +133,8 @@ public class PaxWebIntegrationService {
|
|||
Constraint constraint = constraintMapping.getConstraint();
|
||||
String[] roles = constraint.getRoles();
|
||||
// name property is unavailable on constraint object :/
|
||||
String name = "Constraint-" + new Random().nextInt();
|
||||
|
||||
String name = "Constraint-" + new SecureRandom().nextInt(Integer.MAX_VALUE);
|
||||
|
||||
int dataConstraint = constraint.getDataConstraint();
|
||||
String dataConstraintStr;
|
||||
|
|
|
@ -3,15 +3,15 @@ package org.keycloak.provider;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Marker interface for ProviderFactory of Provider which wants to show some info on "Server Info" page in Admin console.
|
||||
* Marker interface for {@link ProviderFactory} of Provider which wants to show some info on "Server Info" page in Admin console.
|
||||
*
|
||||
* @author Vlastimil Elias (velias at redhat dot com)
|
||||
*/
|
||||
public interface ServerInfoAwareProviderFactory<T extends Provider> extends ProviderFactory<T> {
|
||||
public interface ServerInfoAwareProviderFactory {
|
||||
|
||||
/**
|
||||
* Get operational info about given provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is
|
||||
* shown on "Server Info" page.
|
||||
* Return actual info about the provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is
|
||||
* shown on "Server Info" page then.
|
||||
*
|
||||
* @return Map with keys describing value and relevant values itself
|
||||
*/
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -48,8 +48,8 @@
|
|||
<dom4j.version>1.6.1</dom4j.version>
|
||||
<xml-apis.version>1.4.01</xml-apis.version>
|
||||
<slf4j.version>1.7.7</slf4j.version>
|
||||
<wildfly.version>9.0.1.Final</wildfly.version>
|
||||
<wildfly.core.version>1.0.1.Final</wildfly.core.version>
|
||||
<wildfly.version>9.0.2.Final</wildfly.version>
|
||||
<wildfly.core.version>1.0.2.Final</wildfly.core.version>
|
||||
<wildfly.build-tools.version>1.0.0.Final</wildfly.build-tools.version>
|
||||
|
||||
<!-- this is EAP 6.4 alpha, publicly available -->
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
package org.keycloak.services.resources.admin.info;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.core.Context;
|
||||
|
||||
import org.keycloak.broker.provider.IdentityProvider;
|
||||
import org.keycloak.broker.provider.IdentityProviderFactory;
|
||||
import org.keycloak.events.EventType;
|
||||
|
@ -21,10 +33,6 @@ import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
|||
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
|
||||
import org.keycloak.social.SocialIdentityProvider;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.core.Context;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
|
@ -73,7 +81,6 @@ public class ServerInfoAdminResource {
|
|||
for (Spi spi : spis) {
|
||||
SpiInfoRepresentation spiRep = new SpiInfoRepresentation();
|
||||
spiRep.setInternal(spi.isInternal());
|
||||
spiRep.setSystemInfo(ServerInfoAwareProviderFactory.class.isAssignableFrom(spi.getProviderFactoryClass()));
|
||||
|
||||
List<String> providerIds = new LinkedList<>(session.listProviderIds(spi.getProviderClass()));
|
||||
Collections.sort(providerIds);
|
||||
|
@ -83,8 +90,9 @@ public class ServerInfoAdminResource {
|
|||
if (providerIds != null) {
|
||||
for (String name : providerIds) {
|
||||
ProviderRepresentation provider = new ProviderRepresentation();
|
||||
if (spiRep.isSystemInfo()) {
|
||||
provider.setOperationalInfo(((ServerInfoAwareProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name)).getOperationalInfo());
|
||||
ProviderFactory<?> pi = session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name);
|
||||
if (ServerInfoAwareProviderFactory.class.isAssignableFrom(pi.getClass())) {
|
||||
provider.setOperationalInfo(((ServerInfoAwareProviderFactory) pi).getOperationalInfo());
|
||||
}
|
||||
providers.put(name, provider);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Map;
|
|||
public class SpiInfoRepresentation {
|
||||
|
||||
private boolean internal;
|
||||
private boolean systemInfo;
|
||||
|
||||
private Map<String, ProviderRepresentation> providers;
|
||||
|
||||
|
@ -20,14 +19,6 @@ public class SpiInfoRepresentation {
|
|||
this.internal = internal;
|
||||
}
|
||||
|
||||
public boolean isSystemInfo() {
|
||||
return systemInfo;
|
||||
}
|
||||
|
||||
public void setSystemInfo(boolean systemInfo) {
|
||||
this.systemInfo = systemInfo;
|
||||
}
|
||||
|
||||
public Map<String, ProviderRepresentation> getProviders() {
|
||||
return providers;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,18 @@
|
|||
<exclude.console>-</exclude.console>
|
||||
<exclude.account>-</exclude.account>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-util-embedded-ldap</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -57,7 +57,7 @@ public class AdminConsoleRealm extends AdminConsoleRealmsRoot {
|
|||
private WebElement rolesLink;
|
||||
@FindBy(partialLinkText = "Identity Providers")
|
||||
private WebElement identityProvidersLink;
|
||||
@FindBy(partialLinkText = "User Feferation")
|
||||
@FindBy(partialLinkText = "User Federation")
|
||||
private WebElement userFederationLink;
|
||||
@FindBy(partialLinkText = "Authentication")
|
||||
private WebElement authenticationLink;
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.keycloak.testsuite.console.page.authentication;
|
|||
import org.keycloak.testsuite.console.page.AdminConsoleRealm;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.*;
|
||||
|
||||
/**
|
||||
* @author tkyjovsk
|
||||
|
@ -20,6 +20,9 @@ public class Authentication extends AdminConsoleRealm {
|
|||
@FindBy(xpath = "//div[contains(@class, 'alert-success')]")
|
||||
private WebElement success;
|
||||
|
||||
@FindBy(xpath = "//button[@class='close']/span")
|
||||
private WebElement close;
|
||||
|
||||
public String getSuccessMessage() {
|
||||
waitAjaxForElement(success);
|
||||
return success.getText();
|
||||
|
@ -30,6 +33,13 @@ public class Authentication extends AdminConsoleRealm {
|
|||
return error.getText();
|
||||
}
|
||||
|
||||
public void closeNotification() {
|
||||
if (close.isDisplayed()) {
|
||||
close.click();
|
||||
}
|
||||
waitAjaxForElementNotVisible(close);
|
||||
}
|
||||
|
||||
public AuthenticationTabs tabs() {
|
||||
return authenticationTabs;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,17 @@ import org.openqa.selenium.support.FindBy;
|
|||
/**
|
||||
* @author tkyjovsk
|
||||
* @author mhajas
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class RequiredActions extends Authentication {
|
||||
|
||||
public final static String ENABLED = "enabled";
|
||||
public final static String DEFAULT_ACTION = "defaultAction";
|
||||
public final static String ENABLED = ".enabled";
|
||||
public final static String DEFAULT = ".defaultAction";
|
||||
public final static String CONFIGURE_TOTP = "CONFIGURE_TOTP";
|
||||
public final static String UPDATE_PROFILE = "UPDATE_PROFILE";
|
||||
public final static String TERMS_AND_CONDITIONS = "terms_and_conditions";
|
||||
public final static String UPDATE_PASSWORD = "UPDATE_PASSWORD";
|
||||
public final static String VERIFY_EMAIL = "VERIFY_EMAIL";
|
||||
|
||||
@FindBy(tagName = "table")
|
||||
private WebElement requiredActionTable;
|
||||
|
@ -21,51 +27,59 @@ public class RequiredActions extends Authentication {
|
|||
return super.getUriFragment() + "/required-actions";
|
||||
}
|
||||
|
||||
private void setRequiredActionValue(String row, String column, boolean value) {
|
||||
WebElement checkbox = requiredActionTable.findElement(By.xpath("//td[text()='" + row + "']/..//input[@ng-model='requiredAction." + column + "']"));
|
||||
private void setRequiredActionValue(String id, boolean value) {
|
||||
WebElement checkbox = requiredActionTable.findElement(By.id(id));
|
||||
|
||||
if (checkbox.isSelected() != value) {
|
||||
checkbox.click();
|
||||
}
|
||||
}
|
||||
|
||||
private void setRequiredActionEnabledValue(String id, boolean value) {
|
||||
setRequiredActionValue(id + ENABLED, value);
|
||||
}
|
||||
|
||||
private void setRequiredActionDefaultValue(String id, boolean value) {
|
||||
setRequiredActionValue(id + DEFAULT, value);
|
||||
}
|
||||
|
||||
public void setTermsAndConditionEnabled(boolean value) {
|
||||
setRequiredActionValue("Terms and Conditions", ENABLED, value);
|
||||
setRequiredActionEnabledValue(TERMS_AND_CONDITIONS, value);
|
||||
}
|
||||
|
||||
public void setTermsAndConditionDefaultAction(boolean value) {
|
||||
setRequiredActionValue("Terms and Conditions", DEFAULT_ACTION, value);
|
||||
setRequiredActionDefaultValue(TERMS_AND_CONDITIONS, value);
|
||||
}
|
||||
|
||||
public void setVerifyEmailEnabled(boolean value) {
|
||||
setRequiredActionValue("Verify Email", ENABLED, value);
|
||||
setRequiredActionEnabledValue(VERIFY_EMAIL, value);
|
||||
}
|
||||
|
||||
public void setVerifyEmailDefaultAction(boolean value) {
|
||||
setRequiredActionValue("Verify Email", DEFAULT_ACTION, value);
|
||||
setRequiredActionDefaultValue(VERIFY_EMAIL, value);
|
||||
}
|
||||
|
||||
public void setUpdatePasswordEnabled(boolean value) {
|
||||
setRequiredActionValue("Update Password", ENABLED, value);
|
||||
setRequiredActionEnabledValue(UPDATE_PASSWORD, value);
|
||||
}
|
||||
|
||||
public void setUpdatePasswordDefaultAction(boolean value) {
|
||||
setRequiredActionValue("Update Password", DEFAULT_ACTION, value);
|
||||
setRequiredActionDefaultValue(UPDATE_PASSWORD, value);
|
||||
}
|
||||
|
||||
public void setConfigureTotpEnabled(boolean value) {
|
||||
setRequiredActionValue("Configure Totp", ENABLED, value);
|
||||
setRequiredActionEnabledValue(CONFIGURE_TOTP, value);
|
||||
}
|
||||
|
||||
public void setConfigureTotpDefaultAction(boolean value) {
|
||||
setRequiredActionValue("Configure Totp", DEFAULT_ACTION, value);
|
||||
setRequiredActionDefaultValue(CONFIGURE_TOTP, value);
|
||||
}
|
||||
|
||||
public void setUpdateProfileEnabled(boolean value) {
|
||||
setRequiredActionValue("Update Profile", ENABLED, value);
|
||||
setRequiredActionEnabledValue(UPDATE_PROFILE, value);
|
||||
}
|
||||
|
||||
public void setUpdateProfileDefaultAction(boolean value) {
|
||||
setRequiredActionValue("Update Profile", DEFAULT_ACTION, value);
|
||||
setRequiredActionDefaultValue(UPDATE_PROFILE, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,112 @@
|
|||
package org.keycloak.testsuite.console.page.clients;
|
||||
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.testsuite.console.page.fragment.DataTable;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class ClientMappers extends Client {
|
||||
|
||||
public static final String ADD_BUILTIN = "Add Builtin";
|
||||
|
||||
@FindBy(tagName = "table")
|
||||
private ClientMapperTable table;
|
||||
|
||||
@Override
|
||||
public String getUriFragment() {
|
||||
return super.getUriFragment() + "/mappers";
|
||||
}
|
||||
|
||||
public ClientMapperTable mapperTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public class ClientMapperTable extends DataTable {
|
||||
|
||||
public List<ProtocolMapperRepresentation> searchMappings(String searchPattern) {
|
||||
search(searchPattern);
|
||||
return getMappingsFromRows();
|
||||
}
|
||||
|
||||
public void createMapper() {
|
||||
waitAjaxForBody();
|
||||
clickHeaderLink(CREATE);
|
||||
}
|
||||
|
||||
public void addBuiltin() {
|
||||
waitAjaxForBody();
|
||||
clickHeaderLink(ADD_BUILTIN);
|
||||
}
|
||||
|
||||
public void clickMapper(String mapperName) {
|
||||
waitAjaxForBody();
|
||||
body().findElement(By.linkText(mapperName)).click();
|
||||
}
|
||||
|
||||
public void clickMapper(ProtocolMapperRepresentation mapper) {
|
||||
clickMapper(mapper.getName());
|
||||
}
|
||||
|
||||
private void clickMapperActionButton(String mapperName, String buttonText) {
|
||||
waitAjaxForBody();
|
||||
clickRowActionButton(getRowByLinkText(mapperName), buttonText);
|
||||
}
|
||||
|
||||
private void clickMapperActionButton(ProtocolMapperRepresentation mapper, String buttonName) {
|
||||
clickMapperActionButton(mapper.getName(), buttonName);
|
||||
}
|
||||
|
||||
public void editMapper(String mapperName) {
|
||||
clickMapperActionButton(mapperName, EDIT);
|
||||
}
|
||||
|
||||
public void editMapper(ProtocolMapperRepresentation mapper) {
|
||||
clickMapperActionButton(mapper, EDIT);
|
||||
}
|
||||
|
||||
public void deleteMapper(String mapperName) {
|
||||
clickMapperActionButton(mapperName, DELETE);
|
||||
}
|
||||
|
||||
public void deleteMapper(ProtocolMapperRepresentation mapper) {
|
||||
clickMapperActionButton(mapper, DELETE);
|
||||
}
|
||||
|
||||
public ProtocolMapperRepresentation getMappingFromRow(WebElement row) {
|
||||
if (!row.isDisplayed()) {return null;} // Is that necessary?
|
||||
|
||||
ProtocolMapperRepresentation mappingsRepresentation = new ProtocolMapperRepresentation();
|
||||
List<WebElement> cols = row.findElements(By.tagName("td"));
|
||||
|
||||
|
||||
mappingsRepresentation.setName(cols.get(0).getText());
|
||||
//mappingsRepresentation.setProtocol(cols.get(1).getText());
|
||||
mappingsRepresentation.setProtocolMapper(cols.get(2).getText());
|
||||
|
||||
return mappingsRepresentation;
|
||||
}
|
||||
|
||||
public List<ProtocolMapperRepresentation> getMappingsFromRows() {
|
||||
List<ProtocolMapperRepresentation> mappings = new ArrayList<ProtocolMapperRepresentation>();
|
||||
|
||||
for (WebElement row : rows()) {
|
||||
ProtocolMapperRepresentation mapperRepresentation = getMappingFromRow(row);
|
||||
if (mapperRepresentation != null) {
|
||||
mappings.add(mapperRepresentation);
|
||||
}
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package org.keycloak.testsuite.console.page.clients;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.console.page.AdminConsoleCreate;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class CreateClientMappers extends AdminConsoleCreate {
|
||||
|
||||
@Page
|
||||
private CreateClientMappersForm form;
|
||||
|
||||
public CreateClientMappers() {
|
||||
setEntity("mappers");
|
||||
}
|
||||
|
||||
public CreateClientMappersForm form() {
|
||||
return form;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
package org.keycloak.testsuite.console.page.clients;
|
||||
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||
import org.keycloak.testsuite.page.Form;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.interactions.Actions;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import org.openqa.selenium.support.ui.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*
|
||||
* TODO: SAML
|
||||
*/
|
||||
public class CreateClientMappersForm extends Form {
|
||||
|
||||
// Mappers types
|
||||
public static final String HARDCODED_ROLE = "Hardcoded Role";
|
||||
public static final String HARDCODED_CLAIM = "Hardcoded claim";
|
||||
public static final String USER_SESSION_NOTE = "User Session Note";
|
||||
public static final String ROLE_NAME_MAPPER = "Role Name Mapper";
|
||||
public static final String USER_ADDRESS = "User Address";
|
||||
public static final String USERS_FULL_NAME = "User's full name";
|
||||
public static final String USER_ATTRIBUTE = "User Attribute";
|
||||
public static final String USER_PROPERTY = "User Property";
|
||||
|
||||
@FindBy(id = "name")
|
||||
private WebElement nameElement;
|
||||
|
||||
@FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='consentRequired']]")
|
||||
private OnOffSwitch consentRequiredSwitch;
|
||||
|
||||
@FindBy(id = "consentText")
|
||||
private WebElement consentTextElement;
|
||||
|
||||
@FindBy(id = "mapperTypeCreate")
|
||||
private Select mapperTypeSelect;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Property']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement propertyInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Attribute']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement userAttributeInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Session Note']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement userSessionNoteInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Multivalued']//following-sibling::node()//div[@class='onoffswitch']")
|
||||
private OnOffSwitch multivaluedInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Role']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement roleInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='New Role Name']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement newRoleInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Token Claim Name']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement tokenClaimNameInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim value']//following-sibling::node()//input[@type='text']")
|
||||
private WebElement tokenClaimValueInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim JSON Type']//following-sibling::node()//select")
|
||||
private Select claimJSONTypeInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to ID token']//following-sibling::node()//div[@class='onoffswitch']")
|
||||
private OnOffSwitch addToIDTokenInput;
|
||||
|
||||
@FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to access token']//following-sibling::node()//div[@class='onoffswitch']")
|
||||
private OnOffSwitch addToAccessTokenInput;
|
||||
|
||||
public boolean isConsentRequired() {
|
||||
return consentRequiredSwitch.isOn();
|
||||
}
|
||||
|
||||
public void setConsentRequired(boolean consentRequired) {
|
||||
consentRequiredSwitch.setOn(consentRequired);
|
||||
}
|
||||
|
||||
public String getConsentText() {
|
||||
return getInputValue(consentTextElement);
|
||||
}
|
||||
|
||||
public void setConsentText(String consentText) {
|
||||
setInputValue(consentTextElement, consentText);
|
||||
}
|
||||
|
||||
public String getMapperType() {
|
||||
return mapperTypeSelect.getFirstSelectedOption().getText();
|
||||
}
|
||||
|
||||
public void setMapperType(String type) {
|
||||
mapperTypeSelect.selectByVisibleText(type);
|
||||
}
|
||||
|
||||
public String getProperty() {
|
||||
return getInputValue(propertyInput);
|
||||
}
|
||||
|
||||
public void setProperty(String value) {
|
||||
setInputValue(propertyInput, value);
|
||||
}
|
||||
|
||||
public String getUserAttribute() {
|
||||
return getInputValue(userAttributeInput);
|
||||
}
|
||||
|
||||
public void setUserAttribute(String value) {
|
||||
setInputValue(userAttributeInput, value);
|
||||
}
|
||||
|
||||
public String getUserSessionNote() {
|
||||
return getInputValue(userSessionNoteInput);
|
||||
}
|
||||
|
||||
public void setUserSessionNote(String value) {
|
||||
setInputValue(userSessionNoteInput, value);
|
||||
}
|
||||
|
||||
public boolean isMultivalued() {
|
||||
return multivaluedInput.isOn();
|
||||
}
|
||||
|
||||
public void setMultivalued(boolean value) {
|
||||
multivaluedInput.setOn(value);
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return getInputValue(roleInput);
|
||||
}
|
||||
|
||||
public void setRole(String value) {
|
||||
setInputValue(roleInput, value);
|
||||
}
|
||||
|
||||
public String getNewRole() {
|
||||
return getInputValue(newRoleInput);
|
||||
}
|
||||
|
||||
public void setNewRole(String value) {
|
||||
setInputValue(newRoleInput, value);
|
||||
}
|
||||
|
||||
public String getTokenClaimName() {
|
||||
return getInputValue(tokenClaimNameInput);
|
||||
}
|
||||
|
||||
public void setTokenClaimName(String value) {
|
||||
setInputValue(tokenClaimNameInput, value);
|
||||
}
|
||||
|
||||
public String getTokenClaimValue() {
|
||||
return getInputValue(tokenClaimValueInput);
|
||||
}
|
||||
|
||||
public void setTokenClaimValue(String value) {
|
||||
setInputValue(tokenClaimValueInput, value);
|
||||
}
|
||||
|
||||
public String getClaimJSONType() {
|
||||
return claimJSONTypeInput.getFirstSelectedOption().getText();
|
||||
}
|
||||
|
||||
public void setClaimJSONType(String value) {
|
||||
claimJSONTypeInput.selectByVisibleText(value);
|
||||
}
|
||||
|
||||
public boolean isAddToIDToken() {
|
||||
return addToIDTokenInput.isOn();
|
||||
}
|
||||
|
||||
public void setAddToIDToken(boolean value) {
|
||||
addToIDTokenInput.setOn(value);
|
||||
}
|
||||
|
||||
public boolean isAddToAccessToken() {
|
||||
return addToAccessTokenInput.isOn();
|
||||
}
|
||||
|
||||
public void setAddToAccessToken(boolean value) {
|
||||
addToAccessTokenInput.setOn(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.keycloak.testsuite.console.page.federation;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.console.page.AdminConsoleCreate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pdrozd
|
||||
*/
|
||||
public class CreateKerberosUserProvider extends AdminConsoleCreate {
|
||||
|
||||
@Page
|
||||
private KerberosUserProviderForm form;
|
||||
|
||||
public CreateKerberosUserProvider() {
|
||||
setEntity("user-federation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUriFragment() {
|
||||
return super.getUriFragment() + "/providers/kerberos";
|
||||
}
|
||||
|
||||
public KerberosUserProviderForm form() {
|
||||
return form;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.testsuite.console.page.federation;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.console.page.AdminConsoleCreate;
|
||||
|
||||
/**
|
||||
|
@ -8,6 +9,9 @@ import org.keycloak.testsuite.console.page.AdminConsoleCreate;
|
|||
*/
|
||||
public class CreateLdapUserProvider extends AdminConsoleCreate {
|
||||
|
||||
@Page
|
||||
private LdapUserProviderForm form;
|
||||
|
||||
public CreateLdapUserProvider() {
|
||||
setEntity("user-federation");
|
||||
}
|
||||
|
@ -17,4 +21,7 @@ public class CreateLdapUserProvider extends AdminConsoleCreate {
|
|||
return super.getUriFragment() + "/providers/ldap";
|
||||
}
|
||||
|
||||
public LdapUserProviderForm form() {
|
||||
return form;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package org.keycloak.testsuite.console.page.federation;
|
||||
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
||||
|
||||
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||
import org.keycloak.testsuite.page.Form;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import org.openqa.selenium.support.ui.Select;
|
||||
|
||||
/**
|
||||
* @author pdrozd
|
||||
*/
|
||||
public class KerberosUserProviderForm extends Form {
|
||||
|
||||
@FindBy(id = "consoleDisplayName")
|
||||
private WebElement consoleDisplayNameInput;
|
||||
|
||||
@FindBy(id = "priority")
|
||||
private WebElement priorityInput;
|
||||
|
||||
@FindBy(id = "kerberosRealm")
|
||||
private WebElement kerberosRealmInput;
|
||||
|
||||
@FindBy(id = "serverPrincipal")
|
||||
private WebElement serverPrincipalInput;
|
||||
|
||||
@FindBy(id = "keyTab")
|
||||
private WebElement keyTabInput;
|
||||
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='debug']]")
|
||||
private OnOffSwitch debug;
|
||||
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='allowPasswordAuthentication']]")
|
||||
private OnOffSwitch allowPwdAuth;
|
||||
|
||||
@FindBy(id = "editMode")
|
||||
private Select editModeSelect;
|
||||
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='updateProfileFirstLogin']]")
|
||||
private OnOffSwitch updateProfileFirstLogin;
|
||||
|
||||
public void setConsoleDisplayNameInput(String name) {
|
||||
setInputValue(consoleDisplayNameInput, name);
|
||||
}
|
||||
|
||||
public void setPriorityInput(Integer priority) {
|
||||
setInputValue(priorityInput, String.valueOf(priority));
|
||||
}
|
||||
|
||||
public void setKerberosRealmInput(String kerberosRealm) {
|
||||
waitGuiForElement(By.id("kerberosRealm"));
|
||||
setInputValue(kerberosRealmInput, kerberosRealm);
|
||||
}
|
||||
|
||||
public void setServerPrincipalInput(String serverPrincipal) {
|
||||
setInputValue(serverPrincipalInput, serverPrincipal);
|
||||
}
|
||||
|
||||
public void setKeyTabInput(String keyTab) {
|
||||
setInputValue(keyTabInput, keyTab);
|
||||
}
|
||||
|
||||
public void setDebugEnabled(boolean debugEnabled) {
|
||||
this.debug.setOn(debugEnabled);
|
||||
}
|
||||
|
||||
public void setAllowPasswordAuthentication(boolean enabled) {
|
||||
allowPwdAuth.setOn(enabled);
|
||||
}
|
||||
|
||||
public void selectEditMode(String mode) {
|
||||
waitGuiForElement(By.id("editMode"));
|
||||
editModeSelect.selectByVisibleText(mode);
|
||||
}
|
||||
|
||||
public void setUpdateProfileFirstLogin(boolean enabled) {
|
||||
updateProfileFirstLogin.setOn(enabled);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package org.keycloak.testsuite.console.page.federation;
|
||||
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
||||
|
||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||
import org.keycloak.testsuite.page.Form;
|
||||
|
@ -8,10 +11,8 @@ import org.openqa.selenium.WebElement;
|
|||
import org.openqa.selenium.support.FindBy;
|
||||
import org.openqa.selenium.support.ui.Select;
|
||||
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
||||
|
||||
/**
|
||||
* Created by fkiss.
|
||||
* @author fkiss, pdrozd
|
||||
*/
|
||||
public class LdapUserProviderForm extends Form {
|
||||
|
||||
|
@ -24,24 +25,33 @@ public class LdapUserProviderForm extends Form {
|
|||
@FindBy(id = "usernameLDAPAttribute")
|
||||
private WebElement usernameLDAPAttributeInput;
|
||||
|
||||
@FindBy(id = "rdnLDAPAttribute")
|
||||
private WebElement rdnLDAPAttributeInput;
|
||||
|
||||
@FindBy(id = "uuidLDAPAttribute")
|
||||
private WebElement uuidLDAPAttributeInput;
|
||||
|
||||
@FindBy(id = "userObjectClasses")
|
||||
private WebElement userObjectClassesInput;
|
||||
|
||||
@FindBy(id = "ldapConnectionUrl")
|
||||
private WebElement ldapConnectionUrlInput;
|
||||
|
||||
@FindBy(id = "ldapBaseDn")
|
||||
private WebElement ldapBaseDnInput;
|
||||
|
||||
@FindBy(id = "ldapUsersDn")
|
||||
private WebElement ldapUserDnInput;
|
||||
|
||||
@FindBy(id = "authType")
|
||||
private Select authTypeSelect;
|
||||
|
||||
@FindBy(id = "ldapBindDn")
|
||||
private WebElement ldapBindDnInput;
|
||||
|
||||
@FindBy(id = "ldapBindCredential")
|
||||
private WebElement ldapBindCredentialInput;
|
||||
|
||||
@FindBy(id = "searchScope")
|
||||
private Select searchScopeSelect;
|
||||
|
||||
@FindBy(id = "kerberosRealm")
|
||||
private WebElement kerberosRealmInput;
|
||||
|
||||
|
@ -72,59 +82,173 @@ public class LdapUserProviderForm extends Form {
|
|||
@FindByJQuery("a:contains('Test authentication')")
|
||||
private WebElement testAuthenticationButton;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(0)")
|
||||
@FindByJQuery("a:contains('Synchronize changed users')")
|
||||
private WebElement synchronizeChangedUsersButton;
|
||||
|
||||
@FindByJQuery("button:contains('Synchronize all users')")
|
||||
private WebElement synchronizeAllUsersButton;
|
||||
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='syncRegistrations']]")
|
||||
private OnOffSwitch syncRegistrations;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(1)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='connectionPooling']]")
|
||||
private OnOffSwitch connectionPooling;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(2)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='pagination']]")
|
||||
private OnOffSwitch pagination;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(3)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='userAccountControlsAfterPasswordUpdate']]")
|
||||
private OnOffSwitch enableAccountAfterPasswordUpdate;
|
||||
|
||||
@FindBy(xpath = "//div[contains(@class,'onoffswitch') and ./input[@id='allowKerberosAuthentication']]")
|
||||
private OnOffSwitch allowKerberosAuth;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(4)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='debug']]")
|
||||
private OnOffSwitch debug;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(5)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='useKerberosForPasswordAuthentication']]")
|
||||
private OnOffSwitch useKerberosForPwdAuth;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(6)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='compositeSwitch']]")
|
||||
private OnOffSwitch periodicFullSync;
|
||||
|
||||
@FindByJQuery("div[class='onoffswitch']:eq(7)")
|
||||
@FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='changedSyncEnabled']]")
|
||||
private OnOffSwitch periodicChangedUsersSync;
|
||||
|
||||
@FindByJQuery("button:contains('Save')")
|
||||
private WebElement saveButton;
|
||||
public void setConsoleDisplayNameInput(String name) {
|
||||
setInputValue(consoleDisplayNameInput, name);
|
||||
}
|
||||
|
||||
public void selectEditMode(String mode){
|
||||
public void setPriorityInput(Integer priority) {
|
||||
setInputValue(priorityInput, String.valueOf(priority));
|
||||
}
|
||||
|
||||
public void setUsernameLDAPAttributeInput(String usernameLDAPAttribute) {
|
||||
setInputValue(usernameLDAPAttributeInput, usernameLDAPAttribute);
|
||||
}
|
||||
|
||||
public void setRdnLDAPAttributeInput(String rdnLDAPAttribute) {
|
||||
setInputValue(rdnLDAPAttributeInput, rdnLDAPAttribute);
|
||||
}
|
||||
|
||||
public void setUuidLDAPAttributeInput(String uuidLDAPAttribute) {
|
||||
setInputValue(uuidLDAPAttributeInput, uuidLDAPAttribute);
|
||||
}
|
||||
|
||||
public void setUserObjectClassesInput(String userObjectClasses) {
|
||||
setInputValue(userObjectClassesInput, userObjectClasses);
|
||||
}
|
||||
|
||||
public void setLdapConnectionUrlInput(String ldapConnectionUrl) {
|
||||
setInputValue(ldapConnectionUrlInput, ldapConnectionUrl);
|
||||
}
|
||||
|
||||
public void setLdapUserDnInput(String ldapUserDn) {
|
||||
setInputValue(ldapUserDnInput, ldapUserDn);
|
||||
}
|
||||
|
||||
public void setLdapBindDnInput(String ldapBindDn) {
|
||||
setInputValue(ldapBindDnInput, ldapBindDn);
|
||||
}
|
||||
|
||||
public void setLdapBindCredentialInput(String ldapBindCredential) {
|
||||
setInputValue(ldapBindCredentialInput, ldapBindCredential);
|
||||
}
|
||||
|
||||
public void setKerberosRealmInput(String kerberosRealm) {
|
||||
waitAjaxForElement(kerberosRealmInput);
|
||||
setInputValue(kerberosRealmInput, kerberosRealm);
|
||||
}
|
||||
|
||||
public void setServerPrincipalInput(String serverPrincipal) {
|
||||
waitAjaxForElement(serverPrincipalInput);
|
||||
setInputValue(serverPrincipalInput, serverPrincipal);
|
||||
}
|
||||
|
||||
public void setKeyTabInput(String keyTab) {
|
||||
waitAjaxForElement(keyTabInput);
|
||||
setInputValue(keyTabInput, keyTab);
|
||||
}
|
||||
|
||||
public void setBatchSizeForSyncInput(String batchSizeForSync) {
|
||||
setInputValue(batchSizeForSyncInput, batchSizeForSync);
|
||||
}
|
||||
|
||||
public void selectEditMode(String mode) {
|
||||
waitGuiForElement(By.id("editMode"));
|
||||
editModeSelect.selectByVisibleText(mode);
|
||||
}
|
||||
|
||||
public void selectVendor(String vendor){
|
||||
waitGuiForElement(By.id("editMode"));
|
||||
public void selectVendor(String vendor) {
|
||||
waitGuiForElement(By.id("vendor"));
|
||||
vendorSelect.selectByVisibleText(vendor);
|
||||
}
|
||||
|
||||
public void configureLdap(String displayName, String editMode, String vendor, String connectionUrl, String userDN, String ldapBindDn, String ldapBindCredential){
|
||||
consoleDisplayNameInput.sendKeys(displayName);
|
||||
editModeSelect.selectByVisibleText(editMode);
|
||||
selectVendor(vendor);
|
||||
ldapConnectionUrlInput.sendKeys(connectionUrl);
|
||||
ldapUserDnInput.sendKeys(userDN);
|
||||
ldapBindDnInput.sendKeys(ldapBindDn);
|
||||
ldapBindCredentialInput.sendKeys(ldapBindCredential);
|
||||
saveButton.click();
|
||||
public void selectAuthenticationType(String authenticationType) {
|
||||
waitGuiForElement(By.id("authType"));
|
||||
authTypeSelect.selectByVisibleText(authenticationType);
|
||||
}
|
||||
|
||||
public void testConnection(){
|
||||
public void selectSearchScope(String searchScope) {
|
||||
waitGuiForElement(By.id("searchScope"));
|
||||
searchScopeSelect.selectByVisibleText(searchScope);
|
||||
}
|
||||
|
||||
public void setSyncRegistrationsEnabled(boolean syncRegistrationsEnabled) {
|
||||
this.syncRegistrations.setOn(syncRegistrationsEnabled);
|
||||
}
|
||||
|
||||
public void setConnectionPoolingEnabled(boolean connectionPoolingEnabled) {
|
||||
this.connectionPooling.setOn(connectionPoolingEnabled);
|
||||
}
|
||||
|
||||
public void setPaginationEnabled(boolean paginationEnabled) {
|
||||
this.pagination.setOn(paginationEnabled);
|
||||
}
|
||||
|
||||
public void setAccountAfterPasswordUpdateEnabled(boolean enabled) {
|
||||
if ((!enableAccountAfterPasswordUpdate.isOn() && enabled)
|
||||
|| !enabled && enableAccountAfterPasswordUpdate.isOn()) {
|
||||
driver.findElement(By
|
||||
.xpath("//div[contains(@class,'onoffswitch') and ./input[@id='userAccountControlsAfterPasswordUpdate']]"))
|
||||
.findElements(By.tagName("span")).get(0).click();
|
||||
}
|
||||
}
|
||||
|
||||
public void setAllowKerberosAuthEnabled(boolean enabled) {
|
||||
if ((!allowKerberosAuth.isOn() && enabled) || !enabled && allowKerberosAuth.isOn()) {
|
||||
driver.findElement(
|
||||
By.xpath("//div[contains(@class,'onoffswitch') and ./input[@id='allowKerberosAuthentication']]"))
|
||||
.findElements(By.tagName("span")).get(0).click();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDebugEnabled(boolean debugEnabled) {
|
||||
this.debug.setOn(debugEnabled);
|
||||
}
|
||||
|
||||
public void setUseKerberosForPwdAuthEnabled(boolean useKerberosForPwdAuthEnabled) {
|
||||
this.useKerberosForPwdAuth.setOn(useKerberosForPwdAuthEnabled);
|
||||
}
|
||||
|
||||
public void setPeriodicFullSyncEnabled(boolean periodicFullSyncEnabled) {
|
||||
this.periodicFullSync.setOn(periodicFullSyncEnabled);
|
||||
}
|
||||
|
||||
public void setPeriodicChangedUsersSyncEnabled(boolean periodicChangedUsersSyncEnabled) {
|
||||
this.periodicChangedUsersSync.setOn(periodicChangedUsersSyncEnabled);
|
||||
}
|
||||
|
||||
public void testConnection() {
|
||||
testConnectionButton.click();
|
||||
}
|
||||
|
||||
public void testAuthentication(){
|
||||
public void testAuthentication() {
|
||||
testAuthenticationButton.click();
|
||||
}
|
||||
|
||||
public void synchronizeAllUsers() {
|
||||
waitAjaxForElement(synchronizeAllUsersButton);
|
||||
synchronizeAllUsersButton.click();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,14 @@ public class OnOffSwitch {
|
|||
@ArquillianResource
|
||||
private Actions actions;
|
||||
|
||||
public OnOffSwitch() {
|
||||
}
|
||||
|
||||
public OnOffSwitch(WebElement root, Actions actions) {
|
||||
this.root = root;
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public boolean isOn() {
|
||||
waitAjaxForElement(root);
|
||||
return root.findElement(By.tagName("input")).isSelected();
|
||||
|
|
|
@ -41,6 +41,11 @@ public final class WaitUtils {
|
|||
.element(element).is().not().present();
|
||||
}
|
||||
|
||||
public static void waitAjaxForElementNotVisible(WebElement element) {
|
||||
waitAjax().until()
|
||||
.element(element).is().not().visible();
|
||||
}
|
||||
|
||||
public static void waitGuiForElement(By element, String message) {
|
||||
waitGui().until(message)
|
||||
.element(element).is().present();
|
||||
|
|
|
@ -24,6 +24,7 @@ package org.keycloak.testsuite.console.authentication;
|
|||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||
|
@ -66,42 +67,58 @@ public class OTPPolicyTest extends AbstractConsoleTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore //KEYCLOAK-2051 when you close notification, it is not displayed again
|
||||
public void invalidValuesTest() {
|
||||
otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "", "30");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();// workaround: input.clear() doesn't work when <input type="number" ...
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, " ", "30");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "no number", "30");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertEquals(Integer.valueOf(1), realm.getOtpPolicyLookAheadWindow());
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", " ");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "no number");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertEquals(Integer.valueOf(30), realm.getOtpPolicyPeriod());
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", " ");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "no number");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
|
||||
otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "1 2");
|
||||
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
|
||||
otpPolicyPage.closeNotification();
|
||||
otpPolicyPage.navigateTo();
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertEquals(Integer.valueOf(0), realm.getOtpPolicyInitialCounter());
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package org.keycloak.testsuite.console.federation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||
import org.keycloak.testsuite.console.page.federation.CreateKerberosUserProvider;
|
||||
|
||||
/**
|
||||
* @author pdrozd
|
||||
*/
|
||||
public class KerberosUserFederationTest extends AbstractConsoleTest {
|
||||
|
||||
private static final String UNSYNCED = "UNSYNCED";
|
||||
|
||||
private static final String READ_ONLY = "READ_ONLY";
|
||||
|
||||
@Page
|
||||
private CreateKerberosUserProvider createKerberosUserProvider;
|
||||
|
||||
@Test
|
||||
public void configureKerberosProvider() {
|
||||
createKerberosUserProvider.navigateTo();
|
||||
createKerberosUserProvider.form().setConsoleDisplayNameInput("kerberos");
|
||||
createKerberosUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");
|
||||
createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
|
||||
createKerberosUserProvider.form().setKeyTabInput("http.keytab");
|
||||
createKerberosUserProvider.form().setDebugEnabled(true);
|
||||
createKerberosUserProvider.form().setAllowPasswordAuthentication(true);
|
||||
createKerberosUserProvider.form().selectEditMode(READ_ONLY);
|
||||
createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
|
||||
createKerberosUserProvider.form().save();
|
||||
assertFlashMessageSuccess();
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
||||
assertKerberosSetings(ufpr, "KEYCLOAK.ORG", "HTTP/localhost@KEYCLOAK.ORG", "http.keytab", "true", "true", "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidSettingsTest() {
|
||||
createKerberosUserProvider.navigateTo();
|
||||
createKerberosUserProvider.form().setConsoleDisplayNameInput("kerberos");
|
||||
createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
|
||||
createKerberosUserProvider.form().setKeyTabInput("http.keytab");
|
||||
createKerberosUserProvider.form().setDebugEnabled(true);
|
||||
createKerberosUserProvider.form().setAllowPasswordAuthentication(true);
|
||||
createKerberosUserProvider.form().selectEditMode(UNSYNCED);
|
||||
createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
|
||||
createKerberosUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createKerberosUserProvider.form().setServerPrincipalInput("");
|
||||
createKerberosUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");;
|
||||
createKerberosUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");;
|
||||
createKerberosUserProvider.form().setKeyTabInput("");
|
||||
createKerberosUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createKerberosUserProvider.form().setKeyTabInput("http.keytab");;
|
||||
createKerberosUserProvider.form().save();
|
||||
assertFlashMessageSuccess();
|
||||
}
|
||||
|
||||
private void assertKerberosSetings(UserFederationProviderRepresentation ufpr, String kerberosRealm, String serverPrincipal, String keyTab, String debug, String useKerberosForPasswordAuthentication, String updateProfileFirstLogin) {
|
||||
assertEquals(kerberosRealm, ufpr.getConfig().get("kerberosRealm"));
|
||||
assertEquals(serverPrincipal, ufpr.getConfig().get("serverPrincipal"));
|
||||
assertEquals(keyTab, ufpr.getConfig().get("keyTab"));
|
||||
assertEquals(debug, ufpr.getConfig().get("debug"));
|
||||
assertEquals(useKerberosForPasswordAuthentication, ufpr.getConfig().get("allowKerberosAuthentication"));
|
||||
assertEquals(updateProfileFirstLogin, ufpr.getConfig().get("updateProfileFirstLogin"));
|
||||
}
|
||||
}
|
|
@ -1,71 +1,192 @@
|
|||
package org.keycloak.testsuite.console.federation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.*;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||
import org.keycloak.testsuite.console.page.federation.LdapUserProviderForm;
|
||||
import org.keycloak.testsuite.console.page.federation.UserFederation;
|
||||
import org.keycloak.testsuite.console.page.users.Users;
|
||||
import org.keycloak.testsuite.util.LDAPTestConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
|
||||
import static org.keycloak.testsuite.admin.Users.setPasswordFor;
|
||||
import org.keycloak.testsuite.console.page.federation.CreateLdapUserProvider;
|
||||
import org.keycloak.util.ldap.LDAPEmbeddedServer;
|
||||
|
||||
/**
|
||||
* Created by fkiss.
|
||||
* @author fkiss, pdrozd
|
||||
*/
|
||||
public class LdapUserFederationTest extends AbstractConsoleTest {
|
||||
|
||||
@Page
|
||||
private LdapUserProviderForm ldapUserProviderForm;
|
||||
private static final String UNSYNCED = "UNSYNCED";
|
||||
|
||||
private static final String READ_ONLY = "READ_ONLY";
|
||||
|
||||
private static final String RED_HAT_DIRECTORY_SERVER = "Red Hat Directory Server";
|
||||
|
||||
private static final String WRITABLE = "WRITABLE";
|
||||
|
||||
private static final String ACTIVE_DIRECTORY = "Active Directory";
|
||||
|
||||
@Page
|
||||
private UserFederation userFederationPage;
|
||||
private CreateLdapUserProvider createLdapUserProvider;
|
||||
|
||||
@Page
|
||||
private Users usersPage;
|
||||
|
||||
@Before
|
||||
public void beforeTestLdapUserFederation() {
|
||||
//configure().userFederation();
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void addAndConfigureProvider() {
|
||||
adminConsolePage.navigateTo();
|
||||
testRealmLoginPage.form().login(testUser);
|
||||
public void configureAdProvider() {
|
||||
createLdapUserProvider.navigateTo();
|
||||
createLdapUserProvider.form().selectVendor(ACTIVE_DIRECTORY);
|
||||
createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
|
||||
createLdapUserProvider.form().selectEditMode(WRITABLE);
|
||||
createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
|
||||
createLdapUserProvider.form().setLdapBindDnInput("KEYCLOAK/Administrator");
|
||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||
createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(false);
|
||||
// enable kerberos
|
||||
createLdapUserProvider.form().setAllowKerberosAuthEnabled(true);
|
||||
createLdapUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");
|
||||
createLdapUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
|
||||
createLdapUserProvider.form().setKeyTabInput("http.keytab");
|
||||
createLdapUserProvider.form().setDebugEnabled(true);
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageSuccess();
|
||||
|
||||
String name = "ldapname";
|
||||
|
||||
String LDAP_CONNECTION_PROPERTIES_LOCATION = "ldap/ldap-connection.properties";
|
||||
LDAPTestConfiguration ldapTestConfiguration = LDAPTestConfiguration.readConfiguration(LDAP_CONNECTION_PROPERTIES_LOCATION);
|
||||
|
||||
UserRepresentation newUser = new UserRepresentation();
|
||||
String testUsername = "defaultrole tester";
|
||||
newUser.setUsername(testUsername);
|
||||
setPasswordFor(newUser, PASSWORD);
|
||||
|
||||
Map<String,String> ldapConfig = ldapTestConfiguration.getLDAPConfig();
|
||||
|
||||
//addLdapProviderTest
|
||||
configure().userFederation();
|
||||
userFederationPage.addProvider("ldap");
|
||||
ldapUserProviderForm.configureLdap(ldapConfig.get(LDAPConstants.LDAP_PROVIDER), ldapConfig.get(LDAPConstants.EDIT_MODE), ldapConfig.get(LDAPConstants.VENDOR), ldapConfig.get(LDAPConstants.CONNECTION_URL), ldapConfig.get(LDAPConstants.USERS_DN), ldapConfig.get(LDAPConstants.BIND_DN), ldapConfig.get(LDAPConstants.BIND_CREDENTIAL));
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
||||
assertLdapProviderSetting(ufpr, "ldap", 0, WRITABLE, "false", "ad", "1", "true", "true", "false");
|
||||
assertLdapBasicMapping(ufpr, "cn", "cn", "objectGUID", "person, organizationalPerson, user",
|
||||
"ou=People,dc=keycloak,dc=org");
|
||||
assertLdapSyncSetings(ufpr, "1000", 0, 0);
|
||||
assertLdapKerberosSetings(ufpr, "KEYCLOAK.ORG", "HTTP/localhost@KEYCLOAK.ORG", "http.keytab", "true", "false");
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void caseSensitiveSearch() {
|
||||
// This should fail for now due to case-sensitivity
|
||||
adminConsolePage.navigateTo();
|
||||
testRealmLoginPage.form().login("johnKeycloak", "Password1");
|
||||
assertTrue(flashMessage.getText(), flashMessage.isDanger());
|
||||
public void configureRhdsProvider() {
|
||||
createLdapUserProvider.navigateTo();
|
||||
createLdapUserProvider.form().selectVendor(RED_HAT_DIRECTORY_SERVER);
|
||||
createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
|
||||
createLdapUserProvider.form().selectEditMode(READ_ONLY);
|
||||
createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
|
||||
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
|
||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageSuccess();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
||||
assertLdapProviderSetting(ufpr, "ldap", 0, READ_ONLY, "false", "rhds", "1", "true", "true", "true");
|
||||
assertLdapBasicMapping(ufpr, "uid", "uid", "nsuniqueid", "inetOrgPerson, organizationalPerson",
|
||||
"ou=People,dc=keycloak,dc=org");
|
||||
assertLdapSyncSetings(ufpr, "1000", 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidSettingsTest() {
|
||||
createLdapUserProvider.navigateTo();
|
||||
createLdapUserProvider.form().selectVendor(ACTIVE_DIRECTORY);
|
||||
createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
|
||||
createLdapUserProvider.form().selectEditMode(UNSYNCED);
|
||||
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
|
||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createLdapUserProvider.form().setLdapUserDnInput("");
|
||||
createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||
createLdapUserProvider.form().setLdapBindDnInput("");
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("");
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageDanger();
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageSuccess();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnection() throws Exception {
|
||||
createLdapUserProvider.navigateTo();
|
||||
createLdapUserProvider.form().selectVendor("Other");
|
||||
createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
|
||||
createLdapUserProvider.form().selectEditMode(WRITABLE);
|
||||
createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:10389");
|
||||
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
|
||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||
createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(true);
|
||||
createLdapUserProvider.form().save();
|
||||
assertFlashMessageSuccess();
|
||||
LDAPEmbeddedServer ldapServer = null;
|
||||
try {
|
||||
ldapServer = startEmbeddedLdapServer();
|
||||
createLdapUserProvider.form().testConnection();
|
||||
assertFlashMessageSuccess();
|
||||
createLdapUserProvider.form().testAuthentication();
|
||||
assertFlashMessageSuccess();
|
||||
createLdapUserProvider.form().synchronizeAllUsers();
|
||||
assertFlashMessageSuccess();
|
||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret1");
|
||||
createLdapUserProvider.form().testAuthentication();
|
||||
assertFlashMessageDanger();
|
||||
} finally {
|
||||
if (ldapServer != null) {
|
||||
ldapServer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertLdapProviderSetting(UserFederationProviderRepresentation ufpr, String name, int priority,
|
||||
String editMode, String syncRegistrations, String vendor, String searchScope, String connectionPooling,
|
||||
String pagination, String enableAccountAfterPasswordUpdate) {
|
||||
assertEquals(name, ufpr.getDisplayName());
|
||||
assertEquals(priority, ufpr.getPriority());
|
||||
assertEquals(editMode, ufpr.getConfig().get("editMode"));
|
||||
assertEquals(syncRegistrations, ufpr.getConfig().get("syncRegistrations"));
|
||||
assertEquals(vendor, ufpr.getConfig().get("vendor"));
|
||||
assertEquals(searchScope, ufpr.getConfig().get("searchScope"));
|
||||
assertEquals(connectionPooling, ufpr.getConfig().get("connectionPooling"));
|
||||
assertEquals(pagination, ufpr.getConfig().get("pagination"));
|
||||
assertEquals(enableAccountAfterPasswordUpdate, ufpr.getConfig().get("userAccountControlsAfterPasswordUpdate"));
|
||||
}
|
||||
|
||||
private void assertLdapBasicMapping(UserFederationProviderRepresentation ufpr, String usernameLdapAttribute,
|
||||
String rdnLdapAttr, String uuidLdapAttr, String userObjectClasses, String userDN) {
|
||||
assertEquals(usernameLdapAttribute, ufpr.getConfig().get("usernameLDAPAttribute"));
|
||||
assertEquals(rdnLdapAttr, ufpr.getConfig().get("rdnLDAPAttribute"));
|
||||
assertEquals(uuidLdapAttr, ufpr.getConfig().get("uuidLDAPAttribute"));
|
||||
assertEquals(userObjectClasses, ufpr.getConfig().get("userObjectClasses"));
|
||||
assertEquals(userDN, ufpr.getConfig().get("usersDn"));
|
||||
}
|
||||
|
||||
private void assertLdapKerberosSetings(UserFederationProviderRepresentation ufpr, String kerberosRealm,
|
||||
String serverPrincipal, String keyTab, String debug, String useKerberosForPasswordAuthentication) {
|
||||
assertEquals(kerberosRealm, ufpr.getConfig().get("kerberosRealm"));
|
||||
assertEquals(serverPrincipal, ufpr.getConfig().get("serverPrincipal"));
|
||||
assertEquals(keyTab, ufpr.getConfig().get("keyTab"));
|
||||
assertEquals(debug, ufpr.getConfig().get("debug"));
|
||||
assertEquals(useKerberosForPasswordAuthentication,
|
||||
ufpr.getConfig().get("useKerberosForPasswordAuthentication"));
|
||||
}
|
||||
|
||||
private void assertLdapSyncSetings(UserFederationProviderRepresentation ufpr, String batchSize,
|
||||
int periodicFullSync, int periodicChangedUsersSync) {
|
||||
assertEquals(batchSize, ufpr.getConfig().get("batchSizeForSync"));
|
||||
assertEquals(periodicFullSync, ufpr.getFullSyncPeriod());
|
||||
assertEquals(periodicChangedUsersSync, ufpr.getChangedSyncPeriod());
|
||||
}
|
||||
|
||||
private LDAPEmbeddedServer startEmbeddedLdapServer() throws Exception {
|
||||
Properties defaultProperties = new Properties();
|
||||
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_DSF, LDAPEmbeddedServer.DSF_INMEMORY);
|
||||
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_LDIF_FILE, "classpath:ldap/users.ldif");
|
||||
LDAPEmbeddedServer ldapEmbeddedServer = new LDAPEmbeddedServer(defaultProperties);
|
||||
ldapEmbeddedServer.init();
|
||||
ldapEmbeddedServer.start();
|
||||
return ldapEmbeddedServer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
dn: dc=keycloak,dc=org
|
||||
objectclass: dcObject
|
||||
objectclass: organization
|
||||
o: Keycloak
|
||||
dc: Keycloak
|
||||
|
||||
dn: ou=People,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: People
|
||||
|
||||
dn: ou=RealmRoles,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: RealmRoles
|
||||
|
||||
dn: ou=FinanceRoles,dc=keycloak,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: FinanceRoles
|
Loading…
Reference in a new issue