Security Features of JBoss AS 5.1 - Part 2 - Masking Passwords in the configuration files

Nobody likes the idea of seeing passwords in the open in an xml file.  In JBoss AS, we have various mechanisms by which passwords can be masked in the xml file. This article will act as a single stop reference to the various mechanisms.

In order to mask password attributes in the JBoss Microcontainer Bean definitions, see the following prototype

 https://jira.jboss.org/jira/browse/JBAS-6710

... which works for JBoss AS 5.1 onwards

 Steps to perform

First you need to create a keystore and generate a key (See additional information below for example).

You can use the command in the bin directory.                                              

  1. Use the Password Tool (mentioned below).
  2. Configure the @Password annotation on the MC beans that you are interested in masking the password. Example is provided below.

 

Password Tool

There is a command line tool that can be used for centralized password management.  The script is located in the bin directory. Remember that you can use the tool in the bin directory and the server configurations (default, all etc) can make use of the files that are generated by this tool.

=============================================

anil@localhost:~/jboss-6.0/jboss-head/build/output/jboss-6.0.0.Alpha1/bin$ ./password_tool.sh
**********************************
**** JBoss Password Tool********
**********************************
Error while trying to load data:Encrypted password file not located
Maybe it does not exist and need to be created.
0: Encrypt Keystore Password 1:Specify KeyStore 2:Create Password
3: Remove a domain 4:Enquire Domain 5:Exit

0
Enter Keystore password
testpass
Enter Salt (String should be at least 8 characters)
AnyStringThatIsLong
Enter Iterator Count (integer value)
111
Keystore Password encrypted into password/jboss_keystore_pass.dat



Loading domains [
]
0: Encrypt Keystore Password 1:Specify KeyStore 2:Create Password 3: Remove a domain
4:Enquire Domain 5:Exit
2
Enter security domain:
messaging
Enter passwd:
myPass
0: Encrypt Keystore Password 1:Specify KeyStore 2:Create Password
3: Remove a domain 4:Enquire Domain 5:Exit
5
org.jboss.security.integration.password.PasswordTool$ShutdownHook run called
Storing domains [
messaging,
]

=====================================================================


 

Configure the MC Beans

You will need to add an annotation to the bean definition.  Lets take the example of JBoss Messaging SecurityStore MC Bean defined in deploy/messaging/messaging-jboss-beans.xml

 

Before your modification:

 <bean name="SecurityStore" 
class="org.jboss.jms.server.jbosssx.JBossASSecurityMetadataStore">
<!-- default security configuration -->
<property name="defaultSecurityConfig">
<![CDATA[
<security>
<role name="guest" read="true" write="true" create="true"/>
</security>
]]>
</property>
<property name="suckerPassword">CHANGE ME!!</property>
<property name="securityDomain">messaging</property>
<property name="securityManagement">
<inject bean="JNDIBasedSecurityManagement"/></property>
</bean>

 

After your modification:

 <bean name="SecurityStore"
class="org.jboss.jms.server.jbosssx.JBossASSecurityMetadataStore">
<!-- default security configuration -->
<property name="defaultSecurityConfig">
<![CDATA[
<security>
<role name="guest" read="true" write="true" create="true"/>
</security>
]]>
</property>
<property name="securityDomain">messaging</property>
<property name="securityManagement">
<inject bean="JNDIBasedSecurityManagement"/></property>
<!-- Password Annotation to inject the password from the common password
utility -->
<annotation>@org.jboss.security.integration.password.Password(securityDomain=messaging,
methodName=setSuckerPassword)</annotation>
</bean>

 

As you can see, you have removed the attribute called as "suckerPassword"   and introduced an MC annotation called as @Password whose configuration includes the security domain as well the MC bean property where the password needs to be injected.

 

 

Additional Information

The keystore can be generated as follows:

$ keytool -genkey -alias jboss -keyalg RSA -keysize 1024  -keystore server.keystore
Enter keystore password: testpass
What is your first and last name?
[Unknown]: JBoss Security
What is the name of your organizational unit?
[Unknown]: JBoss Division
What is the name of your organization?
[Unknown]: Red Hat Inc
What is the name of your City or Locality?
[Unknown]: Raleigh
What is the name of your State or Province?
[Unknown]: NC
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=JBoss Security, OU=JBoss Division, O=Red Hat Inc, L=Raleigh, ST=NC, C=US correct?
[no]: yes

Enter key password for <jboss>
(RETURN if same as keystore password):

 

Other Masking Information

  1. Encrypting Data Source Passwords
  2. Encrypting Keystore Password in Tomcat Connector
  3. Encrypting Ldap Password in the LdapExtLoginModule

 

Background Information

This feature utlizes the Microcontainer lifecycle callbacks.

 JBoss MC Deployment

 

 

The password is set from a common utility into the MC bean during the "create" step.

 

Reference:

  1. http://www.jboss.org/community/wiki/MaskingPasswordsinJBossASXMLConfiguration
  2. http://server.dzone.com/articles/security-auditing-jboss

 

About the Author:

Anil Saldhana is the lead security architect at JBoss. He blogs at http://anil-identity.blogspot.com

Article Type: 
How-to
AttachmentSize
MCDeployment_compressed.png73.09 KB
0
Average: 1 (1 vote)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

SecurityMan replied on Tue, 2009/11/24 - 5:22pm

 

I've checked how password_tool encrypts/decrypts the data and found out that the same hard-coded PBE secret (78aac249a60a13d5e882927928043ebb) is used for encrypting/decrypting (see below).

Please let me know what I'm missing here or what is the point of the whole proposed solution? If my findings are correct, it will just create a false feeling of safety.

From FilePassword.java:

124      static char[] decode(RandomAccessFile passwordFile)
125   throws Exception
126   {
127   byte[] salt = new byte[8];
128   passwordFile.readFully(salt);
129   int count = passwordFile.readInt();
130   ByteArrayOutputStream baos = new ByteArrayOutputStream();
131   int b;
132   while( (b = passwordFile.read()) >= 0 )
133   baos.write(b);
134   passwordFile.close();
135   byte[] secret = baos.toByteArray();
136  
137   PBEParameterSpec cipherSpec = new PBEParameterSpec(salt, count);
138   PBEKeySpec keySpec = new PBEKeySpec("78aac249a60a13d5e882927928043ebb".toCharArray());
139   SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithMD5andDES");
140   SecretKey cipherKey = factory.generateSecret(keySpec);
141   Cipher cipher = Cipher.getInstance("PBEwithMD5andDES");
142   cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherSpec);
143   byte[] decode = cipher.doFinal(secret);
144   return new String(decode, "UTF-8").toCharArray();
145   }
146   static void encode(RandomAccessFile passwordFile, byte[] salt, int count,
147   byte[] secret)
148   throws Exception
149   {
150   PBEParameterSpec cipherSpec = new PBEParameterSpec(salt, count);
151   PBEKeySpec keySpec = new PBEKeySpec("78aac249a60a13d5e882927928043ebb".toCharArray());
152   SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithMD5andDES");
153   SecretKey cipherKey = factory.generateSecret(keySpec);
154   Cipher cipher = Cipher.getInstance("PBEwithMD5andDES");
155   cipher.init(Cipher.ENCRYPT_MODE, cipherKey, cipherSpec);
156   byte[] encode = cipher.doFinal(secret);
157   passwordFile.write(salt);
158   passwordFile.writeInt(count);
159   passwordFile.write(encode);
160   passwordFile.close();
161  
162   }

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.