diff --git a/documentation/src/main/asciidoc/stories/assembly_server_security_realm.adoc b/documentation/src/main/asciidoc/stories/assembly_server_security_realm.adoc index 1c02cf78c260..528b1da96817 100644 --- a/documentation/src/main/asciidoc/stories/assembly_server_security_realm.adoc +++ b/documentation/src/main/asciidoc/stories/assembly_server_security_realm.adoc @@ -10,6 +10,7 @@ include::{topics}/ref_server_realm_ldap.adoc[leveloffset=+1] include::{topics}/ref_server_realm_ldap_rewrite.adoc[leveloffset=+2] include::{topics}/ref_server_realm_trust.adoc[leveloffset=+1] include::{topics}/ref_server_realm_token.adoc[leveloffset=+1] +include::{topics}/ref_server_realm_distributed.adoc[leveloffset=+1] // Restore the parent context. ifdef::parent-context[:context: {parent-context}] diff --git a/documentation/src/main/asciidoc/topics/config_examples/server_distributed_realm.xml b/documentation/src/main/asciidoc/topics/config_examples/server_distributed_realm.xml new file mode 100644 index 000000000000..575ee92edf63 --- /dev/null +++ b/documentation/src/main/asciidoc/topics/config_examples/server_distributed_realm.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/documentation/src/main/asciidoc/topics/ref_server_realm_distributed.adoc b/documentation/src/main/asciidoc/topics/ref_server_realm_distributed.adoc new file mode 100644 index 000000000000..0c87c694dbf7 --- /dev/null +++ b/documentation/src/main/asciidoc/topics/ref_server_realm_distributed.adoc @@ -0,0 +1,14 @@ +[id='distributed_realm-{context}'] += Distributed Realms +A security realm definition for authentication and authorization identities distributed between multiple security realms. + +.Distributed realm configuration + +[source,xml,options="nowrap",subs=attributes+] +---- +include::config_examples/server_distributed_realm.xml[] +---- + +.Supported authentication mechanisms + +Distributed realms support the authentication mechanisms of the underlying realms. \ No newline at end of file diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/Attribute.java b/server/runtime/src/main/java/org/infinispan/server/configuration/Attribute.java index c3c4843a5f26..d7cbc3479ceb 100644 --- a/server/runtime/src/main/java/org/infinispan/server/configuration/Attribute.java +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/Attribute.java @@ -14,6 +14,8 @@ public enum Attribute { AUDIENCE, AUTH_SERVER_URL, CACHE_CONTAINER, + CACHE_LIFESPAN, + CACHE_MAX_SIZE, CLIENT_ID, CLIENT_SECRET, CLIENT_SSL_CONTEXT, @@ -22,6 +24,7 @@ public enum Attribute { CREDENTIAL, DEBUG, DEFAULT_INTERFACE, + DEFAULT_REALM, DIGEST_REALM_NAME, DIRECT_VERIFICATION, ENABLED_CIPHERSUITES, @@ -63,6 +66,7 @@ public enum Attribute { PUBLIC_KEY, RDN_IDENTIFIER, READ_TIMEOUT, + REALMS, RECEIVE_BUFFER_SIZE, REFERENCE, REFERRAL_MODE, diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/Element.java b/server/runtime/src/main/java/org/infinispan/server/configuration/Element.java index 1514061030b8..b6dba91aab3b 100644 --- a/server/runtime/src/main/java/org/infinispan/server/configuration/Element.java +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/Element.java @@ -14,6 +14,10 @@ public enum Element { ATTRIBUTE, ATTRIBUTE_MAPPING, ATTRIBUTE_REFERENCE, + BINDINGS, + CONNECTION_PROPERTIES, + CONNECTORS, + DISTRIBUTED_REALM, ENDPOINTS, ENGINE, FILESYSTEM_REALM, @@ -69,9 +73,7 @@ public enum Element { IP_FILTER, ACCEPT, REJECT, - BINDINGS, - CONNECTION_PROPERTIES, - CONNECTORS; + ; private static final Map ELEMENTS; diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/ServerConfigurationParser.java b/server/runtime/src/main/java/org/infinispan/server/configuration/ServerConfigurationParser.java index f847f6496f91..be47e4a26f51 100644 --- a/server/runtime/src/main/java/org/infinispan/server/configuration/ServerConfigurationParser.java +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/ServerConfigurationParser.java @@ -20,6 +20,7 @@ import org.infinispan.server.configuration.endpoint.EndpointConfigurationBuilder; import org.infinispan.server.configuration.security.CredentialStoreConfigurationBuilder; import org.infinispan.server.configuration.security.CredentialStoresConfigurationBuilder; +import org.infinispan.server.configuration.security.DistributedRealmConfigurationBuilder; import org.infinispan.server.configuration.security.FileSystemRealmConfigurationBuilder; import org.infinispan.server.configuration.security.GroupsPropertiesConfigurationBuilder; import org.infinispan.server.configuration.security.JwtConfigurationBuilder; @@ -101,8 +102,7 @@ public void readElement(ConfigurationReader reader, ConfigurationBuilderHolder h } } - private void parseServerElements(ConfigurationReader reader, ConfigurationBuilderHolder holder, ServerConfigurationBuilder builder) - { + private void parseServerElements(ConfigurationReader reader, ConfigurationBuilderHolder holder, ServerConfigurationBuilder builder) { Element element = nextElement(reader); if (element == Element.INTERFACES) { parseInterfaces(reader, builder); @@ -346,7 +346,7 @@ private void parseCredentialStore(ConfigurationReader reader, ServerConfiguratio } private String parseCredentialReference(ConfigurationReader reader, ServerConfigurationBuilder builder) { - switch(Element.forName(reader.getLocalName())) { + switch (Element.forName(reader.getLocalName())) { case CREDENTIAL_REFERENCE: { String store = null; String alias = null; @@ -396,6 +396,25 @@ private void parseSecurityRealms(ConfigurationReader reader, ServerConfiguration private void parseSecurityRealm(ConfigurationReader reader, ServerConfigurationBuilder builder, RealmsConfigurationBuilder realms) { String name = ParseUtils.requireAttributes(reader, Attribute.NAME)[0]; RealmConfigurationBuilder securityRealmBuilder = realms.addSecurityRealm(name); + for(int i = 0; i < reader.getAttributeCount(); i++) { + ParseUtils.requireNoNamespaceAttribute(reader, i); + String value = reader.getAttributeValue(i); + Attribute attribute = Attribute.forName(reader.getAttributeName(i)); + switch (attribute) { + case NAME: + // Already seen + break; + case DEFAULT_REALM: + securityRealmBuilder.defaultRealm(value); + break; + case CACHE_MAX_SIZE: + securityRealmBuilder.cacheMaxSize(Integer.parseInt(value)); + break; + case CACHE_LIFESPAN: + securityRealmBuilder.cacheLifespan(Long.parseLong(value)); + break; + } + } Element element = nextElement(reader); if (element == Element.SERVER_IDENTITIES) { parseServerIdentities(reader, builder, securityRealmBuilder); @@ -429,6 +448,10 @@ private void parseSecurityRealm(ConfigurationReader reader, ServerConfigurationB } element = nextElement(reader); } + if (element == Element.DISTRIBUTED_REALM) { + parseDistributedRealm(reader, securityRealmBuilder.distributedConfiguration()); + element = nextElement(reader); + } if (element != null) { throw ParseUtils.unexpectedElement(reader, element); } @@ -899,6 +922,28 @@ private void parsePropertiesRealm(ConfigurationReader reader, PropertiesRealmCon propertiesBuilder.build(); } + private void parseDistributedRealm(ConfigurationReader reader, DistributedRealmConfigurationBuilder distributedRealmBuilder) { + String name = "distributed"; + String[] realms = ParseUtils.requireAttributes(reader, Attribute.REALMS)[0].split("\\s+"); + for (int i = 0; i < reader.getAttributeCount(); i++) { + ParseUtils.requireNoNamespaceAttribute(reader, i); + String value = reader.getAttributeValue(i); + Attribute attribute = Attribute.forName(reader.getAttributeName(i)); + switch (attribute) { + case NAME: + name = value; + break; + case REALMS: + // Already seen + break; + default: + throw ParseUtils.unexpectedAttribute(reader, i); + } + } + ParseUtils.requireNoContent(reader); + distributedRealmBuilder.name(name).realms(realms).build(); + } + private void parseServerIdentities(ConfigurationReader reader, ServerConfigurationBuilder builder, RealmConfigurationBuilder securityRealmBuilder) { ServerIdentitiesConfigurationBuilder identitiesBuilder = securityRealmBuilder.serverIdentitiesConfiguration(); Element element = nextElement(reader); diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/security/DistributedRealmConfiguration.java b/server/runtime/src/main/java/org/infinispan/server/configuration/security/DistributedRealmConfiguration.java new file mode 100644 index 000000000000..4b98048c7f91 --- /dev/null +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/security/DistributedRealmConfiguration.java @@ -0,0 +1,40 @@ +package org.infinispan.server.configuration.security; + +import java.util.ArrayList; +import java.util.List; + +import org.infinispan.commons.configuration.ConfigurationInfo; +import org.infinispan.commons.configuration.attributes.AttributeDefinition; +import org.infinispan.commons.configuration.attributes.AttributeSet; +import org.infinispan.commons.configuration.elements.DefaultElementDefinition; +import org.infinispan.commons.configuration.elements.ElementDefinition; +import org.infinispan.server.configuration.Element; + +/** + * @author Tristan Tarrant <tristan@infinispan.org> + * @since 13.0 + **/ +public class DistributedRealmConfiguration implements ConfigurationInfo { + static final AttributeDefinition NAME = AttributeDefinition.builder("name", null, String.class).build(); + static final AttributeDefinition> REALMS = AttributeDefinition.builder("realms", new ArrayList<>(), (Class>) (Class) List.class) + .initializer(ArrayList::new).immutable().build(); + + static AttributeSet attributeDefinitionSet() { + return new AttributeSet(DistributedRealmConfiguration.class, NAME, REALMS); + } + + private static ElementDefinition ELEMENT_DEFINITION = new DefaultElementDefinition(Element.TOKEN_REALM.toString()); + private final AttributeSet attributes; + + DistributedRealmConfiguration(AttributeSet attributes) { + this.attributes = attributes.checkProtection(); + } + + public String name() { + return attributes.attribute(NAME).get(); + } + + public List realms() { + return attributes.attribute(REALMS).get(); + } +} diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/security/DistributedRealmConfigurationBuilder.java b/server/runtime/src/main/java/org/infinispan/server/configuration/security/DistributedRealmConfigurationBuilder.java new file mode 100644 index 000000000000..b884bdc608e3 --- /dev/null +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/security/DistributedRealmConfigurationBuilder.java @@ -0,0 +1,65 @@ +package org.infinispan.server.configuration.security; + +import static org.infinispan.server.configuration.security.DistributedRealmConfiguration.NAME; +import static org.infinispan.server.configuration.security.DistributedRealmConfiguration.REALMS; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.infinispan.commons.configuration.Builder; +import org.infinispan.commons.configuration.attributes.AttributeSet; +import org.wildfly.security.auth.realm.DistributedSecurityRealm; +import org.wildfly.security.auth.server.SecurityRealm; + +/** + * @author Tristan Tarrant <tristan@infinispan.org> + * @since 13.0 + **/ +public class DistributedRealmConfigurationBuilder implements Builder { + + private final RealmConfigurationBuilder realmBuilder; + private final AttributeSet attributes; + private DistributedSecurityRealm securityRealm; + + + public DistributedRealmConfigurationBuilder(RealmConfigurationBuilder realmConfigurationBuilder) { + this.realmBuilder = realmConfigurationBuilder; + this.attributes = DistributedRealmConfiguration.attributeDefinitionSet(); + } + + public DistributedRealmConfigurationBuilder name(String name) { + attributes.attribute(NAME).set(name); + return this; + } + + public DistributedRealmConfigurationBuilder realms(String[] realms) { + attributes.attribute(REALMS).set(Arrays.asList(realms)); + return this; + } + + @Override + public void validate() { + + } + + @Override + public DistributedRealmConfiguration create() { + return new DistributedRealmConfiguration(attributes.protect()); + } + + @Override + public Builder read(DistributedRealmConfiguration template) { + attributes.read(template.attributes()); + return this; + } + + public void build() { + if (securityRealm == null) { + SecurityRealm realms[] = attributes.attribute(REALMS).get() + .stream().map(name -> realmBuilder.getRealm(name)).toArray(SecurityRealm[]::new); + securityRealm = new DistributedSecurityRealm(realms); + realmBuilder.addRealm(attributes.attribute(NAME).get(), securityRealm); + } + } +} diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfiguration.java b/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfiguration.java index 18e45ccdcbc2..80a6c16b263d 100644 --- a/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfiguration.java +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfiguration.java @@ -14,12 +14,13 @@ * @since 10.0 */ public class RealmConfiguration implements ConfigurationInfo { - static final AttributeDefinition NAME = AttributeDefinition.builder("name", null, String.class).build(); - static final AttributeDefinition CACHE_MAX_SIZE = AttributeDefinition.builder("cacheMaxSize", 256).build(); - static final AttributeDefinition CACHE_LIFESPAN = AttributeDefinition.builder("lifespan", -1l).build(); + static final AttributeDefinition NAME = AttributeDefinition.builder("name", null, String.class).immutable().build(); + static final AttributeDefinition DEFAULT_REALM = AttributeDefinition.builder("defaultRealm", null, String.class).immutable().build(); + static final AttributeDefinition CACHE_MAX_SIZE = AttributeDefinition.builder("cacheMaxSize", 256).immutable().build(); + static final AttributeDefinition CACHE_LIFESPAN = AttributeDefinition.builder("lifespan", -1l).immutable().build(); static AttributeSet attributeDefinitionSet() { - return new AttributeSet(RealmConfiguration.class, NAME, CACHE_MAX_SIZE, CACHE_LIFESPAN); + return new AttributeSet(RealmConfiguration.class, NAME, DEFAULT_REALM, CACHE_MAX_SIZE, CACHE_LIFESPAN); } private static ElementDefinition ELEMENT_DEFINITION = new DefaultElementDefinition(Element.SECURITY_REALM.toString()); diff --git a/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfigurationBuilder.java b/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfigurationBuilder.java index 8de4c53d3846..6acc65538c2b 100644 --- a/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfigurationBuilder.java +++ b/server/runtime/src/main/java/org/infinispan/server/configuration/security/RealmConfigurationBuilder.java @@ -2,9 +2,12 @@ import static org.infinispan.server.configuration.security.RealmConfiguration.CACHE_LIFESPAN; import static org.infinispan.server.configuration.security.RealmConfiguration.CACHE_MAX_SIZE; +import static org.infinispan.server.configuration.security.RealmConfiguration.DEFAULT_REALM; import java.security.GeneralSecurityException; import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; import java.util.function.Consumer; import java.util.function.Supplier; @@ -43,6 +46,8 @@ public class RealmConfigurationBuilder implements Builder { private final TokenRealmConfigurationBuilder tokenConfiguration = new TokenRealmConfigurationBuilder(this); private final TrustStoreRealmConfigurationBuilder trustStoreConfiguration = new TrustStoreRealmConfigurationBuilder(this); private final PropertiesRealmConfigurationBuilder propertiesRealmConfiguration = new PropertiesRealmConfigurationBuilder(this); + private final DistributedRealmConfigurationBuilder distributedConfiguration = new DistributedRealmConfigurationBuilder(this); + private final Map realms = new HashMap<>(); private SSLContext sslContext = null; private SSLContextBuilder sslContextBuilder = null; @@ -73,6 +78,12 @@ SecurityDomain.Builder domainBuilder() { return domainBuilder; } + public RealmConfigurationBuilder defaultRealm(String defaultRealm) { + this.attributes.attribute(DEFAULT_REALM).set(defaultRealm); + domainBuilder.setDefaultRealmName(defaultRealm); + return this; + } + public RealmConfigurationBuilder cacheMaxSize(int size) { this.attributes.attribute(CACHE_MAX_SIZE).set(size); return this; @@ -111,6 +122,10 @@ public PropertiesRealmConfigurationBuilder propertiesRealm() { return propertiesRealmConfiguration; } + public DistributedRealmConfigurationBuilder distributedConfiguration() { + return distributedConfiguration; + } + void setHttpChallengeReadiness(Supplier readiness) { this.httpChallengeReadiness = readiness; } @@ -206,7 +221,9 @@ public void addRealm(String realmName, SecurityRealm realm) { } public void addRealm(String realmName, SecurityRealm realm, Consumer realmBuilderConsumer) { - SecurityDomain.RealmBuilder realmBuilder = domainBuilder.addRealm(realmName, cacheable(realm)); + SecurityRealm securityRealm = cacheable(realm); + realms.put(realmName, securityRealm); + SecurityDomain.RealmBuilder realmBuilder = domainBuilder.addRealm(realmName, securityRealm); if (realmBuilderConsumer != null) { realmBuilderConsumer.accept(realmBuilder); } @@ -216,4 +233,8 @@ public void addRealm(String realmName, SecurityRealm realm, Consumer + + + + + Specifies which of the underlying realms will be used by default. It defaults to the first realm. + + + @@ -1565,4 +1573,22 @@ + + + + + A realm definition for authentication and authorization of identities distributed between multiple realms. + + + + + + + A list of security realms that should be used for authentication until one succeeds. + At least one realm must be specified. + + + + + diff --git a/server/tests/src/test/java/org/infinispan/server/security/AuthenticationLDAPIT.java b/server/tests/src/test/java/org/infinispan/server/security/AuthenticationLDAPIT.java index 65981667342a..e054797cb267 100644 --- a/server/tests/src/test/java/org/infinispan/server/security/AuthenticationLDAPIT.java +++ b/server/tests/src/test/java/org/infinispan/server/security/AuthenticationLDAPIT.java @@ -57,8 +57,8 @@ public void testReadWrite() { .saslMechanism(mechanism) .serverName("infinispan") .realm("default") - .username("admin") - .password("strongPassword"); + .username("admin_user") + .password("admin_user"); } try { diff --git a/server/tests/src/test/java/org/infinispan/server/security/AuthenticationMultiRealmIT.java b/server/tests/src/test/java/org/infinispan/server/security/AuthenticationMultiRealmIT.java new file mode 100644 index 000000000000..20fe5fb01093 --- /dev/null +++ b/server/tests/src/test/java/org/infinispan/server/security/AuthenticationMultiRealmIT.java @@ -0,0 +1,86 @@ +package org.infinispan.server.security; + +import static org.junit.Assert.assertEquals; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.server.test.api.TestUser; +import org.infinispan.server.test.core.LdapServerListener; +import org.infinispan.server.test.core.category.Security; +import org.infinispan.server.test.junit4.InfinispanServerRule; +import org.infinispan.server.test.junit4.InfinispanServerRuleBuilder; +import org.infinispan.server.test.junit4.InfinispanServerTestMethodRule; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +/** + * @author Tristan Tarrant <tristan@infinispan.org> + * @since 13.0 + **/ + +@Category(Security.class) +public class AuthenticationMultiRealmIT { + @ClassRule + public static InfinispanServerRule SERVERS = + InfinispanServerRuleBuilder.config("configuration/AuthenticationMultiRealm.xml") + .addListener(new LdapServerListener()) + .build(); + + @Rule + public InfinispanServerTestMethodRule SERVER_TEST = new InfinispanServerTestMethodRule(SERVERS); + + public AuthenticationMultiRealmIT() { + } + + @Test + public void testLDAP() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + SERVERS.getServerDriver().applyTrustStore(builder, "ca"); + builder.security().authentication() + .saslMechanism("SCRAM-SHA-256") + .serverName("infinispan") + .realm("default") + .username(TestUser.ADMIN.getUser()) + .password(TestUser.ADMIN.getPassword()); + performOperations(builder); + } + + @Test + public void testProps() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + SERVERS.getServerDriver().applyTrustStore(builder, "ca"); + builder.security().authentication() + .saslMechanism("SCRAM-SHA-256") + .serverName("infinispan") + .realm("default") + .username("all_user") + .password("all"); + performOperations(builder); + } + + @Test + @Ignore + public void testCert() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.maxRetries(1).connectionPool().maxActive(1); + SERVERS.getServerDriver().applyTrustStore(builder, "ca"); + SERVERS.getServerDriver().applyKeyStore(builder, "admin"); + builder.security() + .authentication() + .saslMechanism("EXTERNAL") + .serverName("infinispan") + .realm("default"); + performOperations(builder); + } + + private void performOperations(ConfigurationBuilder builder) { + RemoteCache cache = SERVER_TEST.hotrod().withClientConfiguration(builder).withCacheMode(CacheMode.DIST_SYNC).create(); + cache.put("k1", "v1"); + assertEquals(1, cache.size()); + assertEquals("v1", cache.get("k1")); + } +} diff --git a/server/tests/src/test/java/org/infinispan/server/test/core/Common.java b/server/tests/src/test/java/org/infinispan/server/test/core/Common.java index b9151042c6bf..db1738faef0e 100644 --- a/server/tests/src/test/java/org/infinispan/server/test/core/Common.java +++ b/server/tests/src/test/java/org/infinispan/server/test/core/Common.java @@ -22,7 +22,6 @@ import org.infinispan.client.rest.RestResponse; import org.infinispan.client.rest.configuration.Protocol; import org.infinispan.commons.test.Exceptions; -import org.infinispan.security.AuthorizationPermission; import org.infinispan.test.TestingUtil; import org.wildfly.security.http.HttpConstants; import org.wildfly.security.sasl.util.SaslMechanismInformation; @@ -34,8 +33,6 @@ public class Common { private static final boolean IS_IBM = System.getProperty("java.vendor").contains("IBM"); - public static final Map USER_MAP; - public static final Collection SASL_MECHS; public static final Collection SASL_KERBEROS_MECHS; @@ -47,14 +44,6 @@ public class Common { public static final Collection HTTP_PROTOCOLS = Arrays.asList(Protocol.values()); static { - USER_MAP = new HashMap<>(); - USER_MAP.put("admin", new User("admin", "adminPassword", AuthorizationPermission.ALL.name())); - USER_MAP.put("supervisor", new User("supervisorPassword", AuthorizationPermission.ALL_READ.name(), AuthorizationPermission.ALL_WRITE.name())); - USER_MAP.put("reader", new User("reader", "readerPassword", AuthorizationPermission.ALL_READ.name())); - USER_MAP.put("writer", new User("writer", "writerPassword", AuthorizationPermission.ALL_WRITE.name())); - USER_MAP.put("unprivileged", new User("unprivileged", "unprivilegedPassword", AuthorizationPermission.NONE.name())); - USER_MAP.put("executor", new User("executor", "executorPassword", AuthorizationPermission.EXEC.name())); - SASL_MECHS = new ArrayList<>(); SASL_MECHS.add(new Object[]{""}); SASL_MECHS.add(new Object[]{SaslMechanismInformation.Names.PLAIN}); @@ -96,18 +85,6 @@ public static RestResponse awaitStatus(Supplier> r return response; } - public static class User { - final String username; - final char[] password; - final Iterable groups; - - public User(String username, String password, String... groups) { - this.username = username; - this.password = password.toCharArray(); - this.groups = Arrays.asList(groups); - } - } - public static T sync(CompletionStage stage) { return Exceptions.unchecked(() -> stage.toCompletableFuture().get(5, TimeUnit.SECONDS)); } diff --git a/server/tests/src/test/resources/configuration/AuthenticationMultiRealm.xml b/server/tests/src/test/resources/configuration/AuthenticationMultiRealm.xml new file mode 100644 index 000000000000..67bc54874f94 --- /dev/null +++ b/server/tests/src/test/resources/configuration/AuthenticationMultiRealm.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/server/tests/src/test/resources/configuration/security/multi.xml b/server/tests/src/test/resources/configuration/security/multi.xml new file mode 100644 index 000000000000..dafbf3582772 --- /dev/null +++ b/server/tests/src/test/resources/configuration/security/multi.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +