Contact Us 1-800-596-4880

Anypoint Enterprise Security Example Application

Mule Runtime Engine versions 3.5, 3.6, and 3.7 reached End of Life on or before January 25, 2020. For more information, contact your Customer Success Manager to determine how you can migrate to the latest Mule version.

Designed as a simple demo, this example application offers some insight into how to use two Anypoint Enterprise Security features: Mule Digital Signature Processor and Mule Message Encryption Processor. The demo illustrates how to complete the following tasks with Mule:

  • Verify a digital signature

  • Encrypt part of a message payload

  • Decrypt a message payload

Prerequisites

This document assumes that you have installed the Anypoint Enterprise Security extensions.

It also assumes you are familiar with the Anypoint Studio interface.

This document describes the details of the example within the context of Anypoint Studio, Mule ESB’s graphical user interface (GUI). Where appropriate, the XML configuration follows the Studio interface screenshot.

Importing the Application

  1. Download the Anypoint Enterprise Security Example Application.

  2. Launch Anypoint Studio.

  3. Under the File menu, select Import…​

  4. Studio opens an Import wizard. Expand the Mule folder in the wizard, then select Anypoint Studio generated Deployable Archive (.zip). Click Next.

    If your operating system automatically unzipped the application, select Anypoint Studio Project from External Location instead of Anypoint Studio generated Deployable Archive (.zip).
  5. Use the ellipsis button (. . .) next to the Zip File field to browse for, then select, the Mule application you downloaded:` anypoint-enterprise-security-example.zip`.

  6. Click Finish. Studio imports, then opens the project.

Setting Up, Then Running the Application

  1. In the anypoint_enterprise_security_example project, scroll down the Studio canvas to the Get_secret_file flow.

  2. Double-click the Groovy component to open its Pattern Properties panel.

  3. In the Script Text field, adjust the filepath of the encrypted.txt file to match your system’s filepath, then click OK to save your change.

  4. Click the Save icon in Studio to save the project.

  5. In the Package Explorer, right-click the project name, then select Run As > Mule Application.

  6. Mule runs the application. In the console, it displays the following message: Started anypoint_enterprise_security_example app

How it Works

The Encrypted Message Producer application consists of three simple flows, each of which acts as a Web service provider which encrypts or decrypts a message before returning a response to the caller. Organized according to function, these flows serve different purposes within the application.

  • Get_CC_information receives Web service requests for a customer’s credit card information, which it retrieves, encrypts, then returns to the caller. (See image below, top.)

  • Decrypt_The_Request decrypts messages it receives, logs the decryption activity, then returns the unencrypted message contents — in this case, credit card information — to the caller. (See image below, middle.)

  • Get_secret_file decrypts, upon request, the contents of a file, then returns a response to the caller that displays the decrypted contents of the file. (See image below, bottom.)

    full+example+flow

View the XML

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:spring="http://www.springframework.org/schema/beans" xmlns:secure-property-placeholder="http://www.mulesoft.org/schema/mule/secure-property-placeholder"
    xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
    xmlns:encryption="http://www.mulesoft.org/schema/mule/encryption"
    xmlns:signature="http://www.mulesoft.org/schema/mule/signature"
    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:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/signature http://www.mulesoft.org/schema/mule/signature/current/mule-signature.xsd
http://www.mulesoft.org/schema/mule/encryption http://www.mulesoft.org/schema/mule/encryption/current/mule-encryption.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/secure-property-placeholder http://www.mulesoft.org/schema/mule/secure-property-placeholder/current/mule-secure-property-placeholder.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd">

    <signature:config name="Signature" enableLanguage="true" doc:name="Signature">
        <signature:jce-signer-config algorithm="HmacMD5" key="JLfl5sER3kt4oVkzP2d39UQrUxrEK63LjmXAO45b6cU=" />
    </signature:config>

    <encryption:config name="plainXml" doc:name="Encryption" enableLanguage="true">
        <encryption:xml-encrypter-config algorithm="AES_128" key="pNVDBAtJ8S8mXfHc" xpath="/user/cc" />
    </encryption:config>

    <encryption:config name="e" enableLanguage="true" doc:name="Encryption">
        <encryption:jce-encrypter-config algorithm="CAST5" key="poso123456789lal" />
    </encryption:config>

    <encryption:config name="symmetricPlain" doc:name="Encryption">
        <encryption:jce-encrypter-config key="${xml.encrypter.key}" />
    </encryption:config>

    <encryption:config name="Encryption" doc:name="Encryption" />

    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>

    <flow name="Get_CC_information" >
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP Connector"/>
        <expression-filter
            expression="#[message.inboundProperties.'http.query.params'.token] != null &amp;&amp; message.inboundProperties.'http.query.params'.user] !=null ]"
            doc:name="Expression" />
        <signature:verify-signature config-ref="Signature"
            input-ref="#[message.inboundProperties.'http.query.params'.user]" expectedSignature="#[message.inboundProperties.'http.query.params'.token]"
            doc:name="Verify User Signature"
            doc:description="Verify if the Signature is correct, so we can validate the User" />
        <set-payload
            value="#[new String(&quot;&lt;user&gt;&lt;name&gt;Royal Bank of Canada&lt;/name&gt;&lt;id&gt;Royal_Bank_Of_Canada&lt;/id&gt;&lt;cc&gt;&lt;company&gt;Visa&lt;/company&gt;&lt;number&gt;1234567890&lt;/number&gt;&lt;secret&gt;123&lt;/secret&gt;&lt;/cc&gt;&lt;/user&gt;&quot;)]"
            doc:name="Create XML response based on User" />
        <encryption:encrypt config-ref="plainXml"
            doc:name="Encrypt the XML (only th CC Info)" using="XML_ENCRYPTER"
            input-ref="#[payload.toString()]" />
    </flow>

    <flow name="Decrypt_The_Request" >
        <http:listener config-ref="HTTP_Listener_Configuration" path="decrypt" doc:name="HTTP Connector"/>
        <object-to-string-transformer doc:name="Object to String" />
        <encryption:decrypt config-ref="plainXml" using="XML_ENCRYPTER" doc:name="Decrypt the xml payload" />
        <logger level="INFO" message="#[new String(e.jce().encrypt(payload))]" doc:name="Log the return but encrypted" />
    </flow>

    <flow name="Get_secret_file" >
        <http:listener config-ref="HTTP_Listener_Configuration" path="getFile" doc:name="HTTP Connector"/>
        <expression-filter
            expression="#[message.inboundProperties.'http.query.params'.token] != null &amp;&amp; message.inboundProperties.'http.query.params'.user] !=null ]"
            doc:name="Expression" />
        <signature:verify-signature config-ref="Signature"
            input-ref="#[message.inboundProperties.'http.query.params'.user]" expectedSignature="#[message.inboundProperties.'http.query.params'.token]"
            doc:name="Verify User Signature"
            doc:description="Verify if the Signature is correct, so we can validate the User" />
        <scripting:component doc:name="Look for Encrypted Message">
            <scripting:script engine="Groovy">
                <scripting:text><![CDATA[return new FileInputStream('src/test/resources/encrypted.txt');]]></scripting:text>
            </scripting:script>
        </scripting:component>
        <encryption:decrypt config-ref="symmetricPlain" doc:name="Decrypt Message" />
    </flow>
</mule>

The sections below offer descriptions of the Anypoint Enterprise Security features’ actions as each flow processes end user requests.

Get_CC_Information Flow

Requesting

From a browser, an end user submits a request via the URL to the Mule application to acquire a customer’s credit card information. To submit this request, open your browser and type the following in the address bar:

http://localhost:8081/?user=Royal_Bank_of_Canada&token=z/TKVFswDDOQw2kjW9Y4jQ==

Processing

Upon receipt of an HTTP request, this flow passes it through a filter that uses a MEL expression to verify that it contains both a user and a token in its query parameters.

Then it uses a Mule Digital Signature Processor to verify the identity of the message’s sender. Mule evaluates the token it receives as a parameter of the request (the token in the URL of the request). The table below describes the configurations of the Digital Signature Processor.

Config Reference

references the Signature global digital signature element

Operation

indicates that the element verifies a signature, rather than apply a signature

Input Reference

uses a Mule Expression to define the part of the payload to which the digital signature applies

Expected Signature

uses a Mule Expression to define the parameter Mule uses to verify the signature

example+signature+1
<signature:verify-signature config-ref="Signature" input-ref="#[message.inboundProperties.'http.query.params'.user]" expectedSignature="#[message.inboundProperties.'http.query.params'.token]" doc:name="Verify User Signature" doc:description="Verify if the Signature is correct, so we can validate the User"/>

What is a Global Element?

Mule ESB uses Global Elements, like the Signature global element in this example, to specify transport details and set reusable configurations.

Rather than repeatedly write the same code to apply the same configuration to multiple message processors, you can create one global element that details your configurations or transport details. Then, you can instruct any number of message processors in your Mule application to reference that global element.

Learn more…​

In this example, the code which specifies the encryption strategy, the algorithm and the key does not exist within the Reservations flow; rather, that code resides in a global element at the top of the application’s XML configuration file (and in the Global Elements tab in — see image below). The Verify User Signature element in the Get_CC_Information flow references and uses the configurations defined within this global element (see code in expandable section below).

global_signature
View the XML for Global Signature Element

After verifying that the requester is valid, Mule uses an expression to set the payload of the message to bank and credit card information. (This function is a simple way to simulate the action of retrieving a customer’s credit card information from a database. For practical reasons in this example, the credit card details are hard-coded into the application.)

Rather than returning the raw credit card information to the caller, Mule first encodes it using a Mule Message Encryption Processor. Using an XML encryption strategy, Mule encrypts the message payload. The table below describes the configurations of the encrypter.

<signature:config name="Signature"  enableLanguage="true" doc:name="Signature">
    <signature:jce-signer algorithm="HmacMD5" key="JLfl5sER3kt4oVkzP2d39UQrUxrEK63LjmXAO45b6cU="/>
    </signature:config>

Config Reference

references the plainXML global encryption element

Operation

indicates that the element encrypts, rather than decrypt a message

Input Reference

instructs Mule to encrypt the payload and display as a string

Using

indicates the encryption strategy

encrypt1

The Message Encryption Processor references the plainXML global encryption element to behave according to the following configurations:

  • Enable Language

  • key (the encryption key)

  • xpath expression which indicates the fields in the payload to encrypt

  • algorithm (the encryption algorithm)

    global_XML_encrypt
<signature:config name="Signature"  enableLanguage="true" doc:name="Signature">
    <signature:jce-signer algorithm="HmacMD5" key="JLfl5sER3kt4oVkzP2d39UQrUxrEK63LjmXAO45b6cU="/>
    </signature:config>

Responding

Finally, Mule uses the HTTP connector to pass the response — encrypted credit card information — to the end user’s browser. The highlighted content in the image below provides the encrypted credit card information.

get_cc_info_response

Decrypt_The_Request Flow

Requesting

An end user submits a request to the Mule application to decrypt the message payload in order to acquire a customer’s unencrypted credit card information. Use an HTTP Request tool (such as the REST Console plugin in the Chrome Web browser) to POST the request below to http://localhost:8081/decrypt

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <name>Royal Bank of Canada</name>
    <id>Royal_Bank_Of_Canada</id>
    <cc>
        <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
                    <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                        <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">9eUu9/kVzwb4ExPxr2UTiugRKoU6oJE9</xenc:CipherValue>
                    </xenc:CipherData>
                </xenc:EncryptedKey>
            </ds:KeyInfo>
            <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"><xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">cUmSEUP5M/OJsIS9MQvX3tMPBk9MgEo1yu2yGDc8swPVuTcs67nwFi25Yak86v+21I1Y98amjseX
5jU4hTz3eJXqd3AVkvTsWA/3d79yoY/c1CyOiTenlSw38+kHQ+JR</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </cc>
</user>

Processing

After accepting an HTTP request from and end user, Mule converts the message payload from a Java object to a string, then employs a Mule Message Encryption Processor to decrypt the message payload.

Using an XML encryption strategy, Mule decrypts the message payload before logging the decryption activity. Mule then returns a response to the caller, which contains the unencrypted credit card data. The table below describes the configurations of the decrypter.

Config Reference

references the plainXML global encryption element

Operation

indicates that the element decrypts, rather than encrypt a message

Encrypter to use

indicates the encryption strategy

decrypt1
<encryption:decrypt config-ref="plainXml" using="XML_ENCRYPTER" doc:name="Decrypt the xml payload"/>

The Message Encryption Processor references the plainXML global encryption element to behave according to the following configurations:

  • Enable Language

  • key (the encryption key)

  • xpath expression which indicates the fields in the payload to decrypt

  • algorithm (the encryption algorithm)

Responding

Finally, Mule uses the HTTP connector to pass the response — decrypted credit card information — to the end user’s browser. The code below displays the unencrypted credit card information.

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <name>Royal Bank of Canada</name>
    <id>Royal_Bank_Of_Canada</id>
    <cc>
        <company>Visa</company>
        <number>1234567890</number>
        <secret>123</secret>
    </cc>
</user>

Get_secret_file Flow

Requesting

From a browser, an end user submits a request via the URL to the Mule application to decrypt the contents of a particular file, then display the decrypted contents to the user. To submit this request, open your browser and type the following in the address bar:

http://localhost:8081/getFile?user=Royal_Bank_of_Canada&token=z/TKVFswDDOQw2kjW9Y4jQ==

Processing

Upon receipt of an HTTP request, this flow, in a manner very similar to the Get_CC_Information flow, first runs a filter to verify that the user and token query parameters exist. Then it uses a Mule Digital Signature Processor to verify the identity of the message’s sender.

Next, Mule uses a Groovy script to locate the file that contains the data to decrypt (in this case, the encryption.txt file in the src > test > resources folder). It then passes the file content to the Mule Message Encryption Processor to decrypt.

The processor references the symmetricPlain global encryption element for directions on how to decrypt the file’s contents. The symmetricPlain element uses the JCE encryption strategy (as indicated by the BINARY_ENCRYPTER selection in the Default field), provides the encryption key, and defines the encryption algorithm.

Responding

Finally, Mule uses the HTTP connector to pass the response — the decrypted message in the encrypted.txt file — to the end user’s browser (see image below).

get_secret_file_response

See Also