This is a complete tutorial about configuring SSL/HTTPS support for JBoss EAP / WildFly application server.
Generally speaking, to configure SSL/HTTPS you can either use the pure JSSE implementation (and the keytool utility) or a native implementation such as OpenSSL. We will cover at first the JSSE implementation with keytool. Later we will show how to enable OpenSSL on WildFly 11 or newer.
Create server and client certificates
The keytool utility stores the keys and certificates in a keystore file, which is a repository of certificates used for identifying a client or a server. Typically, a keystore contains one client or one server’s identity, which can optionally include a password.
You can create a certificate for your server using the following command:
$ keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -validity 365 -keystore server.keystore -dname "cn=Server Administrator,o=Acme,c=GB" -keypass secret -storepass secret
This command creates the keystore server.keystore in the working directory, with the password “secret” . It generates a public/private key pair for the entity whose “distinguished name” has a common name of Server Administrator , organization of Acme and two-letter country code of GB.
TIP: The message “The JKS keystore uses a proprietary format” simply reminds you that JKS is a format specific to Java. PKCS12, on the other hand, is the standardized and language-neutral way of storing encrypted private keys and certificates. You can generate a PKCS12 format using the option -storetype PKCS12 or importing the JKS file into a PKCS12 one with the following command:
keytool -importkeystore -srckeystore server.keystore -destkeystore server.keystore -deststoretype pkcs12
Now let’s store the server keystore into the configuration folder of the application server:
$ cp server.keystore $JBOSS_HOME/standalone/configuration
If you only need a one-way authentication (Server–>Client) then you are done.
Configuring Two-way SSL
On the other hand, if you need a two-way authentication (Server<–>Client) then we need to create as well the client certificates and export them to create a truststore.
The following command, will create the client certificate, which you can use to authenticate against the server when accessing a resource through SSL:
$ keytool -genkeypair -alias client -keyalg RSA -keysize 2048 -validity 365 -keystore client.keystore -dname "CN=client" -keypass secret -storepass secret
Now export both the client and the server keystores in a certificate file:
$ keytool -exportcert -keystore server.keystore -alias localhost -keypass secret -storepass secret -file server.crt $ keytool -exportcert -keystore client.keystore -alias client -keypass secret -storepass secret -file client.crt
Finally, import the certificates into the server’s and client’s truststores:
$ keytool -importcert -keystore server.truststore -storepass secret -alias client -trustcacerts -file client.crt -noprompt $ keytool -importcert -keystore client.truststore -storepass secret -alias localhost -trustcacerts -file server.crt -noprompt
The above commands are available in this script at:
Finally, we will also store the the client.truststore into the configuration folder of the application server:
$ cp client.truststore $JBOSS_HOME/standalone/configuration
Configuring One-Way SSL / HTTPS for WildFly applications
When using WildFly 11 or newer you can either use Elytron or the Legacy SSL configuration.
To verify which one is the default one check and see if the https-listener is configured to use a legacy security realm for its SSL configuration:
/subsystem=undertow/server=default-server/https-listener=https:read-attribute(name=security-realm) { "outcome" => "success", "result" => undefined }
The above command shows that there is no legacy ApplicationRealm bound to the https-listener. You can jump to the batch script below.
On the other hand, if the https-listener uses the legacy ApplicationRealm for its SSL configuration you need to undefine it first:
/subsystem=undertow/server=default-server/https-listener=https:undefine-attribute(name=security-realm)
Next, run the following CLI batch script. The script will add the keystores the key manager and the ssl-context configuration in the elytron subsystem. Finally, it will store the SSL Context information in the https-listener.
batch # Configure Server Keystore /subsystem=elytron/key-store=demoKeyStore:add(path=server.keystore,relative-to=jboss.server.config.dir, credential-reference={clear-text=secret},type=JKS) # Server Keystore credentials /subsystem=elytron/key-manager=demoKeyManager:add(key-store=demoKeyStore,credential-reference={clear-text=secret}) # Server keystore Protocols /subsystem=elytron/server-ssl-context=demoSSLContext:add(key-manager=demoKeyManager,protocols=["TLSv1.2"]) # Store SSL Context information in undertow /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=demoSSLContext) run-batch reload
You can find the above CLI script at:
Finally, try to access a WildFly through the https://localhost:8443 address. You will get a warning as you are using a self-signed certificate. If you add an exception to the browser, you will be running through the SSL channel, with your certificate.
As you can see from the Browser Developer Console, the Connection uses a Secure Socket Layer with the data from our Certificate:
Alternatively, you can use the curl command with the –verbose option (-v) to see details about the SSL Handshake:
curl -v https://localhost:8443
TIP: You can also define a default SSL Context to be used by the Elytron subsystem, by setting the property default-ssl-context that will reference to the SSLContext which should be globally registered as the default.
How to view your certificate
You can dump your SSL session from the command line using openssl tool as follows:
$ openssl s_client -showcerts -connect localhost:8443 CONNECTED(00000003) Can't use SSL_get_servername depth=0 C = GB, O = Acme, CN = Server Administrator verify error:num=18:self signed certificate verify return:1 depth=0 C = GB, O = Acme, CN = Server Administrator verify return:1 --- Certificate chain 0 s:C = GB, O = Acme, CN = Server Administrator i:C = GB, O = Acme, CN = Server Administrator -----BEGIN CERTIFICATE----- MIIDFTCCAf2gAwIBAgIEYWcexzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJH QjENMAsGA1UEChMEQWNtZTEdMBsGA1UEAxMUU2VydmVyIEFkbWluaXN0cmF0b3Iw HhcNMjEwMjI3MTEzNzQ3WhcNMjIwMjI3MTEzNzQ3WjA7MQswCQYDVQQGEwJHQjEN MAsGA1UEChMEQWNtZTEdMBsGA1UEAxMUU2VydmVyIEFkbWluaXN0cmF0b3IwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtBmaeo7l2/CaW+FPY5UZOnlOY Pg4xQtr5SHIR7mF3Q5+jfxi4trGWia0yRd6ae0pBF3tyVQAf/C7gZDPRczxnshoc TQD/7vtEJcUJ5N7k+DXqoFtn7vkXyFpvilSVT1PCnlkuAXD9jZnDhRl8xfs16pVQ Sm+NxOGFLlsLr5iJWsGHSLmRqTrGPcY1aPbXAahGLtqE/rPwVGt4nXhbKV9s3tsD LDQHOfsbbm8qbxmR47IdMR5XNx8vhJt+fhB/ZVgoFUw+CVMmEa8PfNxWY/fDFiPU ePv3/ZRzagLfnlpN+vVZTaZsJUHysumfEhlpRjiqPWLXlk3SVfIboL6nrPfBAgMB AAGjITAfMB0GA1UdDgQWBBRy5STkvTGZuddpCBPR+CcBXHzVXzANBgkqhkiG9w0B AQsFAAOCAQEAc0NYtsjBBueHjc6hgeMZmBqq7agZ7IkRSNrHQTUtznYAD/K3aZU9 G4NbxZ+weHpsaJc9qg0zmdDjLgSmYOAR87OU0OAAXf47h2ZUMQIpdmJMf/swBXsH /QmWS6CBmaGGm6ND29mNyzdRDwYbeG45j2DYZI9a1TK2x3WLS0H5on4qRcqUWElW iItwR22QlKrWdiBcl0jSxxJNPdFU0DSCGNwJqByYalS6Z0d+AQG6y7BMIsdyLi06 zNP+8auhvex5LmUx8tEWO4pxhLe+G4iVm6XXVUkgw+6tBwDLzpaL+eL/EQZZWLbP WrrpXVlYc/kuxq4iJtTFWEMCZEnzWblyYA== -----END CERTIFICATE----- --- Server certificate subject=C = GB, O = Acme, CN = Server Administrator issuer=C = GB, O = Acme, CN = Server Administrator --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: ECDH, P-256, 256 bits --- SSL handshake has read 1281 bytes and written 429 bytes Verification error: self signed certificate --- New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: DFB40F6008C4BF507807DFBBDFD3E937195595E191221631EF20F18296C6F845 Session-ID-ctx: Master-Key: 87A7C384BE6F232D63903BC18CD385A6F29216CA1D0F281E9976785D89C990BE92E5B0F4C20618619B416407F6D24055 PSK identity: None PSK identity hint: None SRP username: None Start Time: 1614426182 Timeout : 7200 (sec) Verify return code: 18 (self signed certificate) Extended master secret: yes ---
As an alternative, you can also dump the Certificate from the CLI by referencing its keystore:
/subsystem=elytron/key-store=demoKeyStore:read-alias(alias=localhost,verbose=false)
Changes in your configuration
If you have completed the above steps, the following tls section should be in your XML Configuration:
<tls> <key-stores> <key-store name="demoKeyStore"> <credential-reference clear-text="secret"/> <implementation type="JKS"/> <file path="server.keystore" relative-to="jboss.server.config.dir"/> </key-store> </key-stores> <key-managers> <key-manager name="demoKeyManager" key-store="demoKeyStore"> <credential-reference clear-text="secret"/> </key-manager> </key-managers> <server-ssl-contexts> <server-ssl-context name="demoSSLContext" protocols="TLSv1.2" key-manager="demoKeyManager"/> </server-ssl-contexts> </tls>
Finally, here is the corresponding undertow section:
<subsystem xmlns="urn:jboss:domain:undertow:10.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}"> <buffer-cache name="default"/> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> <https-listener name="https" socket-binding="https" ssl-context="demoSSLContext" enable-http2="true"/> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content"/> <filter-ref name="server-header"/> <filter-ref name="x-powered-by-header"/> <http-invoker security-realm="ApplicationRealm"/> </host> </server>
Configuring Mutual SSL Authentication for WildFly applications
Mutual SSL provides the same security as SSL, with the addition of authentication and non-repudiation of the client authentication, using digital signatures. When mutual authentication is in place, the server would request the client to provide a certificate in addition to the server certificate issued to the client. Mutual authentication requires an extra round trip time for client certificate exchange. In addition, the client must buy and maintain a digital certificate. We can secure our war application deployed over WildFly with mutual(two-way) client certificate authentication and provide access permissions or privileges to legitimate users.
IMPORTANT: It is assumed that you have already completed the One-Way SSL configuration for the server as discussed earlier in this tutorial!
In order to update your One-Way configuration to use Mutual SSL configuration, we need a SSL Context which includes also the Client Truststore and TrustManager in its configuration:
batch # Add the Truststore, TrustManager to a SSL Context configuration /subsystem=elytron/key-store=demoTrustStore:add(path=client.truststore,relative-to=jboss.server.config.dir,type=JKS,credential-reference={clear-text=secret}) /subsystem=elytron/trust-manager=demoTrustManager:add(key-store=demoTrustStore) /subsystem=elytron/server-ssl-context=twoWaySSL:add(key-manager=demoKeyManager,trust-manager=demoTrustManager,protocols=[TLSv1.2],need-client-auth=true) # This is only needed if WildFly uses by default the Legacy security realm /subsystem=undertow/server=default-server/https-listener=https:undefine-attribute(name=security-realm) # Store SSL Context information in undertow /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=twoWaySSL) run-batch reload
Using the CLI security command to configure One-Way HTTPS
If you prefer, a simpler way to enable SSL for the HTTP server is by means of the **security enable-ssl-http-server** CLI command. This command has the advantage of combining the definition of the key-store, key-manager and ssl-context in just one command. So, assumed that the file server.keystore is in the same folder as the jboss-cli, you can enable SSL for the HTTP server as follows:
[standalone@localhost:9990 /] security enable-ssl-http-server --key-store-path=server.keystore --key-store-password=secret Server reloaded. SSL enabled for default-server ssl-context is ssl-context-server.keystore key-manager is key-manager-server.keystore key-store is server.keystore
Your One-Way SSL configuration is ready and the server has been reloaded for you to reflect the changes. You can also use the **–interactive** option which will let you create also the keystore. Here is a transcript of a sample ssl configuration for the HTTP server which will eventually create the file wildfly.keystore, the certificate file wildfly.pem and wildfly.csr file in server configuration directory:
[standalone@localhost:9990 /] security enable-ssl-http-server --interactive Please provide required pieces of information to enable SSL: Certificate info: Key-store file name (default default-server.keystore): wildfly.keystore Password (blank generated): password What is your first and last name? [Unknown]: John Smith What is the name of your organizational unit? [Unknown]: QA What is the name of your organization? [Unknown]: Acme What is the name of your City or Locality? [Unknown]: London What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: UK Is CN=John Smith, OU=QA, O=Acme, L=London, ST=Unknown, C=UK correct y/n [y]?y Validity (in days, blank default): Alias (blank generated): jsmith Enable SSL Mutual Authentication y/n (blank n):n SSL options: key store file: wildfly.keystore distinguished name: CN=John Smith, OU=QA, O=Acme, L=London, ST=Unknown, C=UK password: password validity: default alias: jsmith Server keystore file wildfly.keystore, certificate file wildfly.pem and wildfly.csr file will be generated in server configuration directory. Do you confirm y/n :y Server reloaded. SSL enabled for default-server ssl-context is ssl-context-24f3d44b-a511-4b54-9610-ac414a8b6143 key-manager is key-manager-24f3d44b-a511-4b54-9610-ac414a8b6143 key-store is key-store-24f3d44b-a511-4b54-9610-ac414a8b6143
Configuring OpenSSL as provider
When using Elytron for SSL/HTTPS you can opt for two different providers:
<providers> <aggregate-providers name="combined-providers"> <providers name="openssl"/> <providers name="elytron"/> </aggregate-providers> <provider-loader name="elytron" module="org.wildfly.security.elytron"/> <provider-loader name="openssl" module="org.wildfly.openssl"/> </providers>
In order to switch to OpenSSL, run the following CLI script:
/subsystem=elytron:write-attribute(name=initial-providers, value=combined-providers) /subsystem=elytron:undefine-attribute(name=final-providers) reload
You will see the following log that confirms your OpenSSL version:
19:06:23,403 INFO [org.wildfly.openssl.SSL] (MSC service thread 1-3) WFOPENSSL0002 OpenSSL Version OpenSSL 1.1.1q FIPS 5 Jul 2022
On the other hand, you can also choose to configure SSL as provider for a single SSL Context. For example, let’s switch to OpenSSL for the sample demoSSLContext
. You can add the providers
additional parameter to it:
/subsystem=elytron/server-ssl-context=demoSSLContext:add(key-manager=demoKeyManager,protocols=["TLSv1.2"],providers=openssl)
Finally, it’s worth mentioning that you can specify a custom path for the for the OpenSSL library by setting the org.wildfly.openssl.path System Property at server startup.
Configuring SSL using Legacy mode
If you are using an earlier version of WildFly (8/9/10) or you simply don’t want to use Elytron as security mechanism, you can still use the Legacy security for securing your HTTP communication.
Start by creating a Security Realm which will contain the keystore and trustore references
/core-service=management/security-realm=SSLRealm:add
Next, for one-way SSL, set the path to the keystore, along with the keystore path and password:
/core-service=management/security-realm=SSLRealm/server-identity=ssl:add(keystore-path="server.keystore", keystore-relative-to="jboss.server.config.dir", keystore-password="secret")
If you are using mutual authentication, you will need to set the path to the truststore, along with the its path and password:
/core-service=management/security-realm=SSLRealm/authentication=truststore:add(keystore-password="secret",keystore-path="server.truststore",keystore-relative-to="jboss.server.config.dir")
Finally, set the value of Undertow’s https listener to your Security Realm:
/subsystem=undertow/server=default-server/https-listener=default-https:write-attribute(name=security-realm,value=SSLRealm)
Conclusion
This tutorial has covered how to configure TLS/SSL on WildFly application server. If you want to use the latest version of TLS (1.3), you can continue reading here: Configuring TLS 1.3 on WildFly application Server
On the other hand, if you want to configure TLS/SSL for WildFly Management interfaces, check out this tutorial: Securing JBoss / WildFly Management Interfaces: the easy way