Encrypting configuration properties

In real-world applications, we typically store an environment-specific configuration outside of the application, and access it through the properties mechanism described in the Using external properties in Camel routes recipe in Chapter 1, Structuring Routes. This enables us to move an application between development, test, and production environments with no code changes required to repoint it to different databases, message brokers, and so on.

To access these resources we often need to store sensitive information such as passwords. It is considered bad practice to keep these in plain text, as that would allow the reader to freely access those resources. To address this, we need to overlay another mechanism that allows us to hide passwords through encryption.

This recipe will show you how to use the Camel Jasypt Component to manage encrypted configuration values within Camel.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.security.encryptedproperties package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with encryptedProperties.

To use the Camel Jasypt Component, add the following to the dependencies section of your Maven POM:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jasypt</artifactId>
  <version>${camel-version}</version>
</dependency>

To encrypt passwords you will also require access to the camel-jasypt JAR file. This file can be found in the binary download of the Camel distribution in the lib directory.

How to do it...

To encrypt configuration properties, perform the following steps:

  1. Download the Camel binary distribution from the Apache Camel website (http://camel.apache.org/download.html) and extract it into a working directory.
  2. Run the following command in the lib directory of the location that you just extracted Camel into:
    # java -jar camel-jasypt-2.12.2.jar -c encrypt -p encryptionPassword -i myDatabasePassword
    

    Tip

    The version in the name of the .jar file corresponds to the Camel version you downloaded.

    The -c flag denotes the task to be performed (encrypt/decrypt). The -p argument is the password used to encrypt the property that you wish to hide. The -i argument is the input that is to be encrypted. The encrypted version of the database password is printed out:

    Encrypted text: hRR5B31qPMJpxk078rXmwllpzQNPpR5kXdnNQrOmIfs=
    
  3. Copy this password and add it to a properties file that provides placeholders to your Camel routes (see the Using external properties in Camel routes recipe in Chapter 1, Structuring Routes). The encrypted text must be surrounded by an ENC(..) string to denote encryption:
    start.endpoint=direct:in
    log.message=The database password is {{database.password}}
    database.password=ENC(hRR5B31qPMJpxk078rXmwllpzQNPpR5kXdnNQrOmIfs=)
    end.endpoint=mock:out

    Tip

    Properties can be embedded within each other, and you can mix encrypted and regular content.

  4. Enable the Jasypt properties parser within the properties component. If using Spring or OSGi Blueprint, instantiate the parser as a regular bean:
    <bean id="jasypt"
          class="org.apache.camel.component.jasypt.JasyptPropertiesParser">
      <property name="password" value="encryptionPassword"/>
    </bean>

    The password used here is the same as that provided to the -p argument during the encryption phase in the command line.

    Inside the camelContext element, define a propertyPlaceholder element that refers to the properties file to be picked up and the parser bean:

    <propertyPlaceholder id="properties"
                         location=
                           "classpath:placeholder.properties"
                         propertiesParserRef="jasypt"/>

    If using Java only, you need to instantiate the parser and PropertiesComponent, and set the component on the Camel context before it is started:

    JasyptPropertiesParser propParser = new JasyptPropertiesParser();
    propParser.setPassword("encryptionPassword");
    
    PropertiesComponent propComponent = new PropertiesComponent();
    propComponent.setLocation("classpath:placeholder.properties");
    propComponent.setPropertiesParser(propParser);
    
    CamelContext camelContext = new DefaultCamelContext();
    camelContext.addComponent("properties", propComponent);
  5. Inside your route you can now use encrypted properties as usual; encrypted properties will be decrypted at runtime.

    The following XML DSL demonstrates this usage:

    <from uri="{{start.endpoint}}"/>
    <setHeader headerName="dbPassword">
      <constant>{{database.password}}</constant>
    </setHeader>
    <log message="{{log.message}}"/>
    <to uri="{{end.endpoint}}"/>

    The same route is expressed in the Java DSL as:

    from("{{start.endpoint}}")
      .setHeader("dbPassword", simple("{{database.password}}"))
      .log("{{log.message}}")
      .to("{{end.endpoint}}");

    Tip

    In the Java DSL, a constant(..) expression does not resolve properties, so we use simple(..) instead.

    In both cases, the route will print out the decrypted string when a message is passed through it:

    The database password is myDatabasePassword

How it works...

The Jasypt Component uses the password that it has been provided with to decrypt any properties that contain the string pattern ENC(..) using the default algorithm PBEWithMD5AndDES.

If you want to use a different algorithm, you run the encryption command from the command line, and pass in the algorithm name through its -a argument. The same algorithm name needs to be passed to the JasyptPropertiesParser through its algorithm property.

Note

Algorithm names are defined in the JCE Standard Algorithm Names Documentation. The algorithm used has to be supported by the JCE providers on both the system that you encrypt the password on, and the one that decrypts it. Not all algorithms are available on all JVMs due to export restrictions. For most purposes, the default algorithm is perfectly adequate.

There's more...

Leaving your master password unencrypted in your code is rarely a good idea. The JasyptPropertiesParser allows you to pass in the name of a Java system variable, or an environment variable, and resolves the password from that for decryption purposes. To use this mechanism, you prefix the password property as follows:

  • sys:jasyptMasterPassword - This resolves a Java system property, set through java –DjasyptMasterPassword=… when starting the JVM that runs the routes
  • sysenv:JASYPT_MASTER_PASSWORD - This resolves to a system variable, set through the shell before the process is started

The choice of the variable name is up to you; it is only the prefix (sys: or sysenv:) that is important.

You often want to use encryption of properties beyond just those used by Camel (for example, passwords for DataSource objects that are instantiated in Spring). For instructions on how to do this, refer to the Jasypt documentation.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.77.208