JBoss AS7 Securing Passwords

Version 19

    This article will describe the capabilities available in JBoss AS7.1 with regard to securing sensitive attributes such as passwords.

     

    Disclaimer:

     

    The default implementation described in this article only solves the problem of masking clear text passwords. There is always a weak link (in this case, the keystore password).

     

     

    For windows platform, refer to https://community.jboss.org/wiki/AS7PasswordVaultOnWindows

     

     

    What is needed?

    1. Java KeyStore.

    2. Scripts provided in the bin directory of JBoss AS 7 .1 (vault.sh etc)

     

    Process

    Step 1:  Create a Java KeyStore

     

    $ keytool -genkey -alias vault -keyalg RSA -keysize 1024  -keystore vault.keystore
    Enter keystore password: vault22 
    Re-enter new password:vault22 
    What is your first and last name?
      [Unknown]:  Picketbox vault
    What is the name of your organizational unit?
      [Unknown]:  picketbox
    What is the name of your organization?
      [Unknown]:  JBoss
    What is the name of your City or Locality?
      [Unknown]:  chicago
    What is the name of your State or Province?
      [Unknown]:  il
    What is the two-letter country code for this unit?
      [Unknown]:  us
    Is CN=Picketbox vault, OU=picketbox, O=JBoss, L=chicago, ST=il, C=us correct?
      [no]:  yes
    
    Enter key password for <vault>
            (RETURN if same as keystore password):  
    
    

     

    It is important to keep track of the keystore password and the alias.  In this example, the keystore password is "vault22" and the alias is "vault".

     

    If one preferes just one command here is equivalent:

     

    keytool -genkey -alias vault -keystore vault.keystore -keyalg RSA -keysize 1024 -storepass vault22 -keypass vault22 -dname "CN=Picketbox vault,OU=picketbox,O=JBoss,L=chicago,ST=il,C=us"
    

     

    Step 2: Use the Vault Tool scripts to store a password in the vault

     

    /bin/util$ ./vault.sh 
    =========================================================================
    
      JBoss Vault
    
      JBOSS_HOME: /home/anil/as7/jboss-as/build/target/jboss-as-7.1.0.Alpha2-SNAPSHOT
    
      JAVA: /opt/java/jdk1.6.0_23/bin/java
    
      VAULT Classpath: /home/anil/as7/jboss-as/build/target/jboss-as-7.1.0.Alpha2-SNAPSHOT/modules/org/picketbox/main/*:/home/anil/as7/jboss-as/build/target/jboss-as-7.1.0.Alpha2-SNAPSHOT/modules/org/jboss/logging/main/*:/home/anil/as7/jboss-as/build/target/jboss-as-7.1.0.Alpha2-SNAPSHOT/modules/org/jboss/common-core/main/*:/home/anil/as7/jboss-as/build/target/jboss-as-7.1.0.Alpha2-SNAPSHOT/modules/org/jboss/as/security/main/*
    =========================================================================
    
    **********************************
    ****  JBoss Vault ********
    **********************************
    Please enter a Digit::   0: Start Interactive Session  1: Remove Interactive Session  2: Exit
    0
    Starting an interactive session
    Enter directory to store encrypted files (end with either / or \ based on Unix or Windows:/home/anil/vault/
    Enter Keystore URL:/home/anil/vault/vault.keystore
    Enter Keystore password: 
    Enter Keystore password again: 
    Values match
    Enter 8 character salt:12345678
    Enter iteration count as a number (Eg: 44):50
    
    Please make note of the following:
    ********************************************
    Masked Password:MASK-5WNXs8oEbrs
    salt:12345678
    Iteration Count:50
    ********************************************
    
    Enter Keystore Alias:vault
    Sep 28, 2011 11:48:39 AM org.jboss.security.vault.SecurityVaultFactory get
    INFO: Getting Security Vault with implementation of org.picketbox.plugins.vault.PicketBoxSecurityVault
    Obtained Vault
    Intializing Vault
    Vault is initialized and ready for use
    Handshake with Vault complete
    Please enter a Digit::   0: Store a password  1: Check whether password exists  2: Exit
    0
    Task:  Store a password
    Please enter attribute value: 
    Please enter attribute value again: 
    Values match
    Enter Vault Block:ds_ExampleDS
    Enter Attribute Name:password
    Attribute Value for (ds_ExampleDS, password) saved
    
    Please make note of the following:
    ********************************************
    Vault Block:ds_ExampleDS
    Attribute Name:password
    Shared Key:N2NhZDYzOTMtNWE0OS00ZGQ0LWE4MmEtMWNlMDMyNDdmNmI2TElORV9CUkVBS3ZhdWx0
    Configuration should be done as follows:
    VAULT::ds_ExampleDS::password::N2NhZDYzOTMtNWE0OS00ZGQ0LWE4MmEtMWNlMDMyNDdmNmI2TElORV9CUkVBS3ZhdWx0
    ********************************************
    
    Please enter a Digit::   0: Store a password  1: Check whether password exists  2: Exit
    2
    

     

    Scriptable (non-interactive) command to create vault (available from AS 7.2 on):

     

    ./vault.sh -k vault.keystore -p vault22 -e /home/anil/vault -i 50 -s 12345678 -v vault -b ds_ExampleDS -a password -x sa
    

     

    for more information use ./vault.sh --help

    Step 3:   Configure the attributes in your xml such as standalone.xml and host.xml

    <server xmlns="urn:jboss:domain:1.1">
    
      <extensions>
         ...
      </extensions>
      <vault>
          <vault-option name="KEYSTORE_URL" value="/home/anil/vault/vault.keystore"/>
          <vault-option name="KEYSTORE_PASSWORD" value="MASK-3y28rCZlcKR"/>
          <vault-option name="KEYSTORE_ALIAS" value="vault"/>
          <vault-option name="SALT" value="12438567"/>
          <vault-option name="ITERATION_COUNT" value="50"/>
          <vault-option name="ENC_FILE_DIR" value="${user.home}/vault/"/>
        </vault>
       ...
      <subsystem xmlns="urn:jboss:domain:datasources:1.0">
                <datasources>
                    <datasource jndi-name="java:jboss/datasources/ExampleDS" enabled="true" use-java-context="true" pool-name="H2DS">
                        <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
                        <driver>h2</driver>
                        <pool></pool>
                        <security>
                            <user-name>sa</user-name>
                            <password>${VAULT::ds_ExampleDS::password::N2NhZDYzOTMtNWE0OS00ZGQ0LWE4MmEtMWNlMDMyNDdmNmI2TElORV9CUkVBS3ZhdWx0}</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>
    
    

     

     

    Note previously, the datasource password would have been:

     

     <security>
         <user-name>sa</user-name>
        <password>sa</password>
    </security>
    

     

    Guidance for subsystems seeking passwords in AS7

     

    The server module in JBoss AS7 workspace has a class called as VaultUtil which has methods for you to seamlessly pass the vault formatted string to get the password from the vault.

     

     

    I am posting the integration done in org.jboss.as.connector.subsystems.datasources.AbstractDataSourceService

    Note that do not seek the password from the vault during the xml parsing phase because the vault has not been initialized and ready. It has to be done in the services phase when you actually do something with the configured elements of your subsystem.

     

    In the case of JCA datasource integration, we do it in AbstractDataSourceService

     

    import org.jboss.as.server.services.security.VaultUtil;
    import org.jboss.security.vault.SecurityVaultException;
    
    final DsSecurity security = dataSourceConfig.getSecurity();
                if (security != null) {
                    if (security.getUserName() != null) {
                        managedConnectionFactory.setUserName(security.getUserName());
                    }
                    if (security.getPassword() != null) {
                        String password = security.getPassword();
                        if (VaultUtil.isVaultFormat(password)) {
                            try {
                                password = VaultUtil.getValueAsString(password);
                            } catch (SecurityVaultException e) {
                                throw new RuntimeException(e); // TODO: use bundle from IJ
                            }
                        }
                        managedConnectionFactory.setPassword(password);
                    }
                }
    
    

     

    We do not want to make the configuration of the vault formatted string to be very difficult. As long as the formatted string is prefixed with VAULT::,  the vault will be invoked.  Custom implementations of the vault should consider the last token for any configuration.

     

    If you are using the AttributeDefinition classes the vaulted expression will be automatically resolved when calling AttributeDefiniton.resolveModelAttribute(). If you are not using AttributeDefinition you need to call OperationContext.resolveExpression() yourself as this example from DataSourceModelNodeUtil

     

    ...

            final String password = getResolvedStringIfSetOrGetDefault(operationContext, dataSourceNode, PASSWORD, null);

    ...

     

        private static String getResolvedStringIfSetOrGetDefault(final OperationContext context, final ModelNode dataSourceNode, final SimpleAttributeDefinition key, final String defaultValue) {

            if (dataSourceNode.hasDefined(key.getName())) {

                return context.resolveExpressions(dataSourceNode.get(key.getName())).asString();

            } else {

                return defaultValue;

            }

        }

     

     

     

    Frequently Asked Questions:

    • How secure is this?
      • The default implementation of the vault utlizes a Java KeyStore. Its configuration uses Password Based Encryption, which is security by obscurity.  This is not 100% security. It only gets away from the problem of clear text passwords in configuration files.  There is always a weak link. (As mentallurg suggests in the comments, the keystore password is the weakest link).
      • Ideally, 3rd party ISV robust implementations of Vaults should provide the necessary security.
    • Can I really secure the keystore?
      • You can store the keystore on an USB or an encrypted secure usb or such.

      • When the server starts, insert the USB. On successful start, you can remove the USB.

      • Ideally, use a FIPS 140-2 certified keystore from a keystore vendor if you want foolproof security.
    • How do I get foolproof security for passwords?
      • The default implementation of Vault in JBossAS7 is not 100% secure.
      • You can increase level of security by adopting a FIPS 140-2 certified keystore.
      • You can use 3rd party implementations of the Vault (this is something we are pushing for ISVs to do).
    • I lost the vault formatted string for my attribute?
      • Just reinsert the attribute value in the vault to overrwrite what was previously stored. You will get a new formatted string to insert in the xml.

    • Can I do all this from the UI?
      • Hopefully with time, we can get this integrated into the console.