Using Encrypted Passwords with Mule ESB
Join the DZone community and get the full member experience.
Join For Free
a
good practice
in the
mule esb
is to supply properties by using a property file. most of the time you will end up adding passwords to the properties file. in that case you might want to encrypt the passwords so it is not visible for every one who has access to the property file. mulesoft
described how to do this
in combination with the mule esb. although it is a good starting point i thought it may help to create a complete example so i put all the steps in this post. there are two environments that have to be modified: the development environment and the runtime environment.
the development environment is where you create your mule applications with your
java ide
. you will need to take the following steps:
- add dependencies to your projects pom
in the maven pom file the following dependencies are added:
<dependency> <groupid>org.jasypt</groupid> <artifactid>jasypt-spring3</artifactid> <version>1.9.1</version> <scope>provided</scope> </dependency> <dependency> <groupid>org.jasypt</groupid> <artifactid>jasypt</artifactid> <version>1.9.1</version> <scope>provided</scope> </dependency>
- configure mule to make use of the encrypted properties file
to make the mule esb able using the encrypted properties in the properties file i created a spring config file that is loaded (imported) by the mule configuration of my mule applications. the spring config file ‘my-properties-config.xml’ looks like:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:encryption="http://www.jasypt.org/schema/encryption" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd http://www.jasypt.org/schema/encryption http://www.jasypt.org/schema/encryption/jasypt-spring3-encryption-1.xsd" > <!--password-sys-property-name="mule_encryption_password" --> <encryption:encryptor-config id="econf" password-env-name="mule_encryption_password" algorithm="pbewithmd5anddes"/> <encryption:string-encryptor id="stringenc" config-bean="econf"/> <encryption:encryptable-property-placeholder encryptor="stringenc" location="classpath:my-environment.properties"/> </beans>
- set up your unit test
of course you want to unit test this functionality
this step is divided into three substeps. the first step is to create the unit test class. the one i used is the following:
import org.junit.assert; import org.junit.beforeclass; import org.junit.test; import org.junit.runner.runwith; import org.springframework.test.context.contextconfiguration; import org.springframework.test.context.junit4.springjunit4classrunner; import javax.annotation.resource; import java.lang.reflect.field; import java.util.collections; import java.util.hashmap; import java.util.map; /** * tests the jasypt encryption in a property file. * expects the environment variable 'mule_encryption_password' to be filled * with the correct master password. the setenv method adds this variable to the * env in memory. */ @contextconfiguration(locations = "classpath:test-config.xml") @runwith(springjunit4classrunner.class) public class propertytest { @resource private java.util.map mymap; public void setmymap(map mymap) { this.mymap = mymap; } @test public void mytest() { assert.assertnotnull("mymap should be initialized", mymap); assert.assertequals("the decrypted password should match the expected one", "password", mymap.get("pass1")); } @beforeclass public static void setenv() { map newenv = new hashmap(); newenv.put("mule_encryption_password","mulesoft"); try { class processenvironmentclass = class.forname("java.lang.processenvironment"); field theenvironmentfield = processenvironmentclass.getdeclaredfield("theenvironment"); theenvironmentfield.setaccessible(true); map env = (map) theenvironmentfield.get(null); env.putall(newenv); field thecaseinsensitiveenvironmentfield = processenvironmentclass.getdeclaredfield("thecaseinsensitiveenvironment"); thecaseinsensitiveenvironmentfield.setaccessible(true); map cienv = (map) thecaseinsensitiveenvironmentfield.get(null); cienv.putall(newenv); } catch (nosuchfieldexception e) { try { class[] classes = collections.class.getdeclaredclasses(); map env = system.getenv(); for(class cl : classes) { if("java.util.collections$unmodifiablemap".equals(cl.getname())) { field field = cl.getdeclaredfield("m"); field.setaccessible(true); object obj = field.get(env); map map = (map) obj; map.clear(); map.putall(newenv); } } } catch (exception e2) { e2.printstacktrace(); } } catch (exception e1) { e1.printstacktrace(); } } }the most complex part in this unit test is the code that adds the ‘mule_encryption_password’ variable to the runtime environment. i found this code on the internet and as far as i can tell it works on both windows 7 and linux debian (at least these are the environments where my unit test runs successfully). another option could be to demand that the environment variable is set in every environment that runs the unit test (developers machines and jenkins) but i think sooner or later you will run into the issue the variable is not set.
the java class uses the spring configuration file ‘test-config.xml’ that looks like this:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:spring="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <spring:import resource="classpath:my-properties-config.xml" /> <util:map id="mymap" key-type="java.lang.string" value-type="java.lang.string"> <entry key="key1" value="${property.1}" /> <entry key="key2" value="${property.1}" /> <entry key="pass1" value="${password.1}" /> </util:map> </beans>
the last step is adding the test property file to the unit test. this property file ‘my-environment.properties’ contains the encrypted passwords to test with:
property.1=value1 property.2=value2 password.1=enc(2ekuf20x8zp79yda2d9yo1yhtxnkmxmg)with all this in place the uit tests creates a map with the values of the properties from the property file. the value for ‘password.1′ in the property file is the encrypted value for the string ‘password’ with the master password ‘mulesoft’. in the unit test i get the value and check that it matches the decrypted value.
so that is for the development environment. now the runtime environment. this is where you run your standalone mule esb. you will need to add the necessary jasypt libraries here and use them to generate the encrypted passwords. here are the steps:
- set the environment variable
- add the necessary jars to the mule esb libraries
- generate the encrypted passwords
- put the passwords in the property file
this environment variable will hold the master password that is used to decrypt the encrypted password. please note that this might be another possible security breach.
to set the environment variable automatically at a linux server you can create a script in the ‘/etc/profile.d/’ directory so it is executed when a user logs in like this:
sudo nano /etc/profile.d/mule-env.sh
in the file we put the command to set the environment variable:
export mule_encryption_password=mulesoft
after saving the file load it for the current user:
source /etc/profile
if you don’t like the idea that the master password is set for each user and is saved in a file you might want to try to set the environment variable manually for the user just before you start the mule esb. i am pretty sure there might be better ways to do this but i’m just showing what worked for me.
i put the jasypt jars that corresponds with the dependencies in my project pom file in the directory ‘/opt/mule/lib/shared/default’ where ‘/opt/mule/’ is the installation directory of my standalone mule esb. this way the jasypt libraries are available to all mule applications deployed to this server.
now generate the necessary encrypted passwords with the following command (make sure the password matches the one that is used in the environment variable!):
java -cp jasypt-1.9.1.jar org.jasypt.intf.cli.jasyptpbestringencryptioncli input="xxxx" password=mulesoft algorithm=pbewithmd5anddes
mulesoft/mulesoft gives:
nbb7bpmx93lnmenrrriyjtt8zujz/imh
the output has to be placed in the mule property file of your application as follows:
my.jms.password=enc(zpeoybbmgi/zq7md0qnvo8dm4mjvvjmj)
that’s it. no more readable passwords in your properties file. you could increase the security further by not adding the master password to the environment variables (where it can be accessed by anyone who has access to the environment) but by supplying the master password as a startup parameter when running mule esb.
Published at DZone with permission of $$anonymous$$. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Transactional Outbox Patterns Step by Step With Spring and Kotlin
-
From On-Prem to SaaS
-
Breaking Down the Monolith
-
Cucumber Selenium Tutorial: A Comprehensive Guide With Examples and Best Practices
Comments