Saturday, October 30. 2021
Java ldappasswd implementation for the password modify extended operation


A quick entry this time to present a java implementation of the ldappasswd command tool. The ldap protocol by default performs a password change just sending the modification of the userPassword attribute, just like any other attribute. This behavior was considered not safe and an extended operation was standardized via rfc3062 soon. The extension allows to incorporate the typical requirements to the password change: ensure that it is done under adequate security conditions; allow sending the old password to validate it at modification time; generate a random password and return it to implement a reset... The final name of the extension is LDAP Password Modify Extended Operation (oid 1.3.6.1.4.1.4203.1.11.1) and nowadays it is supported by the majority of the servers. But the JNDI client does not include this extension and, although there are several implementations out there, I decided to implement it along with an ldappasswd counterpart just using plain JavaSE. This entry is the result of that adventure.
The post is not going to comment the java implementation in detail. The code consists in two classes for the standardized request and response (basically the management of the ASN.1 for the fields needed in both parts) and another one for the command. To use the extensions just create an LdapContext normally and call the extendedOperation method passing the initialized request. The LdapPasswd main class executes the same to perform the password change, so you can also check it if you want an example.
LdapContext ctx = new InitialLdapContext(env, null);
PasswordModifyExtendedRequest passwordModifyRequest = new PasswordModifyExtendedRequest(
"uid=ricky,ou=People,dc=sample,dc=com", "old-password", "new-password");
PasswordModifyExtendedResponse passwordModifyResponse =
(PasswordModifyExtendedResponse) ctx.extendedOperation(passwordModifyRequest);
The complete maven project can be downloaded from here and the usage for the main class is more or less the same than the one used in the UNIX package.
unzip ldappasswd.zip
cd ldappasswd
mvn clean package
java -jar target/ldappasswd-1.0.0-SNAPSHOT.jar -h
Exception in thread "main" java.lang.IllegalArgumentException:
USAGE: java -jar ldappasswd.jar [-H ldapuri] [-D binddn] [-W] [-w passwd] [-A] [-a oldPasswd] [-S] [-s newPasswd] [-Z] [user]
OPTIONS:
-H <ldapuri>: DN of the admin user to connect with (default: "ldap://localhost:389")
-D <binddn>: DN of the admin user to connect with (ex: "cn=Directory Manager")
-W: Promp for the password of the admin user to connect with
-w <passwd>: Password of the admin user to connect with
-A: Promp for the old password
-a <oldPasswd>: Old password of the user
-S: Promp for the new password
-s <newPasswd>: New password of the user
-k: insecure connection (accepts any certificate)
-Z: StartTLS before connecting.
-h: Prints this help.
ARGUMENTS:
[user]: DN of the user to change the password (if none it will be changed to the connected user)
Once the tool is ready it is time for the ldap server. This time the 389 Directory Server implementation is going to be used. This ldap software is also a derivative of the old netscape server and it is available in all linux distributions. I decided to install a Debian 11.1 in a VM and quickly setup the package. The installation and configuration is easy.
apt-get install 389-ds
dscreate interactive
Selinux support will be disabled, continue? Yes
Enter system hostname [debian11]:
Enter the instance name [debian11]:
Enter port number [389]:
Create self-signed certificate database [yes]:
Enter secure port number [636]:
Enter Directory Manager DN [cn=Directory Manager]:
Enter the Directory Manager password: password
Confirm the Directory Manager Password: password
Enter the database suffix (or enter "none" to skip) [dc=debian11]: dc=sample,dc=com
Create sample entries in the suffix [no]:
Create just the top suffix entry [no]: yes
Do you want to start the instance after the installation? [yes]:
Are you ready to install? [no]: yes
The software is installed and one instance is created using the default ports and a self-signed certificate. Then a user is added in order to perform the tests with it.
ldapmodify -h localhost -p 389 -D "cn=Directory Manager" -W
dn: ou=People,dc=sample,dc=com
changetype: add
objectclass: organizationalUnit
ou: People
adding new entry "ou=People,dc=sample,dc=com"
dn: uid=ricky,ou=People,dc=sample,dc=com
changetype: add
objectclass: inetorgperson
uid: ricky
sn: ricky
cn: ricky
userpassword: passsword
adding new entry "uid=ricky,ou=People,dc=sample,dc=com"
Now the server is congured to allow users to change their own passwords. An ACL is needed, which should be added to the tree.
ldapmodify -h localhost -p 389 -D "cn=Directory Manager" -W
dn: dc=sample,dc=com
changetype: modify
add: aci
aci: (targetattr = "userPassword") (version 3.0; acl "allow userpassword self modification"; allow (write) userdn = "ldap:///self";)
One more command is presented to show that 389-ds supports the password modify extension.
ldapsearch -h localhost -p 389 -D "cn=Directory Manager" -W -s base -b "" supportedExtension | grep 1.3.6.1.4.1.4203.1.11.1
supportedExtension: 1.3.6.1.4.1.4203.1.11.1
Finally the certificate used by the server was obtained and saved in debian11.p12 trust-store with password changeit. Time to start showing the ldappasswd command with different arguments.
Auto change the password for the same user passing the previous and new password:
java -Djavax.net.ssl.trustStore=debian11.p12 -Djavax.net.ssl.trustStorePassword=changeit -jar target/ldappasswd-1.0.0-SNAPSHOT.jar -H ldaps://debian11:636 -D "uid=ricky,ou=People,dc=sample,dc=com" -w password -a password -s new-password # Using LDAP url ldaps://debian11:636... # Connecting as user uid=ricky,ou=People,dc=sample,dc=com... # Performing password change...
Auto change the password with previous password but generating the new one:
java -Djavax.net.ssl.trustStore=debian11.p12 -Djavax.net.ssl.trustStorePassword=changeit -jar target/ldappasswd-1.0.0-SNAPSHOT.jar -H ldaps://debian11:636 -D "uid=ricky,ou=People,dc=sample,dc=com" -w password -a password # Using LDAP url ldaps://debian11:636... # Connecting as user uid=ricky,ou=People,dc=sample,dc=com... # Performing password change... # generated passwd: n02TRMuu
Using an administrator and only sending the new password:
java -Djavax.net.ssl.trustStore=debian11.p12 -Djavax.net.ssl.trustStorePassword=changeit -jar target/ldappasswd-1.0.0-SNAPSHOT.jar -H ldaps://debian11:636 -D "cn=Directory Manager" -w password -s new-password uid=ricky,ou=People,dc=sample,dc=com # Using LDAP url ldaps://debian11:636... # Connecting as user cn=Directory Manager... # Performing password change...
Using an admin user but performing a start SSL over the port 389.
java -Djavax.net.ssl.trustStore=debian11.p12 -Djavax.net.ssl.trustStorePassword=changeit -jar target/ldappasswd-1.0.0-SNAPSHOT.jar -H ldap://debian11 -Z -D "cn=Directory Manager" -w password -s new-password uid=ricky,ou=People,dc=sample,dc=com # Using LDAP url ldap://debian11... # Performing the StartTLS with user cn=Directory Manager... # Performing password change...
The operation cannot be done without TLS. This is enforced by the server.
java -Djavax.net.ssl.trustStore=debian11.p12 -Djavax.net.ssl.trustStorePassword=changeit -jar target/ldappasswd-1.0.0-SNAPSHOT.jar -H ldap://debian11 -D "cn=Directory Manager" -w password -s new-password uid=ricky,ou=People,dc=sample,dc=com # Using LDAP url ldap://debian11... # Connecting as user cn=Directory Manager... # Performing password change... Exception in thread "main" javax.naming.AuthenticationNotSupportedException: [LDAP: error code 13 - Operation requires a secure connection. ]; remaining name '' at ...
Please note that other servers can act differently. For example the attached maven project performs some tests using apache-ds and it does not generate any password in the response. Therefore with the apache software the new password is compulsory (-s or -S options in the command). As the RFC mentions, the server can not recognize or support the combination of the provided fields (user-dn, old and new password), in that case it should not proceed with the password change and return an error.
That is all for today. If, for whatever reason, you need the ldap modify password extension in a Java project, here you have an example that requires nothing except JavaSE. Feel free to re-use or extend the code as you need.
Extended regards!
Saturday, October 16. 2021
OpenSSL3 FIPS for wildfly?


Today's entry is going to continue with wildfly and the security standard FIPS. The previous entry was about configuring the application server with the bouncy castle FIPS implementation. But this time the (in)famous openssl library will be used instead. Until now the openssl FIPS was a separate module that only worked with version 1.0.2, but the recent release of version 3.0.0 introduces the idea of crypto providers, and a new FIPS provider is now included by default. On the other side wildfly can be configured to use openssl instead of the native JSSE implementation. The projects wildfly-openssl and wildfly-openssl-natives wrap the C library in order to transform it into a Java SSL engine. So, with both ideas in place, there is a new easy option to configure FIPS inside wildfly.
Nevertheless the previous statement is not right or, better said, it is not right yet. There are mainly two snags:
The wildfly projects should be modified to make the server work with the new openssl version 3. Hopefully the enhancement will be managed by issues WFSSL-80 and SSLNTV-13.
The new openssl3 FIPS implementation is still not validated by the NIST. Currently the request is submitted for review and it is expected to take several months.
So today's entry is going to configure a FIPS setup for wildfly which is still not ready. But, once the previous two points are fixed, the combination of openssl and wildfly will be FIPS compliant. In my humble opinion that setup can be very useful. The rest of the entry is going to describe step by step how to perform that configuration.
Download, compile and install the openssl. Nowadays the last version 3.0.0 is still not included by default in any common linux distribution. So the bundle will be compiled manually with the FIPS provider enabled.
wget https://www.openssl.org/source/openssl-3.0.0.tar.gz tar zxvf openssl-3.0.0.tar.gz cd openssl-3.0.0/ ./Configure enable-fips --prefix=/path/to/openssl-3.0.0 make make test make install
Modify the configuration file openssl.cnf following the FIPS documentation presented before.
diff -Naur openssl.cnf.ORIG openssl.cnf --- openssl.cnf.ORIG 2021-10-09 19:32:01.537655962 +0200 +++ openssl.cnf 2021-10-09 19:44:20.252969136 +0200 @@ -48,17 +48,18 @@ # fips provider. It contains a named section e.g. [fips_sect] which is # referenced from the [provider_sect] below. # Refer to the OpenSSL security policy for more information. -# .include fipsmodule.cnf +.include /path/to/openssl-3.0.0/ssl/fipsmodule.cnf [openssl_init] providers = provider_sect # List of providers to load [provider_sect] -default = default_sect +#default = default_sect # The fips section name should match the section name inside the # included fipsmodule.cnf. -# fips = fips_sect +fips = fips_sect +base = base_sect # If no providers are activated explicitly, the default one is activated implicitly. # See man 7 OSSL_PROVIDER-default for more details. @@ -71,6 +72,8 @@ [default_sect] # activate = 1 +[base_sect] +activate = 1 #################################################################### [ ca ]
FIPS is enabled globally for the library. The idea is that the default provider is commented out and the new FIPS one is added as the only activated algorithm provider (from now on all the applications will use FIPS compulsorily). For example if the ciphers command is executed for TLSv1.3 only the two FIPS compliant ciphers are displayed (TLS_CHACHA20_POLY1305_SHA256 is also available in the out of the box configuration but not listed when FIPS is enforced).
./openssl ciphers -s -v -tls1_3 TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
Time for the wildfly installation. Today this point is not going to be detailed because a development version of the project is necessary. As commented before both wildfly-openssl projects need modifications in order to work with openssl version 3. So for the entry a compiled version of wildfly is used with both modules upgraded with the fixes incorporated.
unzip wildfly-26.0.0.Beta1-SNAPSHOT.zip cd wildfly-26.0.0.Beta1-SNAPSHOT/bin/ ./add-user.sh -u admin -p admin
Generate a RSA key to be used by the server.
keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -validity 365 -keystore ../standalone/configuration/keystore.p12 -storetype pkcs12 -dname "CN=localhost" -storepass password -ext san=dns:localhost,ip:127.0.0.1
Start the server using a JDK version 11 and pointing to the compiled openssl3 libraries to not use the default system ones.
export JAVA_HOME=/usr/lib/jvm/java-11 ./standalone.sh -Dorg.wildfly.openssl.path.ssl=/path/to/openssl-3.0.0/lib64/libssl.so -Dorg.wildfly.openssl.path.crypto=/path/to/openssl-3.0.0/lib64/libcrypto.so
Finally configure the security subsystem to use openssl and the RSA certificate just created. Note that in order to make TLSv1.3 available the option cipher-suite-names should be set with the wanted values (in our case the two complaint ciphers listed before).
/subsystem=elytron/key-store=sslKS:add(path=keystore.p12, type=PKCS12, relative-to=jboss.server.config.dir, credential-reference={clear-text=password}) /subsystem=elytron/key-manager=sslKM:add(key-store=sslKS, algorithm="PKIX", credential-reference={clear-text=password}) /subsystem=elytron/server-ssl-context=sslSSC:add(providers=openssl, key-manager=sslKM, protocols=[TLSv1.2, TLSv1.3], cipher-suite-names=TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256) /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context, value=sslSSC) reload
And that is all. Now the boot messages should contain the following line saying that the version 3.0.0 of openssl is used.
17:19:09,633 INFO [org.wildfly.openssl.SSL] (MSC service thread 1-5) WFOPENSSL0002 OpenSSL Version OpenSSL 3.0.0 7 sep 2021
Using curl the TLS_AES_256_GCM_SHA384 cipher is selected for TLSv1.3:
curl -k -v -I https://localhost:8443/ * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt * CApath: none * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=localhost * start date: Oct 10 11:08:18 2021 GMT * expire date: Oct 10 11:08:18 2022 GMT * issuer: CN=localhost * SSL certificate verify result: self signed certificate (18), continuing anyway. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x55b4e9f48c30) > HEAD / HTTP/2 > Host: localhost:8443 > user-agent: curl/7.76.1 > accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)! < HTTP/2 200 HTTP/2 200 < last-modified: Sun, 10 Oct 2021 10:32:16 GMT last-modified: Sun, 10 Oct 2021 10:32:16 GMT < content-length: 1504 content-length: 1504 < content-type: text/html content-type: text/html < accept-ranges: bytes accept-ranges: bytes < date: Wed, 13 Oct 2021 15:21:27 GMT date: Wed, 13 Oct 2021 15:21:27 GMT
And forcing TLSv1.2 the cipher ECDHE-RSA-AES256-GCM-SHA384 is used:
curl -k -v -I --tls-max 1.2 https://localhost:8443/ * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt * CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=localhost * start date: Oct 10 11:08:18 2021 GMT * expire date: Oct 10 11:08:18 2022 GMT * issuer: CN=localhost * SSL certificate verify result: self signed certificate (18), continuing anyway. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x558282f4dc30) > HEAD / HTTP/2 > Host: localhost:8443 > user-agent: curl/7.76.1 > accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)! < HTTP/2 200 HTTP/2 200 < last-modified: Sun, 10 Oct 2021 10:32:16 GMT last-modified: Sun, 10 Oct 2021 10:32:16 GMT < content-length: 1504 content-length: 1504 < content-type: text/html content-type: text/html < accept-ranges: bytes accept-ranges: bytes < date: Wed, 13 Oct 2021 15:22:55 GMT date: Wed, 13 Oct 2021 15:22:55 GMT
The current entry is just an advance of a new SSL FIPS configuration that will be available in wildfly. The idea is using the new openssl3 configured in FIPS mode as the provider for the elytron context. The setup is not ready at this moment, some PRs should be merged for wildfly and the openssl3 is not a certified FIPS implementation yet. If everything goes as expected the setup will be ready in some months.
FIPS regards!
Sunday, August 1. 2021
Configuring BCFIPS in wildfly via elytron


More or less one year ago an unsuccessful try to configure Bouncy Castle FIPS in wildfly and openjdk 11 was presented in the blog. At that time only the direct JVM setup was performed (adding the BCFIPS at java.security file level). I already knew that the elytron subsystem also had the ability of loading and enabling JCE providers for applications (registering the providers in the Security class). But I did not realize that, using this feature, a new option was at our disposal for adding the BCFIPS to the application server. Recently I discovered this elytron bug and it gave me this idea. So today's entry is going to configure again the BCFIPS inside a wildfly and openjdk 11 server, but this time, via elytron.
As always the steps followed to perform the full configuration are presented one by one.
The last openjdk 11 is installed in the system. The path for the java installation will be ${JAVA_HOME} from now on.
wget https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.11%2B9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.11_9.tar.gz tar zxvf OpenJDK11U-jdk_x64_linux_hotspot_11.0.11_9.tar.gz
Next wildfly 24.0.1 is installed. The directory where the server is unzipped will be called ${WILDFLY_HOME}.
wget https://download.jboss.org/wildfly/24.0.1.Final/wildfly-24.0.1.Final.zip unzip wildfly-24.0.1.Final.zip cd wildfly-24.0.1.Final/bin/ ./add-user.sh -u admin -p admin export JAVA_HOME=/path/to/jdk-11.0.11+9 ./standalone
Now from the Bouncy Castle page download the FIPS (bc-fips-1.0.2.1.jar) and the JSSE (bctls-fips-1.0.12.1.jar) provider files. This try the BCJSSE implementation from Bouncy Castle will be used instead of the default SunJSSE used in the previous entry. The jars are downloaded to ${FIPS_HOME} folder.
Time to create the stores with the server certificate and the trusted CAs. The BCFKS custom format is used to show that the BCFIPS provider is really in place.
cd ${WILDFLY_HOME}/standalone/configuration/ ${JAVA_HOME}/bin/keytool -providername BCFIPS -providerpath ${FIPS_HOME}/bc-fips-1.0.2.1.jar -providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -genkeypair -alias localhost -keyalg RSA -keysize 2048 -validity 365 -keystore localhost.bcfks -storetype bcfks -dname "CN=localhost" -storepass secret -keypass secret -ext "SAN=DNS:localhost,IP:127.0.0.1" cp ${JAVA_HOME}/lib/security/cacerts . ${JAVA_HOME}/bin/keytool -providername BCFIPS -providerpath ${FIPS_HOME}/bc-fips-1.0.2.1.jar -providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -importkeystore -srckeystore cacerts -destkeystore cacerts.bcfks -srcstoretype JKS -deststoretype bcfks -srcstorepass changeit -deststorepass changeit
The elytron magic starts here. Both jar files are registered as modules inside the server using CLI. Please note that the JSSE module has the main one as a dependency.
module add --name=org.bouncycastle.fips --resources=${FIPS_HOME}/bc-fips-1.0.2.1.jar module add --name=org.bouncycastle.tls.fips --resources=${FIPS_HOME}/bctls-fips-1.0.12.1.jar --dependencies=org.bouncycastle.fips
The BC documentation (which only explains direct JVM configuration using the java.security file) says that the providers should be configured like this:
security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS
So the main FIPS provider is defined first and then the JSSE one needs the argument fips:BCFIPS. This means that the latter is in fips mode and it will use the main BCFIPS provider defined previously to perform the security operations. But, how do we do this inside elytron? This is the only tricky point needed for the configuration. Passing one provider to another provider cannot be configured in wildfly. But the BCJSSE also understands a fully qualified class name. Therefore this setup works:
/subsystem=elytron/provider-loader=bc-fips:add(module=org.bouncycastle.fips) /subsystem=elytron/provider-loader=bc-fips-tls:add(module=org.bouncycastle.tls.fips, class-names=[org.bouncycastle.jsse.provider.BouncyCastleJsseProvider], argument="fips:org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider")
It is extremely important that the BCJSSE provider is registered passing the argument parameter. The value should be fips:org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider, fips mode and the BCFIPS provider but using the class name.
The common configuration for stores and ssl context is performed now, but using the appropriate provider for each step. First the key store and manager:
/subsystem=elytron/key-store=fipsKS:add(path=localhost.bcfks, relative-to=jboss.server.config.dir, credential-reference={clear-text=secret}, type=bcfks, providers=bc-fips) /subsystem=elytron/key-manager=fipsKM:add(key-store=fipsKS, algorithm="PKIX", credential-reference={clear-text=secret}, providers=bc-fips-tls)
Then the same thing for the trust store and manager:
/subsystem=elytron/key-store=fipsCAKS:add(type=bcfks, relative-to=jboss.server.config.dir, path=cacerts.bcfks, credential-reference={clear-text=changeit}, providers=bc-fips) /subsystem=elytron/trust-manager=fipsTM:add(key-store=fipsCAKS, providers=bc-fips-tls)
The server ssl context is created with the previous elements. Please note that only TLSv1.2 is configured. TLSv1.3 was tried first but it seems that currently the BCFIPS implementation has no ciphers for this version.
/subsystem=elytron/server-ssl-context=fipsSSC:add(key-manager=fipsKM, trust-manager=fipsTM, protocols=["TLSv1.2"], providers=bc-fips-tls)
Finally the ssl context is assigned to the https listener.
batch /subsystem=undertow/server=default-server/https-listener=https:undefine-attribute(name=security-realm) /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context, value=fipsSSC) run-batch
And that is all. The Bouncy Castle FIPS is configured and used for the default 8443 secure port. Using for example curl you can see that the server is working and our certificate is displayed.
curl -k -v -I https://localhost:8443/ Trying 127.0.0.1:8443... Connected to localhost (127.0.0.1) port 8443 (#0) ALPN, offering h2 ALPN, offering http/1.1 successfully set certificate verify locations: CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none TLSv1.3 (OUT), TLS handshake, Client hello (1): TLSv1.3 (IN), TLS handshake, Server hello (2): TLSv1.2 (IN), TLS handshake, Certificate (11): TLSv1.2 (IN), TLS handshake, Server key exchange (12): TLSv1.2 (IN), TLS handshake, Server finished (14): TLSv1.2 (OUT), TLS handshake, Client key exchange (16): TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): TLSv1.2 (OUT), TLS handshake, Finished (20): TLSv1.2 (IN), TLS handshake, Finished (20): SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 ALPN, server accepted to use h2 Server certificate: subject: CN=localhost start date: Jul 31 10:30:19 2021 GMT expire date: Jul 31 10:30:19 2022 GMT issuer: CN=localhost SSL certificate verify result: self signed certificate (18), continuing anyway. Using HTTP2, server supports multi-use Connection state changed (HTTP/2 confirmed) Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 Using Stream ID: 1 (easy handle 0x55e78bb10aa0) > HEAD / HTTP/2 > Host: localhost:8443 > user-agent: curl/7.71.1 > accept: / > Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)! < HTTP/2 200 HTTP/2 200 < last-modified: Tue, 27 Jul 2021 08:03:32 GMT last-modified: Tue, 27 Jul 2021 08:03:32 GMT < content-length: 1504 content-length: 1504 < content-type: text/html content-type: text/html < accept-ranges: bytes accept-ranges: bytes < date: Sat, 31 Jul 2021 11:13:42 GMT date: Sat, 31 Jul 2021 11:13:42 GMT
At this point there are more options you can be interested in configuring. For example elytron allows to include the JCE providers into the JVM. This way the applications can use the provider as usual (getProvider("BCFIPS") for example). Check the final-providers and the default combined-providers to see how elytron and openssl providers are exposed by default. Another interesting feature is setting the default-ssl-context at JVM level, allowing to configure a BCFIPS ssl context as the default one for applications.
So today's entry finally shows a working BCFIPS configuration for wildfly and openjdk 11. The removal of the extension mechanism in java complicated a lot the installation of custom JCE providers inside the wildfly server (a thing that was very easy with version 8). But finally elytron was the right component for the goal. The new security system allows the installation of JCE providers and let us configure the different security elements with them (key and trust stores, managers, ssl contexts,...). The only trick in the setup was passing the BCFIPS provider to the BCJSSE provider, but luckily it accepts a class name and that can be configured inside elytron. Note that in this entry the BCJSSE implementation was used instead of the default SunJSSE, elytron is used and not the java.security file, so using an external JSSE implementation is much easier.
Best regards!
Comments