Version 12

    BaseCertLoginModule

     

    This is a login module which authenticates users based on X509Certificates. A typical usecase for this login module is CLIENT-CERT authentication in the web tier (See ModJKBaseCertLoginModule if you use Apache httpd and mod_jk). This login module only performs authentication. You need to combine it with another login module capable of acquiring the authorization roles to completely define access to a secured web or ejb component. Two subclasses of this login module, CertRolesLoginModule and DatabaseCertLoginModule extend the behavior to obtain the authorization roles from either a properties file or database.

     

    The supported login module configuration options include the following:

    • securityDomain - the name of the SecurityDomain to obtain the trust and keystore from.

    • verifier (4.0.2+) - the class name of the org.jboss.security.auth.certs.X509CertificateVerifier to use for verification of the login certificate

     

    The BaseCertLoginModule needs a KeyStore to perform user validation. This is obtained through a org.jboss.security.SecurityDomain implementation. Typically, the SecurityDomain implementation is configured using the org.jboss.security.plugins.JaasSecurityDomain MBean as shown in this jboss-service.xml configuration fragment:

     

       <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
          name="jboss.security:service=SecurityDomain">
          <constructor>
             <arg type="java.lang.String" value="jmx-console"></arg>
          </constructor>
          <attribute name="KeyStoreURL">resource:localhost.keystore</attribute>
          <attribute name="KeyStorePass">unit-tests-server</attribute>
          <depends>jboss.security:service=JaasSecurityManager</depends>
       </mbean>
    

     

    This creates a security domain with the name "jmx-console" whose SecurityDomain implementation is available via JNDI under the name "java:/jaas/jmx-console" following the JBossSX security domain naming pattern. The JaasSecurityDomain depends on the JaasSecurityManager to be loaded first (which is ensured by the

    <depends>

    element) because the JaasSecurityManager sets a cache policy for the security domain. To secure a web application such as the jmx-console.war using client certs and role based authorization, one would first modify the web.xml and jboss-web.xml to specify what resources are secured, along with the allowed roles and security domain to be used for authentication and authorization as shown here:

     

    jmx-console.war/WEB-INF/web.xml:

    <?xml version="1.0"?>
    <!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
       "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
    ...
       <security-constraint>
         <web-resource-collection>
           <web-resource-name>HtmlAdaptor</web-resource-name>
           <description>An example security config that only allows users with the
             role JBossAdmin to access the HTML JMX console web application
           </description>
           <url-pattern>/*</url-pattern>
           <http-method>GET</http-method>
           <http-method>POST</http-method>
         </web-resource-collection>
         <auth-constraint>
           <role-name>JBossAdmin</role-name>
         </auth-constraint>
       </security-constraint>
    
       <login-config>
          <auth-method>CLIENT-CERT</auth-method>
          <realm-name>JBoss JMX Console</realm-name>
       </login-config>
    
       <security-role>
          <role-name>JBossAdmin</role-name>
       </security-role>
    </web-app>
    

    jmx-console.war/WEB-INF/jboss-web.xml:

    <jboss-web>
       <security-domain>java:/jaas/jmx-console</security-domain>
    </jboss-web>
    

     

    Next, you need to define the login module configuration for the jmx-console security domain.

    This can be done using the following conf/login-config.xml fragment:

     <application-policy name = "jmx-console">
        <authentication>
           <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule"
              flag = "required">
              <module-option name="password-stacking">useFirstPass</module-option>
              <module-option name="securityDomain">java:/jaas/jmx-console</module-option>
           </login-module>
           <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
              flag = "required">
              <module-option name="password-stacking">useFirstPass</module-option>
              <module-option name="usersProperties">jmx-console-users.properties</module-option>
              <module-option name="rolesProperties">jmx-console-roles.properties</module-option>
           </login-module>
        </authentication>
     </application-policy>
    

     

    Here the BaseCertLoginModule is used for authentication of the client cert, and the UsersRolesLoginModule is only used for authorization due to the password-stacking=useFirstPass option. Both the localhost.keystore and the jmx-console-roles.properties need an entry that maps to the principal associated with the client cert. By default, the principal is created using the client cert common name. If the following client cert was to be used:

    [starksm@banshee9100 conf]$ keytool -printcert -file unit-tests-client.export
    Owner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US
    Issuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, EMAILADDRESS=admin
    @jboss.com, OU=QA, O=JBoss Inc.
    Serial number: 100103
    Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005
    Certificate fingerprints:
             MD5:  4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:AB
             SHA1: DE:DE:86:59:05:6C:00:E8:CC:C0:16:D3:C2:68:BF:95:B8:83:E9:58
    

     

    The localhost.keystore would need this cert stored with an alias of 'CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US' and the jmx-console-roles.properties would also need the same entry. This has to be handled specially since the CN contains many characters that are normally treated as delimiters. You can escape these using the '\' as shown here:

     

    # A sample roles.properties file for use with the UsersRolesLoginModule
    CN\=unit-tests-client,\ OU\=JBoss\ Inc.,\ O\=JBoss\ Inc.,\ ST\=Washington,\ C\=US=JBossAdmin
    admin=JBossAdmin
    

     

    Verification is performed by obtaining the certificate from the securityDomain keystore based on the alias passed to the login module via the NameCallback and testing the keystore cert against the cert obtained via the ObjectCallback. If you want to customize the verification you can provide an implementation of the org.jboss.security.auth.certs.X509CertificateVerifier interface:

     

    /*
     * JBoss, Home of Professional Open Source
     *
     * Distributable under LGPL license.
     * See terms of license at gnu.org.
     */
    package org.jboss.security.auth.certs;
    
    import java.security.cert.X509Certificate;
    import java.security.KeyStore;
    
    /**
     * A verifier for X509Certificate used by authentication layers.
     * 
     * @see org.jboss.security.auth.spi.BaseCertLoginModule
     * 
     * @author Scott.Stark@jboss.org
     * @version $Revision: 1.1 $
     */
    public interface X509CertificateVerifier
    {
       /**
        * Validate a cert.
        * 
        * @param cert - the X509Certificate to verifier
        * @param alias - the expected keystore alias
        * @param keyStore - the keystore for the cert
        * @param trustStore - the truststore for the cert signer
        * @return true if the cert is valid, false otherwise
        */ 
       public boolean verify(X509Certificate cert, String alias,
          KeyStore keyStore, KeyStore trustStore);
    }
    

     

    One implementation of X509Certificate is org.jboss.security.auth.certs.AnyCertVerifier which would accept any cert accepted by the transport layer in the case of CLIENT-CERT auth. An example usage would be:

     

     <application-policy name = "jmx-console">
        <authentication>
           <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule"
              flag = "required">
              <module-option name="password-stacking">useFirstPass</module-option>
              <module-option name="securityDomain">java:/jaas/jmx-console</module-option>
              <module-option name="verifier">org.jboss.security.auth.certs.AnyCertVerifier</module-option>
           </login-module>
        </authentication>
     </application-policy>