Skip to content

Instantly share code, notes, and snippets.

@jnwelzel
Last active May 9, 2021 22:32
Show Gist options
  • Save jnwelzel/5339093 to your computer and use it in GitHub Desktop.
Save jnwelzel/5339093 to your computer and use it in GitHub Desktop.
Client authentication through SSL certificate in JBoss AS 7.1.1.Final. This configuration will make sure that only clients whose certificates are trusted by the server may have access to the application (standalone.xml line 272)
PASSWORD
changethis
SERVER KEYSTORE - used by the server to establish a secure connection (HTTPS)
c:\eclipse\jdk1.7.0_05\jre\bin\keytool.exe -genkey -keyalg RSA -alias localhost -keystore localhost.jks -validity 365 -keysize 2048
CLIENT KEYSTORE - used to generate ".cer" file that wil be used in the server's trustore and in the browser to identify the client with the server
c:\eclipse\jdk1.7.0_05\jre\bin\keytool.exe -genkey -keyalg RSA -alias jonwelzel -keystore jonwelzel.jks -validity 365 -keysize 2048
PFX FROM JKS - the pfx will be used in the browser for example
c:\eclipse\jdk1.7.0_05\jre\bin\keytool.exe -importkeystore -srckeystore jonwelzel.jks -srcstoretype JKS -destkeystore jonwelzel.pfx -deststoretype PKCS12
ADD CLIENT'S CERT TO SERVER'S TRUSTSTORE - this will make sure that the client will be able to access the application only if he uses this certificate (the truststore password and the server keystore password must be the same)
c:\eclipse\jdk1.7.0_05\jre\bin\keytool.exe -import -v -trustcacerts -alias client-alias -file jonwelzel.cer -keystore cacerts.jks -keypass changeit -storepass changeit
<?xml version='1.0' encoding='UTF-8'?>
<server xmlns="urn:jboss:domain:1.2">
<extensions>
<extension module="org.jboss.as.clustering.infinispan"/>
<extension module="org.jboss.as.configadmin"/>
<extension module="org.jboss.as.connector"/>
<extension module="org.jboss.as.deployment-scanner"/>
<extension module="org.jboss.as.ee"/>
<extension module="org.jboss.as.ejb3"/>
<extension module="org.jboss.as.jaxrs"/>
<extension module="org.jboss.as.jdr"/>
<extension module="org.jboss.as.jmx"/>
<extension module="org.jboss.as.jpa"/>
<extension module="org.jboss.as.logging"/>
<extension module="org.jboss.as.mail"/>
<extension module="org.jboss.as.naming"/>
<extension module="org.jboss.as.osgi"/>
<extension module="org.jboss.as.pojo"/>
<extension module="org.jboss.as.remoting"/>
<extension module="org.jboss.as.sar"/>
<extension module="org.jboss.as.security"/>
<extension module="org.jboss.as.threads"/>
<extension module="org.jboss.as.transactions"/>
<extension module="org.jboss.as.web"/>
<extension module="org.jboss.as.webservices"/>
<extension module="org.jboss.as.weld"/>
</extensions>
<management>
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
<security-realm name="ApplicationRealm">
<authentication>
<properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
</security-realms>
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket-binding native="management-native"/>
</native-interface>
<http-interface security-realm="ManagementRealm">
<socket-binding http="management-http"/>
</http-interface>
</management-interfaces>
</management>
<profile>
<subsystem xmlns="urn:jboss:domain:logging:1.1">
<console-handler name="CONSOLE">
<level name="INFO"/>
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
<logger category="org.apache.tomcat.util.modeler">
<level name="WARN"/>
</logger>
<logger category="sun.rmi">
<level name="WARN"/>
</logger>
<logger category="jacorb">
<level name="WARN"/>
</logger>
<logger category="jacorb.config">
<level name="ERROR"/>
</logger>
<root-logger>
<level name="INFO"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
</subsystem>
<subsystem xmlns="urn:jboss:domain:configadmin:1.0"/>
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
<subsystem xmlns="urn:jboss:domain:deployment-scanner:1.1">
<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:ee:1.0"/>
<subsystem xmlns="urn:jboss:domain:ejb3:1.2">
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
<stateful default-access-timeout="5000" cache-ref="simple"/>
<singleton default-access-timeout="5000"/>
</session-bean>
<pools>
<bean-instance-pools>
<strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
<strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
<caches>
<cache name="simple" aliases="NoPassivationCache"/>
<cache name="passivating" passivation-store-ref="file" aliases="SimpleStatefulCache"/>
</caches>
<passivation-stores>
<file-passivation-store name="file"/>
</passivation-stores>
<async thread-pool-name="default"/>
<timer-service thread-pool-name="default">
<data-store path="timer-service-data" relative-to="jboss.server.data.dir"/>
</timer-service>
<remote connector-ref="remoting-connector" thread-pool-name="default"/>
<thread-pools>
<thread-pool name="default">
<max-threads count="10"/>
<keepalive-time time="100" unit="milliseconds"/>
</thread-pool>
</thread-pools>
</subsystem>
<subsystem xmlns="urn:jboss:domain:infinispan:1.2" default-cache-container="hibernate">
<cache-container name="hibernate" default-cache="local-query">
<local-cache name="entity">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</local-cache>
</cache-container>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
<subsystem xmlns="urn:jboss:domain:jca:1.1">
<archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
<bean-validation enabled="true"/>
<default-workmanager>
<short-running-threads>
<core-threads count="50"/>
<queue-length count="50"/>
<max-threads count="50"/>
<keepalive-time time="10" unit="seconds"/>
</short-running-threads>
<long-running-threads>
<core-threads count="50"/>
<queue-length count="50"/>
<max-threads count="50"/>
<keepalive-time time="10" unit="seconds"/>
</long-running-threads>
</default-workmanager>
<cached-connection-manager/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
<subsystem xmlns="urn:jboss:domain:jmx:1.1">
<show-model value="true"/>
<remoting-connector/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jpa:1.0">
<jpa default-datasource=""/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:mail:1.0">
<mail-session jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
</subsystem>
<subsystem xmlns="urn:jboss:domain:naming:1.1"/>
<subsystem xmlns="urn:jboss:domain:osgi:1.2" activation="lazy">
<properties>
<property name="org.osgi.framework.startlevel.beginning">
1
</property>
</properties>
<capabilities>
<capability name="javax.servlet.api:v25"/>
<capability name="javax.transaction.api"/>
<capability name="org.apache.felix.log" startlevel="1"/>
<capability name="org.jboss.osgi.logging" startlevel="1"/>
<capability name="org.apache.felix.configadmin" startlevel="1"/>
<capability name="org.jboss.as.osgi.configadmin" startlevel="1"/>
</capabilities>
</subsystem>
<subsystem xmlns="urn:jboss:domain:pojo:1.0"/>
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:resource-adapters:1.0"/>
<subsystem xmlns="urn:jboss:domain:sar:1.0"/>
<subsystem xmlns="urn:jboss:domain:security:1.1">
<security-domains>
<security-domain name="other" cache-type="default">
<authentication>
<login-module code="Remoting" flag="optional">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="RealmUsersRoles" flag="required">
<module-option name="usersProperties" value="${jboss.server.config.dir}/application-users.properties"/>
<module-option name="rolesProperties" value="${jboss.server.config.dir}/application-roles.properties"/>
<module-option name="realm" value="ApplicationRealm"/>
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
</authentication>
</security-domain>
<security-domain name="jboss-web-policy" cache-type="default">
<authorization>
<policy-module code="Delegating" flag="required"/>
</authorization>
</security-domain>
<security-domain name="jboss-ejb-policy" cache-type="default">
<authorization>
<policy-module code="Delegating" flag="required"/>
</authorization>
</security-domain>
<security-domain name="RequireCertificateDomain">
<authentication>
<login-module code="CertificateRoles" flag="required">
<module-option name="securityDomain" value="RequireCertificateDomain"/>
<module-option name="verifier" value="org.jboss.security.auth.certs.AnyCertVerifier"/>
<module-option name="usersProperties" value="file:/home/jboss-as-7.1.1.Final/standalone/configuration/my-users.properties"/>
<module-option name="rolesProperties" value="file:/home/jboss-as-7.1.1.Final/standalone/configuration/my-roles.properties"/>
</login-module>
</authentication>
<jsse keystore-password="changeit" keystore-url="file:localhost.jks" truststore-password="changeit" truststore-url="file:truststore.jks"/>
</security-domain>
</security-domains>
</subsystem>
<subsystem xmlns="urn:jboss:domain:threads:1.1"/>
<subsystem xmlns="urn:jboss:domain:transactions:1.1">
<core-environment>
<process-id>
<uuid/>
</process-id>
</core-environment>
<recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
<coordinator-environment default-timeout="300"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https">
<ssl name="ssl" key-alias="localhost" password="changethis" certificate-key-file="../standalone/configuration/localhost.jks" verify-client="true" ca-certificate-file="../standalone/configuration/cacerts.jks" truststore-type="JKS"/>
</connector>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
</subsystem>
<subsystem xmlns="urn:jboss:domain:webservices:1.1">
<modify-wsdl-address>true</modify-wsdl-address>
<wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
<endpoint-config name="Standard-Endpoint-Config"/>
<endpoint-config name="Recording-Endpoint-Config">
<pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
<handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
</pre-handler-chain>
</endpoint-config>
</subsystem>
<subsystem xmlns="urn:jboss:domain:weld:1.0"/>
</profile>
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
<interface name="unsecure">
<inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="management-native" interface="management" port="${jboss.management.native.port:9999}"/>
<socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
<socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9443}"/>
<socket-binding name="ajp" port="8009"/>
<socket-binding name="http" port="8080"/>
<socket-binding name="https" port="8443"/>
<socket-binding name="osgi-http" interface="management" port="8090"/>
<socket-binding name="remoting" port="4447"/>
<socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="mail-smtp">
<remote-destination host="localhost" port="25"/>
</outbound-socket-binding>
</socket-binding-group>
</server>
@lorenmcguire
Copy link

That's all fine, but what certificate - from the client side - is actually being sent and where does that certificate need to be for JBoss to understand it is a valid certificate? I have this in place, but the client connection states:

Secure Connection Failed

An error occurred during a connection to app1:8443. SSL peer cannot verify your certificate. (Error code: ssl_error_bad_cert_alert)

I have put the client certificate - issued by an Active Directory Certificate Service - in every cacerts file for java on the JBoss server. Is there a way to have JBoss actually check the certificate against the Active Directory Certificate Service?

@lorenmcguire
Copy link

In you're creation of the certificate, you reference the "-keystore localhost.jks" so the keystore location would be the "localhost.jks". In your import of the Client Certificate, you reference "-keystore cacerts.jks" which would indicate the "cacerts.jks" as your keystore file. In your JBoss https line you indicate the following:
certificate-key-file="../standalone/configuration/localhost.jks" verify-client="true" ca-certificate-file="../standalone/configuration/cacerts.jks" truststore-type="JKS"

This would indicate to me the verify-client operation would actually operate on a different certificate keystore file name "cacerts.jks" in the ../standalone/configuration directory.

Is this a correct interpretation or did I miss something here?

Copy link

ghost commented May 16, 2016

lorenmcguire: You are correct in your assumption. I recommend reviewing the documentation on this topic for jboss. The use of "ca-certificate-file" in the configuration element tells jboss to use that file path as the "truststore" when checking certificates. Without this configuration artifact, the generic JDK/JRE installed truststore would be utilized. (i.e. /etc/.../cacerts.jks). Also, do you have the ca-chain cert in your truststore? (I know this is nearly a year old, but I figured I would post it anyway.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment