@@ -271,6 +271,266 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-asn1</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-audit</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server-http</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server-sasl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-base</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-client</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential-source-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential-store</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-basic</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-bearer</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-cert</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-form</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-spnego</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-sso</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-jacc</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-jaspi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-json-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-keystore</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-gssapi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-http</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-scram</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-password-impl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-permission</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-token</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-auth-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-anonymous</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-entity</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-external</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-gs2</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-gssapi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-localuser</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-otp</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-plain</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-scram</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-security-manager</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-security-manager-action</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-ssl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-cert</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-cert-acme</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-cert-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-principal</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.openssl</groupId>
@@ -500,11 +760,6 @@
<artifactId>wildfly-security-manager</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-tool</artifactId>
@@ -37,7 +37,70 @@
</exports>

<resources>
<artifact name="${org.wildfly.security:wildfly-elytron}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-asn1}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-audit}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-auth}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-auth-server}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-auth-server-deprecated}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-auth-server-http}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-auth-server-sasl}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-auth-util}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-base}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-client}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-credential}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-credential-source-deprecated}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-credential-store}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-digest}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-basic}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-bearer}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-cert}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-digest}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-deprecated}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-form}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-spnego}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-sso}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-util}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-jacc}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-jaspi}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-json-util}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-keystore}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-mechanism}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-mechanism-digest}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-mechanism-http}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-mechanism-gssapi}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-mechanism-oauth2}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-mechanism-scram}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-password-impl}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-permission}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-realm}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-realm-jdbc}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-realm-ldap}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-realm-token}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-auth-util}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-anonymous}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-deprecated}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-digest}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-entity}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-external}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-gs2}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-gssapi}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-localuser}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-oauth2}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-otp}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-plain}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-sasl-scram}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-security-manager}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-security-manager-action}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-ssl}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-util}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-x500}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-x500-cert}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-x500-cert-acme}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-x500-cert-util}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-x500-deprecated}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-x500-principal}"/>
</resources>

<dependencies>
@@ -518,7 +518,262 @@
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-asn1</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-audit</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server-http</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server-sasl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-server-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-auth-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-base</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-client</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential-source-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential-store</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-basic</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-bearer</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-cert</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-form</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-spnego</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-sso</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-http-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-jacc</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-jaspi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-json-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-keystore</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-gssapi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-http</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-mechanism-scram</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-password-impl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-permission</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-token</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-auth-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-anonymous</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-entity</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-external</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-gs2</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-gssapi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-localuser</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-otp</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-plain</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-scram</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-security-manager</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-security-manager-action</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-ssl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-cert</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-cert-acme</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-cert-util</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-deprecated</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-x500-principal</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-tool</artifactId>
@@ -379,10 +379,12 @@ private static ExtensionHandlers setupOpenListener(HttpOpenListener listener, in
ROOT_LOGGER.consoleModuleNotFound(builder.consoleSlot == null ? "main" : builder.consoleSlot);
}

try {
addErrorContextHandler(pathHandler, builder);
} catch (ModuleLoadException e) {
ROOT_LOGGER.errorContextModuleNotFound(builder.consoleSlot == null ? "main" : builder.consoleSlot);
if (builder.consoleMode.hasConsole()) {
try {
addErrorContextHandler(pathHandler, builder);
} catch (ModuleLoadException e) {
ROOT_LOGGER.errorContextModuleNotFound(builder.consoleSlot == null ? "main" : builder.consoleSlot);
}
}

ManagementRootConsoleRedirectHandler rootConsoleRedirectHandler = new ManagementRootConsoleRedirectHandler(consoleHandler);
@@ -82,12 +82,12 @@
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceRegistry;
import org.wildfly.common.bytes.ByteStringBuilder;
import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.extension.elytron.FileAttributeDefinitions.PathResolver;
import org.wildfly.extension.elytron._private.ElytronSubsystemMessages;
import org.wildfly.security.credential.source.CredentialSource;
import org.wildfly.security.pem.Pem;
import org.wildfly.security.util.ByteStringBuilder;
import org.wildfly.security.x500.X500;
import org.wildfly.security.x500.cert.PKCS10CertificateSigningRequest;
import org.wildfly.security.x500.cert.SelfSignedX509CertificateAndSigningKey;
@@ -56,7 +56,7 @@
import org.wildfly.extension.elytron.FileAttributeDefinitions.PathResolver;
import org.wildfly.extension.elytron.TrivialService.ValueSupplier;
import org.wildfly.extension.elytron.capabilities.CredentialSecurityFactory;
import org.wildfly.security.asn1.util.OidsUtil;
import org.wildfly.security.asn1.OidsUtil;
import org.wildfly.security.auth.util.GSSCredentialSecurityFactory;

/**
@@ -52,7 +52,7 @@
import org.wildfly.extension.elytron.TrivialService.ValueSupplier;
import org.wildfly.extension.elytron._private.ElytronSubsystemMessages;
import org.wildfly.extension.elytron.capabilities.PrincipalTransformer;
import org.wildfly.security.asn1.util.OidsUtil;
import org.wildfly.security.asn1.OidsUtil;
import org.wildfly.security.auth.server.PrincipalDecoder;
import org.wildfly.security.x500.X500AttributePrincipalDecoder;

@@ -61,6 +61,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BooleanSupplier;
import java.util.regex.Pattern;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -92,6 +93,7 @@
import org.jboss.as.controller.operations.validation.AllowedValuesValidator;
import org.jboss.as.controller.operations.validation.IntRangeValidator;
import org.jboss.as.controller.operations.validation.ModelTypeValidator;
import org.jboss.as.controller.operations.validation.ParameterValidator;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.controller.security.CredentialReference;
@@ -302,6 +304,7 @@
.setMinSize(0)
.setAllowExpression(false)
.setCapabilityReference(SSL_CONTEXT_CAPABILITY)
.setMapValidator(new HostContextMapValidator())
.setRestartAllServices()
.build();

@@ -365,6 +368,23 @@ public void validateParameter(String parameterName, ModelNode value) throws Oper
}
}

static class HostContextMapValidator implements ParameterValidator{
// valid hosts in SNI mapping can contain letters, numbers, asterisks, dots and dashes
// dash and dot can be at most one at a time, and dash must be surrounded by [a-z0-9*]
static Pattern hostnamePattern = Pattern.compile("^([a-zA-Z0-9*]+(-[a-zA-Z0-9*]+)*\\.?)+[a-zA-Z0-9*]$");

@Override
public void validateParameter(String parameterName, ModelNode value) throws OperationFailedException {
if (value.isDefined()) {
for (String hostname : value.keys()) {
if (!hostnamePattern.matcher(hostname).matches()) {
throw ROOT_LOGGER.invalidHostContextMapValue(hostname);
}
}
}
}
}

static ResourceDefinition getKeyManagerDefinition() {

final StandardResourceDescriptionResolver RESOURCE_RESOLVER = ElytronExtension.getResourceDescriptionResolver(ElytronDescriptionConstants.KEY_MANAGER);
@@ -557,4 +557,6 @@
@Message(id = 1060, value = "Fileless KeyStore needs to have a defined type.")
OperationFailedException filelessKeyStoreMissingType();

@Message(id = 1061, value = "Value of host context map '%s' is not a valid hostname.")
OperationFailedException invalidHostContextMapValue(String hostname);
}
@@ -30,6 +30,8 @@
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.REALM;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.ROLES;

import java.util.concurrent.ThreadLocalRandom;

import org.jboss.as.controller.ObjectTypeAttributeDefinition;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
@@ -52,7 +54,6 @@
import org.wildfly.security.password.interfaces.SaltedSimpleDigestPassword;
import org.wildfly.security.password.interfaces.ScramDigestPassword;
import org.wildfly.security.password.interfaces.SimpleDigestPassword;
import org.wildfly.security.password.util.PasswordUtil;
import org.wildfly.security.permission.PermissionVerifier;

/**
@@ -299,7 +300,7 @@ public void testBcryptPassword() throws Exception {
ModelNode result = services.executeOperation(operation);
assertSuccessful(result);

byte[] salt = PasswordUtil.generateRandomSalt(BCryptPassword.BCRYPT_SALT_SIZE);
byte[] salt = generateRandomSalt(BCryptPassword.BCRYPT_SALT_SIZE);

operation = createSetPasswordOperation("default", realmAddress, principalName,
ModifiableRealmDecorator.SetPasswordHandler.Bcrypt.OBJECT_DEFINITION, "bcryptPassword", salt, 10, null, null, null, null);
@@ -353,7 +354,7 @@ public void testSaltedSimpleDigestPassword() throws Exception {
assertSuccessful(result);

operation = createSetPasswordOperation("default", realmAddress, principalName,
ModifiableRealmDecorator.SetPasswordHandler.SaltedSimpleDigest.OBJECT_DEFINITION, "saltedSimpleDigest", PasswordUtil.generateRandomSalt(16), null, null, SaltedSimpleDigestPassword.ALGORITHM_PASSWORD_SALT_DIGEST_SHA_256, null, null);
ModifiableRealmDecorator.SetPasswordHandler.SaltedSimpleDigest.OBJECT_DEFINITION, "saltedSimpleDigest", generateRandomSalt(16), null, null, SaltedSimpleDigestPassword.ALGORITHM_PASSWORD_SALT_DIGEST_SHA_256, null, null);
result = services.executeOperation(operation);
assertSuccessful(result);
}
@@ -369,7 +370,7 @@ public void testScramDigestPassword() throws Exception {
ModelNode result = services.executeOperation(operation);
assertSuccessful(result);

byte[] salt = PasswordUtil.generateRandomSalt(ScramDigestPassword.DEFAULT_SALT_SIZE);
byte[] salt = generateRandomSalt(ScramDigestPassword.DEFAULT_SALT_SIZE);
int iterationCount = ScramDigestPassword.DEFAULT_ITERATION_COUNT;

operation = createSetPasswordOperation("default", realmAddress, principalName,
@@ -582,4 +583,10 @@ public PermissionVerifier mapPermissions(PermissionMappable permissionMappable,
return PermissionVerifier.from(new LoginPermission());
}
}

private static byte[] generateRandomSalt(int saltSize) {
byte[] randomSalt = new byte[saltSize];
ThreadLocalRandom.current().nextBytes(randomSalt);
return randomSalt;
}
}
@@ -67,8 +67,7 @@ private DomainCommandBuilder(final Path wildflyHome, final Jvm jvm) {
hostControllerJavaOpts.addAll(DEFAULT_VM_ARGUMENTS);
processControllerJavaOpts = new Arguments();
processControllerJavaOpts.addAll(DEFAULT_VM_ARGUMENTS);
hostControllerJvm = Jvm.current();
serverJvm = Jvm.current();
hostControllerJvm = serverJvm = environment.getJvm();
}

/**
329 pom.xml

Large diffs are not rendered by default.

@@ -13,7 +13,7 @@ remoting.worker-task-max-threads=The maximum number of threads for the remoting
remoting.worker-task-max-threads.deprecated=Use IO subsystem worker configuration
remoting.worker-write-threads=The number of write threads to create for the remoting worker.
remoting.worker-write-threads.deprecated=Use IO subsystem worker configuration
remoting.authorize-id=The SASL authorization ID. Used as authentication user name to use if no authentication CallbackHandler is specified\
remoting.authorize-id=The SASL authorization ID. Used as authentication user name to use if no authentication CallbackHandler is specified \
and the selected SASL mechanism demands a user name.
remoting.auth-realm=The authentication realm to use if no authentication CallbackHandler is specified.
remoting.sasl-protocol=Where a SaslServer or SaslClient are created by default the protocol specified it 'remoting', this can be used to override this.
@@ -26,7 +26,7 @@ remoting.max-outbound-messages=The maximum number of concurrent outbound message
remoting.send-buffer-size=The size of the largest buffer that this endpoint will transmit over a connection.
remoting.max-inbound-messages=The maximum number of concurrent inbound messages on a channel.
remoting.receive-window-size=The maximum window size of the receive direction for connection channels, in bytes.
remoting.heartbeat-interval=The interval to use for connection heartbeat, in milliseconds. If the connection is idle in the outbound direction\
remoting.heartbeat-interval=The interval to use for connection heartbeat, in milliseconds. If the connection is idle in the outbound direction \
for this amount of time, a ping message will be sent, which will trigger a corresponding reply message.
remoting.max-inbound-message-size=The maximum inbound message size to be allowed. Messages exceeding this size will cause an exception to be thrown on the reading side as well as the writing side.
remoting.max-outbound-channels=The maximum number of outbound channels to support for a connection.
@@ -40,7 +40,7 @@ endpoint=Endpoint configuration
endpoint.add=Adds endpoint
endpoint.remove=Removes endpoint configuration
endpoint.deprecated=The child resource for configuring the remoting endpoint is deprecated. Use the attributes on the parent resource to configure the remoting endpoint.
endpoint.authorize-id=The SASL authorization ID. Used as authentication user name to use if no authentication CallbackHandler is specified\
endpoint.authorize-id=The SASL authorization ID. Used as authentication user name to use if no authentication CallbackHandler is specified \
and the selected SASL mechanism demands a user name.
endpoint.auth-realm=The authentication realm to use if no authentication CallbackHandler is specified.
endpoint.sasl-protocol=Where a SaslServer or SaslClient are created by default the protocol specified it 'remoting', this can be used to override this.
@@ -53,7 +53,7 @@ endpoint.max-outbound-messages=The maximum number of concurrent outbound message
endpoint.send-buffer-size=The size of the largest buffer that this endpoint will transmit over a connection.
endpoint.max-inbound-messages=The maximum number of concurrent inbound messages on a channel.
endpoint.receive-window-size=The maximum window size of the receive direction for connection channels, in bytes.
endpoint.heartbeat-interval=The interval to use for connection heartbeat, in milliseconds. If the connection is idle in the outbound direction\
endpoint.heartbeat-interval=The interval to use for connection heartbeat, in milliseconds. If the connection is idle in the outbound direction \
for this amount of time, a ping message will be sent, which will trigger a corresponding reply message.
endpoint.max-inbound-message-size=The maximum inbound message size to be allowed. Messages exceeding this size will cause an exception to be thrown on the reading side as well as the writing side.
endpoint.max-outbound-channels=The maximum number of outbound channels to support for a connection.
@@ -325,6 +325,11 @@
*/
public static final AttachmentKey<AttachmentList<ServiceName>> JNDI_DEPENDENCIES = AttachmentKey.createList(ServiceName.class);

/**
* Component JNDI dependencies, only attached to the top level deployment
*/
public static final AttachmentKey<Map<ServiceName, Set<ServiceName>>> COMPONENT_JNDI_DEPENDENCIES = AttachmentKey.create(Map.class);

/**
* The reflection index for the deployment.
*/
@@ -0,0 +1,57 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2019, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.server.deployment;

import java.util.function.Supplier;

/**
* A supplier which delegates to other supplier if it is configured.
* @param <T> the type of objects that may be supplied by this supplier.
*
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
public final class DelegatingSupplier<T> implements Supplier<T> {

private volatile Supplier<T> delegate;

/**
* Gets delegating supplier value or <code>null</code> if supplier is not configured.
*
* @return delegating supplier value
*/
@Override
public T get() {
final Supplier<T> delegate = this.delegate;
return delegate != null ? delegate.get() : null;
}

/**
* Sets supplier to delegate to.
*
* @param delegate supplier to delegate to
*/
public void set(final Supplier<T> delegate) {
this.delegate = delegate;
}

}
@@ -34,6 +34,7 @@
* the {@link DeploymentUnit}.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
public interface DeploymentPhaseContext extends Attachable {

@@ -96,9 +97,21 @@
* @param type the type to inject
* @param injector the injector into which the dependency value is injected
* @throws IllegalStateException If this is the last phase
* @deprecated use {@link #requires(ServiceName, DelegatingSupplier)} method instead
*/
@Deprecated
<T> void addDependency(ServiceName serviceName, Class<T> type, Injector<T> injector);

/**
* Adds a dependency on the service to the next phase service.
*
* @param <T> the type of the injected value
* @param serviceName the service name to add to {@link Attachments#NEXT_PHASE_DEPS}
* @param supplier the supplier into which the dependency value is injected
* @throws IllegalStateException If this is the last phase
*/
<T> void requires(ServiceName serviceName, DelegatingSupplier<T> supplier);

/**
* Adds a dependency on the service to the next phase service. The service value will be make available as an attachment to
* the {@link DeploymentUnit}. This attachment will be removed when the phase service for the next phase stops.
@@ -32,6 +32,7 @@

/**
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
final class DeploymentPhaseContextImpl extends SimpleAttachable implements DeploymentPhaseContext {
private final ServiceTarget serviceTarget;
@@ -78,17 +79,22 @@ public Phase getPhase() {
this.dependencies.add(new InjectorDeploymentPhaseDependency<>(serviceName, type, injector));
}

@Override
public <T> void requires(final ServiceName serviceName, final DelegatingSupplier<T> supplier) {
this.dependencies.add(new SupplierDeploymentPhaseDependency<>(serviceName, supplier));
}

@Override
public <T> void addDeploymentDependency(ServiceName serviceName, AttachmentKey<T> attachmentKey) {
addToAttachmentList(Attachments.NEXT_PHASE_ATTACHABLE_DEPS, new AttachableDependency(attachmentKey, serviceName, true));
}

private static class InjectorDeploymentPhaseDependency<T> implements DeploymentUnitPhaseDependency {
private static final class InjectorDeploymentPhaseDependency<T> implements DeploymentUnitPhaseDependency {
private final ServiceName name;
private final Class<T> type;
private final Injector<T> injector;

public InjectorDeploymentPhaseDependency(ServiceName name, Class<T> type, Injector<T> injector) {
private InjectorDeploymentPhaseDependency(ServiceName name, Class<T> type, Injector<T> injector) {
this.name = name;
this.type = type;
this.injector = injector;
@@ -99,4 +105,19 @@ public void register(ServiceBuilder<?> builder) {
builder.addDependency(this.name, this.type, this.injector);
}
}

private static final class SupplierDeploymentPhaseDependency<T> implements DeploymentUnitPhaseDependency {
private final ServiceName name;
private final DelegatingSupplier<T> supplier;

private SupplierDeploymentPhaseDependency(final ServiceName name, final DelegatingSupplier<T> supplier) {
this.name = name;
this.supplier = supplier;
}

@Override
public void register(final ServiceBuilder<?> builder) {
supplier.set(builder.requires(name));
}
}
}
@@ -32,7 +32,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.jboss.as.controller.ModelVersion;
@@ -44,7 +43,6 @@
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
import org.jboss.as.controller.registry.LegacyResourceDefinition;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.model.test.ModelTestUtils;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.Property;
import org.junit.Assert;
@@ -120,39 +118,18 @@ private static Resource modelToResource(final PathAddress startAddress, final Im
}
res.writeModel(value);

Set<PathElement> childAddresses = reg.getChildAddresses(PathAddress.EMPTY_ADDRESS);

// When we have overrides those should be used for the checking. The set of child addresses however,
// may have the wildcard children before more specific ones. So we move the specific ones first
List<PathElement> sortedChildAddresses = ModelTestUtils.moveWildcardChildrenToEnd(childAddresses);
Set<PathElement> handledChildren = new HashSet<>();
for (PathElement path : sortedChildAddresses) {

ImmutableManagementResourceRegistration sub = reg.getSubModel(PathAddress.pathAddress(path));
if (path.isWildcard()) {
ModelNode subModel = model.get(path.getKey());
if (subModel.isDefined()) {
for (Property p : subModel.asPropertyList()) {
if (p.getValue().isDefined()) {
final PathElement element = PathElement.pathElement(path.getKey(), p.getName());
if (!handledChildren.contains(element)) {
res.registerChild(
element,
modelToResource(startAddress,sub, p.getValue(), includeUndefined, fullPath.append(path)));
}
}
}
}
} else {
ModelNode subModel = model.get(path.getKeyValuePair());
if (subModel.isDefined()) {
res.registerChild(path, modelToResource(startAddress,sub, subModel, includeUndefined, fullPath.append(path)));
for (String childType : reg.getChildNames(PathAddress.EMPTY_ADDRESS)) {
if (model.hasDefined(childType)) {
for (Property property : model.get(childType).asPropertyList()) {
PathElement childPath = PathElement.pathElement(childType, property.getName());
ImmutableManagementResourceRegistration subRegistration = reg.getSubModel(PathAddress.pathAddress(childPath));
Resource child = modelToResource(startAddress, subRegistration, property.getValue(), includeUndefined, fullPath.append(childPath));
res.registerChild(childPath, child);
}
}

handledChildren.add(path);
allFields.remove(path.getKey());
allFields.remove(childType);
}

if (!allFields.isEmpty()){
throw ControllerLogger.ROOT_LOGGER.modelFieldsNotKnown(allFields, startAddress.append(fullPath));
}
@@ -89,7 +89,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
testSupport = null;
@@ -91,7 +91,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();

testSupport = null;
domainMasterLifecycleUtil = null;
@@ -77,7 +77,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();

testSupport = null;
}
@@ -115,7 +115,7 @@ public static void setupDomain() throws Exception {
@AfterClass
public static void tearDownDomain() throws Exception {
httpManagementRealmSetup.tearDown(domainMasterLifecycleUtil.getDomainClient());
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
FileUtils.deleteDirectory(WORK_DIR);
@@ -52,7 +52,7 @@ public void testServerResolvesKeytabNode() throws Throwable {
Assert.fail("Server did not start properly.");
} finally {
if (testSupport != null) {
testSupport.stop();
testSupport.close();
testSupport = null;
}
if (keytabFileCreated){
@@ -42,7 +42,7 @@
@After
public void cleanUp() {
if (testSupport != null) {
testSupport.stop();
testSupport.close();
}
}

@@ -200,7 +200,7 @@ public static void tearDownDomain() throws Exception {
ModelNode removeExtension = Util.createEmptyOperation(REMOVE, PathAddress.pathAddress(PathElement.pathElement(EXTENSION, BlockerExtension.MODULE_NAME)));
executeForResult(safeTimeout(removeExtension), masterClient);

testSupport.stop();
testSupport.close();
testSupport = null;
masterClient = null;
}
@@ -80,7 +80,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
@@ -18,19 +18,12 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.concurrent.Future;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.client.helpers.Operations;
import org.jboss.as.controller.client.helpers.domain.DomainClient;
import org.jboss.as.controller.client.helpers.domain.impl.DomainClientImpl;
import org.jboss.as.test.integration.domain.management.util.DomainLifecycleUtil;
import org.jboss.as.test.integration.domain.management.util.DomainTestSupport;
import org.jboss.as.test.integration.domain.management.util.WildFlyManagedConfiguration;
import org.jboss.as.test.shared.TimeoutUtil;
import org.jboss.dmr.ModelNode;
import org.junit.After;
import org.junit.Assert;
@@ -43,16 +36,13 @@
*/
public class ReadOnlyModeTestCase {

private DomainTestSupport.Configuration domainConfig;
private DomainTestSupport domainManager;
private DomainLifecycleUtil domainMasterLifecycleUtil;
private DomainLifecycleUtil domainSlaveLifecycleUtil;
private static final long TIMEOUT_S = TimeoutUtil.adjust(30);
private static final int TIMEOUT_SLEEP_MILLIS = 50;

@Before
public void setupDomain() throws Exception {
domainConfig = DomainTestSupport.Configuration.create(ReadOnlyModeTestCase.class.getSimpleName(),
DomainTestSupport.Configuration domainConfig = DomainTestSupport.Configuration.create(ReadOnlyModeTestCase.class.getSimpleName(),
"domain-configs/domain-standard.xml", "host-configs/host-master.xml", "host-configs/host-slave.xml");
domainConfig.getMasterConfiguration().setReadOnlyHost(true);
domainConfig.getMasterConfiguration().setReadOnlyDomain(true);
@@ -66,7 +56,7 @@ public void setupDomain() throws Exception {

@After
public void tearDownDomain() throws Exception {
domainManager.stop();
domainManager.close();
domainManager = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
@@ -77,97 +67,62 @@ public void testConfigurationNotUpdated() throws Exception {
ModelNode domainAddress = PathAddress.pathAddress("system-property", "domain-read-only").toModelNode();
ModelNode masterAddress = PathAddress.pathAddress("host", "master").append("system-property", "master-read-only").toModelNode();
ModelNode slaveAddress = PathAddress.pathAddress("host", "slave").append("system-property", "slave-read-only").toModelNode();
try (final DomainClient masterClient = domainMasterLifecycleUtil.getDomainClient()) {
ModelNode op = Operations.createAddOperation(domainAddress);
op.get("value").set(true);
Operations.isSuccessfulOutcome(masterClient.execute(op));
op = Operations.createAddOperation(masterAddress);
op.get("value").set(true);
Operations.isSuccessfulOutcome(masterClient.execute(op));
op = Operations.createAddOperation(slaveAddress);
op.get("value").set(true);
Operations.isSuccessfulOutcome(masterClient.execute(op));
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());

// reload master HC
op = new ModelNode();
op.get(OP_ADDR).add(HOST, "master");
op.get(OP).set("reload");
domainMasterLifecycleUtil.executeAwaitConnectionClosed(op);
// Try to reconnect to the hc
domainMasterLifecycleUtil.connect();
domainMasterLifecycleUtil.awaitHostController(System.currentTimeMillis());

Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());

// reload slave HC
op = new ModelNode();
op.get(OP_ADDR).add(HOST, "slave");
op.get(OP).set("reload");
domainSlaveLifecycleUtil.executeAwaitConnectionClosed(op);
// Try to reconnect to the hc
domainSlaveLifecycleUtil.connect();
domainSlaveLifecycleUtil.awaitHostController(System.currentTimeMillis());

Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());
}
domainManager.stop();
domainConfig.getMasterConfiguration().setRewriteConfigFiles(false);
domainConfig.getSlaveConfiguration().setRewriteConfigFiles(false);
domainMasterLifecycleUtil = domainManager.getDomainMasterLifecycleUtil();
domainSlaveLifecycleUtil = domainManager.getDomainSlaveLifecycleUtil();
domainMasterLifecycleUtil.startAsync();
domainSlaveLifecycleUtil.startAsync();
try (final DomainClient clientMaster = getDomainClient(domainConfig.getMasterConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, clientMaster);
Assert.assertTrue(Operations.getFailureDescription(clientMaster.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asString().contains("WFLYCTL0216"));
Assert.assertTrue(Operations.getFailureDescription(clientMaster.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asString().contains("WFLYCTL0216"));
Assert.assertTrue(Operations.readResult(clientMaster.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());
}
}


private void waitForHostControllerBeingStarted(long timeoutSeconds, DomainClient client) {
runWithTimeout(timeoutSeconds, () -> client.getServerStatuses());
}

private void runWithTimeout(long timeoutSeconds, Runnable voidFunctionInterface) {
runWithTimeout(timeoutSeconds, () -> {
voidFunctionInterface.run();
return null;
});
}

private <T> T runWithTimeout(long timeoutSeconds, Supplier<T> function) {
final long timeoutTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(timeoutSeconds);
while(true) {
try {
return function.get();
} catch (Throwable t) {
if(timeoutTime < System.currentTimeMillis()) {
throw new IllegalStateException("Function '" + function
+ "' failed to process in " + timeoutSeconds + " s, caused: " + t.getMessage() , t);
}
try {
Thread.sleep(TIMEOUT_SLEEP_MILLIS);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
DomainClient masterClient = domainMasterLifecycleUtil.getDomainClient();

ModelNode op = Operations.createAddOperation(domainAddress);
op.get("value").set(true);
Operations.isSuccessfulOutcome(masterClient.execute(op));
op = Operations.createAddOperation(masterAddress);
op.get("value").set(true);
Operations.isSuccessfulOutcome(masterClient.execute(op));
op = Operations.createAddOperation(slaveAddress);
op.get("value").set(true);
Operations.isSuccessfulOutcome(masterClient.execute(op));
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());

// reload master HC
op = new ModelNode();
op.get(OP_ADDR).add(HOST, "master");
op.get(OP).set("reload");
domainMasterLifecycleUtil.executeAwaitConnectionClosed(op);
// Try to reconnect to the hc
domainMasterLifecycleUtil.connect();
domainMasterLifecycleUtil.awaitHostController(System.currentTimeMillis());

Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());

// reload slave HC
op = new ModelNode();
op.get(OP_ADDR).add(HOST, "slave");
op.get(OP).set("reload");
domainSlaveLifecycleUtil.executeAwaitConnectionClosed(op);
// Try to reconnect to the hc
domainSlaveLifecycleUtil.connect();
domainSlaveLifecycleUtil.awaitHostController(System.currentTimeMillis());

Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asBoolean());
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());

domainSlaveLifecycleUtil.stop();
domainMasterLifecycleUtil.stop();

domainMasterLifecycleUtil.getConfiguration().setRewriteConfigFiles(false);
domainSlaveLifecycleUtil.getConfiguration().setRewriteConfigFiles(false);
Future<Void> masterFuture = domainMasterLifecycleUtil.startAsync();
Future<Void> slaveFuture = domainSlaveLifecycleUtil.startAsync();
masterFuture.get();
slaveFuture.get();

masterClient = domainMasterLifecycleUtil.getDomainClient();
Assert.assertTrue(Operations.getFailureDescription(masterClient.execute(Operations.createReadAttributeOperation(domainAddress, "value"))).asString().contains("WFLYCTL0216"));
Assert.assertTrue(Operations.getFailureDescription(masterClient.execute(Operations.createReadAttributeOperation(masterAddress, "value"))).asString().contains("WFLYCTL0216"));
Assert.assertTrue(Operations.readResult(masterClient.execute(Operations.createReadAttributeOperation(slaveAddress, "value"))).asBoolean());

private DomainClient getDomainClient(WildFlyManagedConfiguration config) throws UnknownHostException {
final InetAddress address = InetAddress.getByName(config.getHostControllerManagementAddress());
final int port = config.getHostControllerManagementPort();
final String protocol = config.getHostControllerManagementProtocol();
return new DomainClientImpl(protocol, address, port);
}

}
@@ -81,7 +81,7 @@ public static void setupDomain() throws Exception {
public static void tearDownDomain() throws Exception {
masterManagementRealmSetup.tearDown(domainMasterLifecycleUtil.getDomainClient());

testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;

@@ -76,7 +76,7 @@ public static void setupDomain() throws Exception {
public static void tearDownDomain() throws Exception {
masterManagementRealmSetup.tearDown(domainMasterLifecycleUtil.getDomainClient());

testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;

@@ -157,7 +157,7 @@ public static void tearDownDomain() throws Exception {
PathAddress.pathAddress(EXTENSION, "org.wildfly.extension.profile-includes-test")), domainMasterLifecycleUtil.getDomainClient());
}

testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
@@ -98,7 +98,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterClient = null;
domainSlaveClient = null;
@@ -143,7 +143,7 @@ public static void setupDomain(boolean slaveIsBackupDC, boolean slaveIsCachedDc)

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
testSupport = null;
@@ -762,7 +762,7 @@ private void restartDomainAndReloadReadOnlyConfig() throws Exception {

private void restartDomainAndReloadReadOnlyConfig(boolean slaveIsBackupDC, boolean slaveIsCachedDC) throws Exception {
DomainTestSupport.stopHosts(TimeoutUtil.adjust(30000), domainSlaveLifecycleUtil, domainMasterLifecycleUtil);
testSupport.stop();
testSupport.close();

//Totally reinitialize the domain client
setupDomain(slaveIsBackupDC, slaveIsCachedDC);
@@ -92,7 +92,7 @@ public void specifyDomainConfig() throws Exception {
@After
public void stopDomain() {
if(domainManager != null) {
domainManager.stop();
domainManager.close();
}
}

@@ -186,14 +186,10 @@ public void dcConfigChangePropagated() throws Exception {
domainManager.getDomainMasterLifecycleUtil()
.executeForResult(getCreateOperationTestLoggingCategory());

domainManager.stop();
domainManager.getDomainSlaveLifecycleUtil().startAsync();
domainManager.stopHosts();

try (final DomainClient client = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, client);
waitForServersBeingStarted(TIMEOUT_S, client);
checkTestLoggerFromSlaveHost(client);
}
domainManager.getDomainSlaveLifecycleUtil().start();
checkTestLoggerFromSlaveHost(domainManager.getDomainSlaveLifecycleUtil().getDomainClient());
}

/**
@@ -214,25 +210,17 @@ public void dcConfigChangePropagatedAfterRestart() throws Exception {
assertEquals(false, domainManager.getDomainSlaveLifecycleUtil().isHostControllerStarted());
domainManager.getDomainMasterLifecycleUtil()
.executeForResult(getCreateOperationTestLoggingCategory());
domainManager.stop();
domainManager.stopHosts();

// starting domain once again - reusing already changed config files
domainConfig.getMasterConfiguration().setRewriteConfigFiles(false);
domainConfig.getSlaveConfiguration().setRewriteConfigFiles(false);

// HC started with old domain.cached-remote.xml
domainManager.getDomainSlaveLifecycleUtil().startAsync();
try (final DomainClient clientSlave = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, clientSlave);
waitForServersBeingStarted(TIMEOUT_S, clientSlave);
}
domainManager.getDomainSlaveLifecycleUtil().start();

// DC started where domain config contains a configuration change (a new logger was created)
domainManager.getDomainMasterLifecycleUtil().startAsync();
try (final DomainClient clientMaster = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, clientMaster);
waitForServersBeingStarted(TIMEOUT_S, clientMaster);
}
domainManager.getDomainMasterLifecycleUtil().start();

// timeout waits to get changes from DC propagated to HC
// by WFCORE-2331 the host controller log file should advert need of configuration change
@@ -294,7 +282,7 @@ public void reloadAdvertisedAfterDcModelChangeWithShutdown() throws Exception {
final ModelNode profileRead = readLoggingApiDependencies(client);
assertEquals("Expecting value of attribute 'add-logging-api-dependencies' was changed" + profileRead,
isAddLoggingApiDependencies, profileRead.get("result").asBoolean());
domainManager.stop();
domainManager.stopHosts();

// starting domain once again - reusing already changed config files
// slave will be started with cached dc parameter but not with backup parameter
@@ -303,37 +291,23 @@ public void reloadAdvertisedAfterDcModelChangeWithShutdown() throws Exception {
.setRewriteConfigFiles(false).setBackupDC(false).setCachedDC(true);

// starting HC with old domain.cached-remote.xml
domainManager.getDomainSlaveLifecycleUtil().startAsync();
try (final DomainClient clientSlave = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, clientSlave);
waitForServersBeingStarted(TIMEOUT_S, clientSlave);
}
domainManager.getDomainSlaveLifecycleUtil().start();

// starting DC where domain config contains a configuration change
domainManager.getDomainMasterLifecycleUtil().startAsync();
try (final DomainClient clientMaster = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, clientMaster);
waitForServersBeingStarted(TIMEOUT_S, clientMaster);
}
domainManager.getDomainMasterLifecycleUtil().start();

try (final DomainClient clientSlave = getDomainClient(domainConfig.getSlaveConfiguration())) {
runWithTimeout(TIMEOUT_S, () -> {
ModelNode hostRead = readLoggingApiDependenciesAtServerOtherTwo(clientSlave);
assertEquals("Read operation should suceed", SUCCESS, hostRead.get(OUTCOME).asString());
assertEquals("Expecting change of attribute 'add-logging-api-dependencies' requests a reload: " + hostRead,
"reload-required", hostRead.get("response-headers").get("process-state").asString());
});
}
try (final DomainClient clientMaster = getDomainClient(domainConfig.getMasterConfiguration())) {
reloadServers(clientMaster);
}
try (final DomainClient clientMaster = getDomainClient(domainConfig.getMasterConfiguration())) {
runWithTimeout(TIMEOUT_S, () -> {
ModelNode hostRead = readLoggingApiDependenciesAtServerOtherTwo(clientMaster);
assertEquals("Expecting value of attribute 'add-logging-api-dependencies' changed: " + hostRead,
isAddLoggingApiDependencies, hostRead.get("result").asBoolean());
});
}
runWithTimeout(TIMEOUT_S, () -> {
ModelNode hostRead = readLoggingApiDependenciesAtServerOtherTwo(domainManager.getDomainSlaveLifecycleUtil().getDomainClient());
assertEquals("Read operation should suceed", SUCCESS, hostRead.get(OUTCOME).asString());
assertEquals("Expecting change of attribute 'add-logging-api-dependencies' requests a reload: " + hostRead,
"reload-required", hostRead.get("response-headers").get("process-state").asString());
});
reloadServers(domainManager.getDomainMasterLifecycleUtil().getDomainClient());
runWithTimeout(TIMEOUT_S, () -> {
ModelNode hostRead = readLoggingApiDependenciesAtServerOtherTwo(domainManager.getDomainMasterLifecycleUtil().getDomainClient());
assertEquals("Expecting value of attribute 'add-logging-api-dependencies' changed: " + hostRead,
isAddLoggingApiDependencies, hostRead.get("result").asBoolean());
});
// by WFCORE-2331 the host controller log file should advert need of configuration change
runWithTimeout(TIMEOUT_S, () -> checkHostControllerLogFile(domainConfig.getSlaveConfiguration(), "WFLYHC0202"));
}
@@ -347,16 +321,10 @@ private void test_hcStartsWhenCachedConfigAvailable(DomainTestSupport.Configurat
assertTrue("Master should be started", masterHost.areServersStarted());
assertTrue("Slave should be started", slaveHost.areServersStarted());

domainManager.stop();
domainManager.stopHosts();

domainConfig.getSlaveConfiguration().setCachedDC(true);
slaveHost.startAsync();

// check that HC and servers were started
try (final DomainClient client = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, client);
waitForServersBeingStarted(TIMEOUT_S, client);
}
slaveHost.start();
}

/**
@@ -376,10 +344,8 @@ private void test_hcWaitsForDcBeingStarted(DomainTestSupport.Configuration domai

// after starting DC, HC is ready to use with all its servers
domainManager.getDomainMasterLifecycleUtil().start();
try (final DomainClient client = getDomainClient(domainConfig.getSlaveConfiguration())) {
waitForHostControllerBeingStarted(TIMEOUT_S, client);
waitForServersBeingStarted(TIMEOUT_S, client);
}
waitForHostControllerBeingStarted(TIMEOUT_S, domainManager.getDomainSlaveLifecycleUtil().getDomainClient());
waitForServersBeingStarted(TIMEOUT_S, domainManager.getDomainSlaveLifecycleUtil().getDomainClient());
}

private DomainClient getDomainClient(WildFlyManagedConfiguration config) throws UnknownHostException {
@@ -59,7 +59,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
master = null;
slave = null;
@@ -53,7 +53,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;

FileUtils.deleteDirectory(WORK_DIR);
@@ -53,7 +53,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;

FileUtils.deleteDirectory(WORK_DIR);
@@ -82,7 +82,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterClient = null;
domainSlaveClient = null;
@@ -89,7 +89,7 @@ public static void setupClass() throws Exception {
@AfterClass
public static void cleanClass() throws Exception {
task.tearDown(domainMasterLifecycleUtil.getDomainClient(), "main-server-group");
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
DomainTestSuite.stopSupport();
@@ -111,7 +111,7 @@ public static void setup() throws Exception {

@AfterClass
public static void tearDown() throws Exception {
testSupport.stop();
testSupport.close();
PathUtil.deleteSilentlyRecursively(data);
}

@@ -57,7 +57,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
@@ -65,7 +65,7 @@ public static void setupDomain() {

@AfterClass
public static void tearDownDomain() {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
}
@@ -125,7 +125,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
@@ -108,7 +108,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
}
@@ -100,7 +100,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
testSupport = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
@@ -99,7 +99,7 @@ private static synchronized void start(final String name) {

private static synchronized void stop() {
if(support != null) {
support.stop();
support.close();
support = null;
}
}
@@ -100,7 +100,7 @@ private static synchronized void start(final String name) {

private static synchronized void stop() {
if(support != null) {
support.stop();
support.close();
support = null;
}
}
@@ -77,7 +77,7 @@ private static synchronized void start(final String name) {

private static synchronized void stop() {
if(support != null) {
support.stop();
support.close();
support = null;
}
}
@@ -79,7 +79,7 @@ private static synchronized void start(final String name) {

private static synchronized void stop() {
if(support != null) {
support.stop();
support.close();
support = null;
}
}
@@ -92,7 +92,7 @@ private static synchronized void start(final String name) {

private static synchronized void stop() {
if(support != null) {
support.stop();
support.close();
support = null;
}
}
@@ -221,7 +221,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();
domainMasterLifecycleUtil = null;
testSupport = null;
}
@@ -77,7 +77,7 @@ private static synchronized void start(final String name) {

private static synchronized void stop() {
if(support != null) {
support.stop();
support.close();
support = null;
}
}
@@ -60,7 +60,7 @@
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.auth.client.MatchRule;
import org.wildfly.security.auth.permission.LoginPermission;
import org.wildfly.security.mechanism.scram.ScramServerErrorCode;
import org.wildfly.security.mechanism.ScramServerErrorCode;
import org.wildfly.security.sasl.SaslMechanismSelector;
import org.wildfly.security.ssl.SSLContextBuilder;
import org.wildfly.test.security.common.TestRunnerConfigSetupTask;
@@ -0,0 +1,71 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.wildfly.test.integration.elytron.ssl;

import org.jboss.as.test.integration.management.util.CLIWrapper;
import org.jboss.as.test.integration.management.util.ServerReload;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.wildfly.core.testrunner.ServerSetup;
import org.wildfly.core.testrunner.WildflyTestRunner;

import static org.hamcrest.CoreMatchers.containsString;

@ServerSetup(ServerReload.SetupTask.class)
@RunWith(WildflyTestRunner.class)
public class ServerSslSniContextTestCase {
CLIWrapper cli;

@Before
public void setup() throws Exception {
cli = new CLIWrapper(true);
// add server-ssl-sni-context
cli.sendLine("/subsystem=elytron/key-store=exampleKeyStore:add(path=server.keystore,relative-to=jboss.server.config.dir,credential-reference={clear-text=\"keystore_password\"},type=JKS)");
cli.sendLine("/subsystem=elytron/key-manager=exampleKeyManager:add(key-store=exampleKeyStore,alias-filter=server,credential-reference={clear-text=\"key_password\"})");
cli.sendLine("/subsystem=elytron/server-ssl-context=exampleSslContext:add(key-manager=exampleKeyManager)");
cli.sendLine("/subsystem=elytron/server-ssl-sni-context=exampleSslSniContext:add(default-ssl-context=exampleSslContext");
}

@After
public void cleanup() throws Exception {
removeTestResources();
cli.close();
}

@Test
public void testInvalidHostContextMapValue() {
boolean success = cli.sendLine("/subsystem=elytron/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"\\\\?.invalid.example.com\"=exampleSslContext})", true);
Assert.assertFalse(success);
Assert.assertThat("Wrong error message", cli.readOutput(), containsString("not a valid hostname"));
}

@Test
public void testValidHostContextMapValue() {
boolean success = cli.sendLine("/subsystem=elytron/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"valid.example.com\"=exampleSslContext})", true);
Assert.assertTrue(success);
}

private void removeTestResources() {
cli.sendLine("/subsystem=elytron/server-ssl-sni-context=exampleSslSniContext:remove");
cli.sendLine("/subsystem=elytron/server-ssl-context=exampleSslContext:remove");
cli.sendLine("/subsystem=elytron/key-manager=exampleKeyManager:remove");
cli.sendLine("/subsystem=elytron/key-store=exampleKeyStore:remove");
}
}
@@ -76,7 +76,7 @@ public static void setupDomain() throws Exception {

@AfterClass
public static void tearDownDomain() throws Exception {
testSupport.stop();
testSupport.close();

if (IoUtils.recursiveDelete(tempDir)) {
tempDir.deleteOnExit();
@@ -18,6 +18,8 @@
*/
package org.jboss.as.test.integration.domain.management.util;

import static org.jboss.as.test.integration.domain.management.util.DomainTestSupport.safeClose;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@@ -76,7 +78,7 @@
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
*/
public class DomainLifecycleUtil {
public class DomainLifecycleUtil implements AutoCloseable {

public static final String SLAVE_HOST_USERNAME = "slave";
public static final String SLAVE_HOST_PASSWORD = "slave_us3r_password";
@@ -99,6 +101,7 @@
private final DomainControllerClientConfig clientConfiguration;
private final PathAddress address;
private final boolean closeClientConfig;
private volatile boolean closed;

public DomainLifecycleUtil(final WildFlyManagedConfiguration configuration) throws IOException {
this(configuration, DomainControllerClientConfig.create(), true);
@@ -126,6 +129,13 @@ public PathAddress getAddress() {
return address;
}

/**
* Starts a {@code ProcessController} process configured according to the provided {@link #getConfiguration() configuration}.
* The {@code ProcessController} will start a {@code HostController} process, which, if it is so configured, will
* start managed servers. This method will block until any such servers are started.
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public void start() {
try {
configuration.validate();
@@ -225,7 +235,7 @@ public void start() {

if (configuration.getDomainConfigFile() != null) {
final String prefix = configuration.isCachedDC() ? null : "testing-";
String name = null;
String name;
if(configuration.isRewriteConfigFiles()) {
name = copyConfigFile(configuration.getDomainConfigFile(), configDir, prefix);
} else {
@@ -240,7 +250,7 @@ public void start() {
}
if (configuration.getHostConfigFile() != null) {
final String prefix = "testing-";
String name = null;
String name;
if(configuration.isRewriteConfigFiles()) {
name = copyConfigFile(configuration.getHostConfigFile(), configDir, prefix);
} else {
@@ -286,7 +296,15 @@ public void start() {

}

/**
* Creates a task to call {@link #start()} and executes it asynchronously.
*
* @return a {@link Future} which can be used to track the completion or failure of the task
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public Future<Void> startAsync() {
checkClosed();
Callable<Void> c = new Callable<Void>() {

@Override
@@ -339,6 +357,7 @@ public synchronized void stop() {
}
}

@SuppressWarnings("WeakerAccess")
public Future<Void> stopAsync() {
Callable<Void> c = new Callable<Void>() {

@@ -352,18 +371,30 @@ public Void call() throws Exception {
return Executors.newSingleThreadExecutor(threadFactory).submit(c);
}

/**
* Marks the object as closed and calls {@link #stop()}. The object will no longer be usable for managing
* the lifecycle of a host.
*/
public void close() {
closed = true;
stop();
}

/**
* Execute an operation and wait until the connection is closed. This is only useful for :reload and :shutdown operations.
*
* @param operation the operation to execute
* @return the operation result
* @throws IOException for any error
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public ModelNode executeAwaitConnectionClosed(final ModelNode operation) throws IOException {
checkClosed();
final DomainTestClient client = internalGetOrCreateClient();
final Channel channel = client.getChannel();
if( null == channel )
if ( null == channel ) {
throw new IllegalStateException("Didn't get a remoting channel from the DomainTestClient.");
}
final Connection ref = channel.getConnection();
ModelNode result = new ModelNode();
try {
@@ -379,10 +410,9 @@ public ModelNode executeAwaitConnectionClosed(final ModelNode operation) throws
} // else ignore, this might happen if the channel gets closed before we got the response
}
try {
if(channel != null) {
// Wait for the channel to close
channel.awaitClosed();
}
// Wait for the channel to close
channel.awaitClosed();

// Wait for the connection to be closed
connection.awaitConnectionClosed(ref);
} catch (InterruptedException e) {
@@ -394,7 +424,7 @@ public ModelNode executeAwaitConnectionClosed(final ModelNode operation) throws
/**
* Try to connect to the host controller.
*
* @throws IOException
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public void connect() throws IOException {
connect(30, TimeUnit.SECONDS);
@@ -405,8 +435,11 @@ public void connect() throws IOException {
*
* @param timeout the timeout
* @param timeUnit the timeUnit
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public void connect(final long timeout, final TimeUnit timeUnit) throws IOException {
checkClosed();
final DomainTestConnection connection = this.connection;
if(connection == null) {
throw new IllegalStateException();
@@ -434,6 +467,8 @@ public void connect(final long timeout, final TimeUnit timeUnit) throws IOExcept
* Create a new model controller client. The client can (and should) be closed without affecting other usages.
*
* @return the domain client
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public DomainClient createDomainClient() {
return createDomainClient(null);
@@ -445,8 +480,12 @@ public DomainClient createDomainClient() {
* @param authConfigUri the path to the {@code wildfly-config.xml} to use or {@code null}
*
* @return the domain client
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
@SuppressWarnings("WeakerAccess")
public DomainClient createDomainClient(final URI authConfigUri) {
checkClosed();
final DomainTestConnection connection = this.connection;
if(connection == null) {
throw new IllegalStateException();
@@ -466,6 +505,8 @@ public DomainClient createDomainClient(final URI authConfigUri) {
* Get a shared domain client.
*
* @return the domain client
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public synchronized DomainClient getDomainClient() {
return getDomainClient(null);
@@ -477,8 +518,11 @@ public synchronized DomainClient getDomainClient() {
* @param authConfigUri the path to the {@code wildfly-config.xml} to use or {@code null}
*
* @return the domain client
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public synchronized DomainClient getDomainClient(final URI authConfigUri) {
checkClosed();
if (authConfigUri == null) {
return DomainClient.Factory.create(internalGetOrCreateClient());
}
@@ -490,9 +534,17 @@ public synchronized DomainClient getDomainClient(final URI authConfigUri) {
}
}

/** Wait for all auto-start servers for the host to reach {@link ControlledProcessState.State#RUNNING} */
/**
* Poll until {@link #areServersStarted()} returns {@code true} or the
* {@link WildFlyManagedConfiguration#getStartupTimeoutInSeconds() configured timeout} is reached.
*
* @param start time in milliseconds that should be used as the starting time for the timeout check.
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
* @throws TimeoutException if no call {@link #areServersStarted()} returns {@code true} before the timeout
*/
public void awaitServers(long start) throws InterruptedException, TimeoutException {

checkClosed();
boolean serversAvailable = false;
long deadline = start + configuration.getStartupTimeoutInSeconds() * 1000;
while (!serversAvailable && getProcessExitCode() < 0) {
@@ -508,8 +560,17 @@ public void awaitServers(long start) throws InterruptedException, TimeoutExcepti
}
}

/**
* Poll until {@link #isHostControllerStarted()} returns {@code true} or the
* {@link WildFlyManagedConfiguration#getStartupTimeoutInSeconds() configured timeout} is reached.
*
* @param start time in milliseconds that should be used as the starting time for the timeout check.
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
* @throws TimeoutException if no call {@link #isHostControllerStarted()} returns {@code true} before the timeout
*/
public void awaitHostController(long start) throws InterruptedException, TimeoutException {

checkClosed();
boolean hcAvailable = false;
long deadline = start + configuration.getStartupTimeoutInSeconds() * 1000;
while (!hcAvailable && getProcessExitCode() < 0) {
@@ -544,16 +605,23 @@ private synchronized ExecutorService getExecutorService() {
return executor;
}

/**
* Returns whether the {@code server-state} attribute on the {@code /host=x/server=y} resource for all auto-start
* servers managed by the host managed by this object are reporting state {@link ControlledProcessState.State#RUNNING}.
* Problems connecting to the host result in returning {@code false}.
*
* @return {@code true} if the host reports as '{@code running}'
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public boolean areServersStarted() {
checkClosed();
try {
Map<ServerIdentity, ControlledProcessState.State> statuses = getServerStatuses();
for (Map.Entry<ServerIdentity, ControlledProcessState.State> entry : statuses.entrySet()) {
switch (entry.getValue()) {
case RUNNING:
continue;
default:
log.log(Level.INFO, entry.getKey() + " status is " + entry.getValue());
return false;
if (entry.getValue() != ControlledProcessState.State.RUNNING) {
log.log(Level.INFO, entry.getKey() + " status is " + entry.getValue());
return false;
}
}
// serverStatuses.putAll(statuses);
@@ -564,7 +632,17 @@ public boolean areServersStarted() {
return false;
}

/**
* Returns whether the {@code host-state} attribute on the {@code /host=x} resource for the host managed
* by this object is reporting state {@link ControlledProcessState.State#RUNNING}. Problems connecting to the
* host result in returning {@code false}.
*
* @return {@code true} if the host reports as '{@code running}'
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
*/
public boolean isHostControllerStarted() {
checkClosed();
try {
ModelNode address = new ModelNode();
address.add("host", configuration.getHostName());
@@ -580,6 +658,7 @@ public boolean isHostControllerStarted() {
private synchronized void closeConnection() {
if (connection != null) {
try {
safeClose(domainClient);
domainClient = null;
connection.close();
} catch (Exception e) {
@@ -638,11 +717,36 @@ private ModelNode readAttribute(String name, ModelNode address) {
return executeForResult(new OperationBuilder(op).build());
}

/**
* Uses the {@link #getDomainClient() shared client} to execute an operation and return its {@code result} response
* value, throwing a {@link RuntimeException} if the operation does not succeed.
*
* @param op the operation.
*
* @return the value of the {@code result} node of the operation response (which may be an undefined node.)
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
* @throws RuntimeException if the operation did not execute resulting with a response with an {@code outcome} value
* of {@code success}
*/
public ModelNode executeForResult(ModelNode op) {
return executeForResult(new OperationBuilder(op).build());
}

/**
* Uses the {@link #getDomainClient() shared client} to execute an operation and return its {@code result} response
* value, throwing a {@link RuntimeException} if the operation does not succeed.
*
* @param op the operation.
*
* @return the value of the {@code result} node of the operation response (which may be an undefined node.)
*
* @throws IllegalStateException if {@link #close()} has previously been invoked on this instance.
* @throws RuntimeException if the operation did not execute resulting with a response with an {@code outcome} value
* of {@code success}
*/
public ModelNode executeForResult(Operation op) {
checkClosed();
try {
ModelNode result = getDomainClient().execute(op);
if (result.hasDefined("outcome") && "success".equals(result.get("outcome").asString())) {
@@ -661,6 +765,12 @@ public ModelNode executeForResult(Operation op) {
}
}

private void checkClosed() {
if (closed) {
throw new IllegalStateException(getClass().getSimpleName() + " is closed");
}
}

private static final class AsyncThreadFactory implements ThreadFactory {

private int threadCount;