diff --git a/.github/workflows/quickstart_helloworld-mutual-ssl-secured_ci.yml b/.github/workflows/quickstart_helloworld-mutual-ssl-secured_ci.yml
new file mode 100644
index 0000000000..bf0c1a6769
--- /dev/null
+++ b/.github/workflows/quickstart_helloworld-mutual-ssl-secured_ci.yml
@@ -0,0 +1,16 @@
+name: WildFly helloworld-mutual-ssl-secured Quickstart CI
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
+ paths:
+ - 'helloworld-mutual-ssl-secured/**'
+ - '.github/workflows/quickstart_ci.yml'
+
+jobs:
+ call-quickstart_ci:
+ uses: ./.github/workflows/quickstart_ci.yml
+ with:
+ QUICKSTART_PATH: helloworld-mutual-ssl-secured
+ TEST_PROVISIONED_SERVER: true
+ TEST_OPENSHIFT: false
\ No newline at end of file
diff --git a/helloworld-mutual-ssl-secured/README.adoc b/helloworld-mutual-ssl-secured/README.adoc
index 1dfbfdeab7..329aa96889 100644
--- a/helloworld-mutual-ssl-secured/README.adoc
+++ b/helloworld-mutual-ssl-secured/README.adoc
@@ -70,7 +70,7 @@ Notice that it sets the `first and last name` to `quickstartUser` and that this
[source,options="nowrap"]
----
$>keytool -exportcert -keystore client.keystore -storetype pkcs12 -storepass secret -keypass secret -file client.crt
-$>keytool -import -file client.crt -alias quickstartUser -keystore client.truststore -storepass secret
+$>keytool -import -file client.crt -alias quickstartUser -keystore server.truststore -storepass secret
Owner: CN=quickstartUser, OU=Sales, O=My Company, L=Sao Paulo, ST=Sao Paulo, C=BR
Issuer: CN=quickstartUser, OU=Sales, O=My Company, L=Sao Paulo, ST=Sao Paulo, C=BR
@@ -155,7 +155,7 @@ After stopping the server, open the `__{jbossHomeName}__/standalone/configuratio
-
+
----
@@ -231,7 +231,7 @@ It maps the `client_cert_domain` from the quickstart application to the `http-au
[[test_the_server_ssl_configuration]]
== Test the Server TLS Configuration
-To test the TLS configuration, access: https://localhost:8443
+To test the TLS configuration, start {productName} and access: https://localhost:8443
If it is configured correctly, you should be asked to trust the server certificate.
@@ -290,6 +290,8 @@ dzXZz0EjjWCPJk+LVEhEvH0GcWAp3x3irpNU4hRZLd0XomY0Z4NnUt7VMBNYDOxVxgT9qcLnEaEpIfYU
ynfnMaOxI67FC2QzhfzERyKqHj47WuwN0xWbS/1gBypS2nUwvItyxaEQG2X5uQY8j8QoY9wcMzIIkP2Mk14gJGHUnA8=
----
+// Server Distribution Testing
+include::../shared-doc/run-integration-tests-with-server-distribution.adoc[leveloffset=+2]
// Undeploy the Quickstart
include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1]
@@ -320,7 +322,7 @@ $ cd __{jbossHomeName}__/standalone/configuration/
+
NOTE: For Windows, use the `__{jbossHomeName}__\bin\standalone.bat` script.
-. Remove the `clientCert.p12`, `client.crt`, and `client.truststore` files that were generated for this quickstart.
+. Remove the `clientCert.p12`, `client.crt`, and `server.truststore` files that were generated for this quickstart.
[[remove_the_client_certificate_from_your_browser]]
== Remove the Client Certificate from Your Browser
@@ -344,26 +346,11 @@ After you are done with this quickstart, remember to remove the certificate that
. Select the *quickstartUser* certificate and click the *Delete* button.
. The certificate has now been removed from the Mozilla Firefox browser.
-// Run the Quickstart in Red Hat CodeReady Studio or Eclipse
-include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1]
-
-// Additional Red Hat CodeReady Studio instructions
-* Make sure you configure the keystores and client certificates as described under xref:set_up_client_keystore_using_java_keytool[Set Up the Client Keystore Using Java Keytool].
-* Depending on the browser you choose, make sure you either xref:import_the_client_certificate_into_google_chrome[import the certificate into Google Chrome] or xref:import_the_client_certificate_into_mozilla_firefox[import the certificate into Mozilla Firefox].
-* Make sure you configure the server by running the JBoss CLI commands as described above under xref:configure_the_server[Configure the Server]. Stop the server at the end of that step.
-* In {JBDSProductName}, choose *Window* –> *Web Browser*, then select the browser you chose to import the certificate.
-* To deploy the application, right-click on the *{artifactId}* project and choose *Run As* –> *Run on Server*.
-* Make sure you xref:restore_the_server_configuration[restore the {productName} server configuration] when you have completed testing this quickstart.
-
-// Debug the Application
-include::../shared-doc/debug-the-application.adoc[leveloffset=+1]
-
-//*************************************************
-// Product Release content only
-//*************************************************
-ifdef::ProductRelease[]
+// Build and run sections for other environments/builds
+ifndef::ProductRelease,EAPXPRelease[]
+:server_provisioning_server_host: https://localhost:8443
+include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1]
+endif::[]
// Quickstart not compatible with OpenShift
include::../shared-doc/openshift-incompatibility.adoc[leveloffset=+1]
-
-endif::[]
diff --git a/helloworld-mutual-ssl-secured/configure-client-cert.cli b/helloworld-mutual-ssl-secured/configure-client-cert.cli
new file mode 100644
index 0000000000..0350479827
--- /dev/null
+++ b/helloworld-mutual-ssl-secured/configure-client-cert.cli
@@ -0,0 +1,19 @@
+# Configure the client's keystore. This will be used to generate the client's certificate. The path to the keystore file doesn’t actually have to exist yet
+/subsystem=elytron/key-store=clientKS:add(path=client.keystore.P12, relative-to=jboss.server.config.dir, credential-reference={clear-text=secret}, type=PKCS12)
+
+# Generate a new key pair for the client. We'll use an RSA key of size 2048 and we'll use CN=quickstartUser
+/subsystem=elytron/key-store=clientKS:generate-key-pair(alias=quickstartUser, algorithm=RSA, key-size=2048, validity=365, credential-reference={clear-text=secret}, distinguished-name="cn=quickstartUser")
+
+# Export the client's certificate to a file called clientCert.crt
+/subsystem=elytron/key-store=clientKS:export-certificate(alias=quickstartUser, path=clientCert.crt, relative-to=jboss.server.config.dir, pem=true)
+
+# Create the server's truststore
+/subsystem=elytron/key-store=serverTS:add(path=server.truststore, relative-to=jboss.server.config.dir, credential-reference={clear-text=secret}, type=PKCS12)
+
+# Import the client's certificate into the server's truststore
+/subsystem=elytron/key-store=serverTS:import-certificate(alias=quickstartUser, path=clientCert.crt, relative-to=jboss.server.config.dir, credential-reference={clear-text=secret}, validate=false)
+
+# Persist the changes we've made to the client's keystore and the server's truststore
+/subsystem=elytron/key-store=serverTS:store()
+/subsystem=elytron/key-store=clientKS:store()
+
diff --git a/helloworld-mutual-ssl-secured/configure-ssl.cli b/helloworld-mutual-ssl-secured/configure-ssl.cli
index bcb84b121e..ce814ca841 100644
--- a/helloworld-mutual-ssl-secured/configure-ssl.cli
+++ b/helloworld-mutual-ssl-secured/configure-ssl.cli
@@ -4,7 +4,7 @@
batch
# Add the keystore and trust manager configuration in the elytron subsystem
-/subsystem=elytron/key-store=qsTrustStore:add(path=client.truststore,relative-to=jboss.server.config.dir,type=JKS,credential-reference={clear-text=secret})
+/subsystem=elytron/key-store=qsTrustStore:add(path=server.truststore,relative-to=jboss.server.config.dir,type=PKCS12,credential-reference={clear-text=secret})
/subsystem=elytron/trust-manager=qsTrustManager:add(key-store=qsTrustStore)
# Update the default server-ssl-context to reference the new trust-manager and require client auth
@@ -29,10 +29,13 @@ batch
# Add an application-security-domain in the undertow subsystem to map the client_cert_domain from the quickstart app to the http-authentication-factory
/subsystem=undertow/application-security-domain=client_cert_domain:add(http-authentication-factory=quickstart-http-authentication)
+# Generate the server's certificate
+/subsystem=elytron/key-store=applicationKS:generate-key-pair(alias=server, algorithm=RSA, key-size=2048, validity=365, credential-reference={clear-text=password}, distinguished-name="cn=localhost")
+
+/subsystem=elytron/key-store=applicationKS:store()
+
# Run the batch commands
run-batch
# Reload the server configuration
-reload
-
-
+#reload
\ No newline at end of file
diff --git a/helloworld-mutual-ssl-secured/pom.xml b/helloworld-mutual-ssl-secured/pom.xml
index 6c3d721f5e..cdb652491d 100644
--- a/helloworld-mutual-ssl-secured/pom.xml
+++ b/helloworld-mutual-ssl-secured/pom.xml
@@ -44,8 +44,12 @@
-
- 30.0.0.Final
+
+ 30.0.0.Final
+
+ ${version.server}
+ 5.0.0.Final
+ 4.2.0.Final
@@ -109,7 +113,7 @@
org.wildfly.bom
wildfly-ee-with-tools
- ${version.server.bom}
+ ${version.bom.ee}
pom
import
@@ -139,5 +143,101 @@
jakarta.servlet-api
provided
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+
+
+
+
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+ ${version.plugin.wildfly}
+
+
+
+
+
+
+ provisioned-server
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+
+
+
+ org.wildfly:wildfly-galleon-pack:${version.server}
+
+
+
+
+ cloud-server
+ undertow-https
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ ROOT.war
+
+
+
+
+ package
+
+
+
+
+
+
+
+
+ integration-testing
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/BasicRuntimeIT
+
+
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
+
diff --git a/helloworld-mutual-ssl-secured/restore-client-certs.cli b/helloworld-mutual-ssl-secured/restore-client-certs.cli
new file mode 100644
index 0000000000..d18658df13
--- /dev/null
+++ b/helloworld-mutual-ssl-secured/restore-client-certs.cli
@@ -0,0 +1,8 @@
+#remove the keypairs and certificates from the keystore and truststore
+/subsystem=elytron/key-store=serverTS:remove-alias(alias=quickstartUser)
+/subsystem=elytron/key-store=clientKS:remove-alias(alias=quickstartUser)
+
+#remove the keystore and truststore
+/subsystem=elytron/key-store=serverTS:remove
+/subsystem=elytron/key-store=clientKS:remove
+
diff --git a/helloworld-mutual-ssl-secured/restore-configuration.cli b/helloworld-mutual-ssl-secured/restore-configuration.cli
index 0cf5606b9d..dff3152ceb 100644
--- a/helloworld-mutual-ssl-secured/restore-configuration.cli
+++ b/helloworld-mutual-ssl-secured/restore-configuration.cli
@@ -3,6 +3,9 @@
# Start batching commands
batch
+# Remove the keypair with the alias server from the application keystore
+/subsystem=elytron/key-store=applicationKS:remove-alias(alias=server)
+
# Remove the application-security-domain mapping that was added for the quickstart
/subsystem=undertow/application-security-domain=client_cert_domain:remove
diff --git a/helloworld-mutual-ssl-secured/src/test/java/org/jboss/as/quickstarts/helloworld_mutual_ssl/BasicRuntimeIT.java b/helloworld-mutual-ssl-secured/src/test/java/org/jboss/as/quickstarts/helloworld_mutual_ssl/BasicRuntimeIT.java
new file mode 100644
index 0000000000..199c745047
--- /dev/null
+++ b/helloworld-mutual-ssl-secured/src/test/java/org/jboss/as/quickstarts/helloworld_mutual_ssl/BasicRuntimeIT.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2023 JBoss by Red Hat.
+ *
+ * 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.jboss.as.quickstarts.helloworld_mutual_ssl;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.DefaultSchemePortResolver;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
+import javax.net.ssl.SSLContext;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.HttpResponse;
+
+
+import static org.jboss.as.quickstarts.helloworld_mutual_ssl.KeystoreUtil.createTrustStore;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * The very basic runtime integration testing.
+ * @author Prarthona Paul
+ * @author emartins
+ */
+public class BasicRuntimeIT {
+
+ private static final String DEFAULT_SERVER_HOST = "https://localhost:8443/helloworld-mutual-ssl-secured";
+
+ @Test
+ public void testHTTPEndpointIsAvailable() throws IOException, URISyntaxException, KeyStoreException {
+ String serverHost = System.getenv("SERVER_HOST");
+ if (serverHost == null) {
+ serverHost = System.getProperty("server.host");
+ }
+ if (serverHost == null) {
+ serverHost = DEFAULT_SERVER_HOST;
+ }
+ String serverDir = System.getenv("SERVER_HOME");
+ if (serverDir == null) {
+ if (System.getProperty("jboss.server.config.dir").contains("target/server")) {
+ serverDir = System.getProperty("user.dir") + "/" + System.getProperty("jboss.server.config.dir");
+ } else {
+ serverDir = System.getProperty("jboss.server.config.dir");
+ }
+ }
+ HttpGet request = new HttpGet(new URI(serverHost+"/"));
+ KeyStore trustStore = createTrustStore(serverDir, "application.keystore", "password", "server", "PKCS12");
+ final HttpClient client = getHttpClientWithSSL(new File(serverDir + "/client.keystore.P12"), "secret", "PKCS12", new File(serverDir + "/client.truststore"), "password", "PKCS12");
+ HttpResponse response = client.execute(request);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ }
+
+ public HttpClient getHttpClientWithSSL(File keyStoreFile, String keyStorePassword, String keyStoreProvider,
+ File trustStoreFile, String trustStorePassword, String trustStoreProvider) {
+
+ try {
+ KeyStore trustStore = KeyStore.getInstance(trustStoreProvider);
+ try (FileInputStream fis = new FileInputStream(trustStoreFile)) {
+ trustStore.load(fis, trustStorePassword.toCharArray());
+ }
+ SSLContextBuilder sslContextBuilder = SSLContexts.custom()
+ .setProtocol("TLS")
+ .loadTrustMaterial(trustStore, null);
+ if (keyStoreFile != null) {
+ KeyStore keyStore = KeyStore.getInstance(keyStoreProvider);
+ try (FileInputStream fis = new FileInputStream(keyStoreFile)) {
+ keyStore.load(fis, keyStorePassword.toCharArray());
+ }
+ sslContextBuilder.loadKeyMaterial(keyStore, keyStorePassword.toCharArray(), null);
+ }
+ SSLContext sslContext = sslContextBuilder.build();
+ SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+
+ Registry registry = RegistryBuilder.create()
+ .register("http", PlainConnectionSocketFactory.getSocketFactory())
+ .register("https", socketFactory)
+ .build();
+
+ return HttpClientBuilder.create()
+ .setSSLSocketFactory(socketFactory)
+// .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .setConnectionManager(new PoolingHttpClientConnectionManager(registry))
+ .setSchemePortResolver(new DefaultSchemePortResolver())
+ .build();
+
+ } catch (Exception e) {
+ throw new RuntimeException("Creating HttpClient with customized SSL failed. We are returning the default one instead.", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/helloworld-mutual-ssl-secured/src/test/java/org/jboss/as/quickstarts/helloworld_mutual_ssl/KeystoreUtil.java b/helloworld-mutual-ssl-secured/src/test/java/org/jboss/as/quickstarts/helloworld_mutual_ssl/KeystoreUtil.java
new file mode 100644
index 0000000000..124ca796ce
--- /dev/null
+++ b/helloworld-mutual-ssl-secured/src/test/java/org/jboss/as/quickstarts/helloworld_mutual_ssl/KeystoreUtil.java
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * 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.jboss.as.quickstarts.helloworld_mutual_ssl;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+
+/**
+ * An interface to obtain the KeyPair from a keystore file.
+ *
+ * @author Prarthona Paul
+ */
+
+public class KeystoreUtil {
+
+ public static KeyStore createTrustStore(String serverDir, String keyStoreFile, String storePassword, String keyAlias, String keyStoreType) throws KeyStoreException {
+ FileInputStream stream = findFile(serverDir + "/" + keyStoreFile);
+ try {
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ keyStore.load(stream, storePassword.toCharArray());
+ Certificate cert = keyStore.getCertificate(keyAlias);
+ KeyStore trustStore = keyStore.getInstance(keyStoreType);
+ trustStore.load(null, null);
+ trustStore.setCertificateEntry("server", cert);
+ trustStore.store(new FileOutputStream(serverDir + "/" + "client.truststore"), storePassword.toCharArray());
+ return trustStore;
+ } catch (Exception e) {
+ throw new KeyStoreException(e.getMessage());
+ }
+ }
+
+ public static FileInputStream findFile(String keystoreFile) {
+ try {
+ return new FileInputStream(keystoreFile);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file