Wednesday, August 26, 2015

Posting to HTTP listener with Firefox poster vs html form submit

I have a simple Mule application listens for http on port 8088. When I use Firefox poster to post up data, it sends in pure payload (in this case text/xml). And the application is happy to process the data.

Naturally I was thinking why go through Firefox poster each time, so I created a simple html file with a form post, something like

<form method="post" action="myserver:8088/mypath">
  enter data below
  <textarea cols=20 row=20>
  </textarea>
  <input type='submit'>
</form>

I ran into several issues, and decided to give up. I may come back later to see there is an actual work around. For now, this post just reminds what NOT to do. Because I have already attempted this twice in 6 weeks. Need to remind myself stopping making the same mistake.

Issue 1: as it appears above, <textarea> has no name, so I don't know what got posted up to the server, Mule application picked up a "null" payload. I believe it posted something, i just didn't spend time to track it. Maybe I'll track it some other day.

Issue 2: I added <textarea name="foo"...>
Now the application picked up the payload, except the payload is "foo=<xml....>", I need the payload to be pure xml like "<xml ...>" so no go :(

Issue 3: I tried to give it a name with just a space like <textarea name=' '...>, didn't go very far either, the payload shows up as " =<xml ...>".

couple other things I looked into:

apparently, firefox poster posts the content up as "content-type=text/xml", but I don't seem to have control over that with HTML form. "enctype" only has 3 options, the closest is "text/plain", no cigar here.

Until I have too much time on my hand to tinker around it, I'm staying with Firefox poster for now.


Wednesday, August 19, 2015

Encyrpt Mule Properties with Jasypt with Complete Sample Code

Mule ESB uses Java properties file to set the dynamic properties for application. We all know we need to encrypt passwords in the property files. I know two ways to encrypt properties with Mule ESB.

One is to use Mule Enterprise Security module
https://developer.mulesoft.com/docs/display/current/Installing+Anypoint+Enterprise+Security I have posted step by step instructions here: http://blogs.perficient.com/integrate/2016/05/16/mule-enterprise-security-password-encryption-steps/

The other one is Jasypt
This post will follow the above blog and show an end to end example of Jasypt with full sample code.  I’ll cover the other method in a different post.

Let’s get started.

Step 1. Create a Hello World Application
   <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
    <flow name="encryptFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/enc" doc:name="HTTP"/>
       <expression-filter expression="#[message.inboundProperties.'http.request.uri' != '/favicon.ico']" doc:name="Filter favicon" />
        <set-payload value="Hello World" doc:name="Set Payload"/>
        <logger message="#[payload] " level="INFO" doc:name="Logger"/>
</flow>

Do a quick test to make yourself feel good.

Step 2. Mavenize the project
Right click on the project name, move to “Maven support in studio”, then select “Mavenize”
This will create a pom.xml for you.
I would like to point out, if you are not happy at any point with your Maven pom.xml, you can chose to delete pom.xml (backup if needed), and then re-run the above step to Mavenize it again.

Step 3. Add a property file to the project
The default property file is my-app.properties. But you should create your own under "src/main/resources". Let’s create “enc.properties” over there.
p1=hello
p2=world
p3=welcome1
p4=foo
Let’s change the flow
        <set-payload value="Here are the parameters p1=${p1} p2=${p2} p3=${p3} p4=${p4}" doc:name="Set Payload"/>

If you test the program, it may not pick up those properties. If that’s the case, add this line right above the flow

<context:property-placeholder location="enc.properties" />

Test it again, you should see “Here are the parameters p1=hello p2=world p3=welcome1 p4=foo”. If not, try to re-generate the pom.xml again. Hope that solves your problem.

Step 4.  Add Jasypt dependency to pom
             <dependency>
               <groupId>org.jasypt</groupId>
               <artifactId>jasypt-spring3</artifactId>
               <version>1.9.1</version>
             </dependency>

Step 5. Add the spring bean section from this post http://blogs.mulesoft.com/dev/mule-dev/encrypting-passwords-in-mule/
   <spring:beans>
        <spring:bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
            <spring:property name="algorithm" value="PBEWithMD5AndDES"/>
<!--             <spring:property name="passwordEnvName" value="MULE_ENCRYPTION_PASSWORD"/> -->
            <spring:property name="password" value="mypass"/>
        </spring:bean>
        <spring:bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
            <spring:property name="config" ref="environmentVariablesConfiguration"/>
        </spring:bean>
        <spring:bean id="propertyConfigurer" class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
            <spring:constructor-arg ref="configurationEncryptor"/>
            <spring:property name="locations">
                <spring:list>
                    <spring:value>enc.properties</spring:value>
                </spring:list>
            </spring:property>
        </spring:bean>
    </spring:beans>

<!--    <context:property-placeholder location="enc.properties" /> -->

Please note 1) I commented out the above “property-placeholder” line. Spring bean we are adding should be sufficient to make the applicaiton include the property file. 2) I have put enc.properties in the “locations” section. 3) I commented out “passwordEnvName”, and added “password” property. I’ll explain 3) later.

If the compiler whines, you may consider re-generating the pom again, remember to put Jasypt dependency back in if you ended up regenerating the POM file.

If everything works, your application should work exactly like before. If not, then you may need to 
stop the application if you are running inside the studio, and re-run it again. Sometimes, the property file change is not picked up properly without restarting the application.

Step 6. Encrypt the Parameters
In command window, run this (you need to pick your own path to the “jasypt” jar file):

java -cp C:\m2\repository\org\jasypt\jasypt\1.9.1\jasypt-1.9.1.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="hello" password="mypass" algorithm=PBEWithMD5AndDES

Run the same command for “world”, “welcome1”.

You should have 3 encrypted string for “hello”, “world”, “welcome1” . Put them in the property file like below, the encrypted strings are inside ENC():
p1=ENC(jDkJK7Ns+OJCRXAZ+7kcUA==)
p2=ENC(eMgHrLD5bPQrVEhu4yOaZw==)
p3=ENC(ennXknKsiEUhAO1a4rpuMXonJ94Nooa1)
p4=foo

Now re-run the program again, you should get the same result. This illustrates that the encryption/decryption is working properly.

Step 7. Wrap it up (using environment variable to keep your master password)

I have copied the final finished source code at the end.
A few notes here:
1    In the previous step, I used “password” property to test the encryption/decryption without using the environment variable
2     In the final code, I have removed (commented out) the “password” property and put back in “passwordEnvName” property, in this case, it is called “MULE_ENCRYPTION_PASSWORD”. This is telling you that you need to setup an environment variable “MULE_ENCRYPTION_PASSWORD” with the value “mypass”.
3      After you setup environment variable, you may need to restart the studio, so it can pick up the environment variable (if you are running standalone Mule ESB, you may need to close that command window and start a new command window, then restart Mule ESB)

Is it safe to use the env varialbe to keep the password? Well, password need be specified by the admin, it has to be somewhere. As explained in the other posts, you can setenv right before you start the server,then unset the env varialbe right after the server is started.

That should be it!

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:context="http://www.springframework.org/schema/context"
       xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
       xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.7.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">

   <spring:beans>
        <spring:bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
            <spring:property name="algorithm" value="PBEWithMD5AndDES"/>
            <spring:property name="passwordEnvName" value="MULE_ENCRYPTION_PASSWORD"/>
<!--             <spring:property name="password" value="mypass"/>  -->
        </spring:bean>
        <spring:bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
            <spring:property name="config" ref="environmentVariablesConfiguration"/>
        </spring:bean>
        <spring:bean id="propertyConfigurer" class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
            <spring:constructor-arg ref="configurationEncryptor"/>
            <spring:property name="locations">
                <spring:list>
                    <spring:value>enc.properties</spring:value>
                </spring:list>
            </spring:property>
        </spring:bean>
    </spring:beans>

<!--    <context:property-placeholder location="enc.properties" /> -->

    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
    <flow name="encryptFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/enc" doc:name="HTTP"/>
       <expression-filter expression="#[message.inboundProperties.'http.request.uri' != '/favicon.ico']" doc:name="Filter favicon" />
        <set-payload value="Here are the parameters p1=${p1} p2=${p2} p3=${p3} p4=${p4}" doc:name="Set Payload"/>
        <logger message="#[payload] " level="INFO" doc:name="Logger"/>
    </flow>
</mule>

For the sake of completeness, I am including the pom.xml as well, which really doesn’t have anything special:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

       <modelVersion>4.0.0</modelVersion>
       <groupId>com.mycompany</groupId>
       <artifactId>encrypt</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>mule</packaging>
       <name>Mule encrypt Application</name>

    <properties>
             <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
             <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

             <mule.version>3.7.0</mule.version>
       <mule.tools.version>1.1</mule.tools.version>
       </properties>

       <build>
             <plugins>
                    <plugin>
                           <groupId>org.mule.tools.maven</groupId>
                           <artifactId>mule-app-maven-plugin</artifactId>
                           <version>${mule.tools.version}</version>
                           <extensions>true</extensions>
                           <configuration>
                    <copyToAppsDirectory>true</copyToAppsDirectory>
                           </configuration>
                    </plugin>
                    <plugin>
                           <artifactId>maven-assembly-plugin</artifactId>
                           <version>2.2.1</version>
                           <configuration>
                                 <descriptorRefs>
                                        <descriptorRef>project</descriptorRef>
                                 </descriptorRefs>
                           </configuration>
                    </plugin>
                    <plugin>
                           <groupId>org.codehaus.mojo</groupId>
                           <artifactId>build-helper-maven-plugin</artifactId>
                           <version>1.7</version>
                           <executions>
                                 <execution>
                                        <id>add-resource</id>
                                        <phase>generate-resources</phase>
                                        <goals>
                                               <goal>add-resource</goal>
                                        </goals>
                                        <configuration>
                                               <resources>
                                                     <resource>
                                                            <directory>src/main/app/</directory>
                                                     </resource>
                                                     <resource>
                                                            <directory>mappings/</directory>
                                                     </resource>
                                               </resources>
                                        </configuration>
                                 </execution>
                           </executions>
                    </plugin>
             </plugins>
       </build>

       <!-- Mule Dependencies -->
       <dependencies>
             <dependency>
               <groupId>org.jasypt</groupId>
               <artifactId>jasypt-spring3</artifactId>
               <version>1.9.1</version>
             </dependency>
      
             <!-- Xml configuration -->
             <dependency>
             <groupId>com.mulesoft.muleesb</groupId>
                    <artifactId>mule-core-ee</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <!-- Xml configuration -->
             <dependency>
                    <groupId>com.mulesoft.muleesb.modules</groupId>
                    <artifactId>mule-module-spring-config-ee</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <!-- Mule Transports -->
             <dependency>
                    <groupId>org.mule.transports</groupId>
                    <artifactId>mule-transport-file</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <dependency>
                    <groupId>org.mule.transports</groupId>
                    <artifactId>mule-transport-http</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <dependency>
             <groupId>com.mulesoft.muleesb.transports</groupId>
                    <artifactId>mule-transport-jdbc-ee</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <dependency>
             <groupId>com.mulesoft.muleesb.transports</groupId>
                    <artifactId>mule-transport-jms-ee</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <dependency>
                    <groupId>org.mule.transports</groupId>
                    <artifactId>mule-transport-vm</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <!-- Mule Modules -->
             <dependency>
                    <groupId>org.mule.modules</groupId>
                    <artifactId>mule-module-scripting</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <dependency>
                    <groupId>org.mule.modules</groupId>
                    <artifactId>mule-module-xml</artifactId>
                    <version>${mule.version}</version>
                    <scope>provided</scope>
             </dependency>
             <!-- for testing -->
             <dependency>
                    <groupId>org.mule.tests</groupId>
                    <artifactId>mule-tests-functional</artifactId>
                    <version>${mule.version}</version>
                    <scope>test</scope>
             </dependency>
       </dependencies>

       <repositories>
          <repository>
            <id>Central</id>
            <name>Central</name>
            <url>http://repo1.maven.org/maven2/</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-releases</id>
            <name>MuleSoft Releases Repository</name>
            <url>http://repository.mulesoft.org/releases/</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-snapshots</id>
            <name>MuleSoft Snapshots Repository</name>
            <url>http://repository.mulesoft.org/snapshots/</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>http://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>