Статьи

Использование зашифрованных паролей с Mule ESB

Хорошая практика в Mule ESB является обеспечение свойств с помощью файла свойств. В большинстве случаев вы добавляете пароли в файл свойств. В этом случае вы можете зашифровать пароли, чтобы они не были видны всем, у кого есть доступ к файлу свойств. Mulesoft описал, как сделать это в сочетании с Mule ESB. Хотя это хорошая отправная точка, я подумал, что это может помочь создать полный пример, поэтому я описал все шаги в этом посте. Необходимо изменить две среды: среду разработки и среду выполнения.

Среда разработки — это то, где вы создаете свои приложения Mule с помощью Java IDE . Вам нужно будет предпринять следующие шаги:

  • Добавьте зависимости в ваши проекты pom
  • В файле Maven pom добавлены следующие зависимости:

<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>
  • Настройте Mule для использования зашифрованного файла свойств
  • Чтобы сделать Mule ESB способным использовать зашифрованные свойства в файле свойств, я создал конфигурационный файл Spring, который загружается (импортируется) конфигурацией Mule моих приложений Mule. Конфигурационный файл Spring ‘my-properties-config.xml’ выглядит так:

<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> 
  • Настройте свой юнит-тест
  • Конечно, вы хотите выполнить модульное тестирование этой функции. :-)
    Этот шаг разделен на три подэтапа. Первым шагом является создание класса Unit Test. Тот, который я использовал, следующий:

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();
        }
    }
}

Наиболее сложной частью этого модульного теста является код, который добавляет переменную ‘MULE_ENCRYPTION_PASSWORD’ в среду выполнения. Я нашел этот код в Интернете, и, насколько я могу судить, он работает как в Windows 7, так и в Linux Debian (по крайней мере, в этих средах мой модульный тест успешно выполняется). Другим вариантом может быть требование установки переменной среды в каждой среде, в которой выполняется модульное тестирование (машины разработчиков и Jenkins), но я думаю, что рано или поздно вы столкнетесь с проблемой, когда переменная не установлена.

Класс Java использует файл конфигурации Spring ‘test-config.xml’, который выглядит следующим образом:

<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>

Последний шаг — добавление файла свойств теста в модульный тест. Этот файл свойств «my-environment.properties» содержит зашифрованные пароли для проверки:

property.1=value1
property.2=value2
password.1=ENC(2ekUF20x8zP79ydA2d9yo1yhtXnKMxmG)

При этом все тесты uit создают карту со значениями свойств из файла свойств. Значение для «password.1» в файле свойств является зашифрованным значением для строки «пароль» с мастер-паролем «mulesoft». В модульном тесте я получаю значение и проверяю, соответствует ли оно расшифрованному значению.

Так что это для среды разработки. Теперь среда выполнения. Здесь вы запускаете свой автономный Mule ESB. Вам нужно будет добавить необходимые библиотеки Jasypt сюда и использовать их для генерации зашифрованных паролей. Вот шаги:

  • Установите переменную среды
  • Эта переменная среды будет содержать мастер-пароль, который используется для расшифровки зашифрованного пароля. Обратите внимание, что это может быть еще одним возможным нарушением безопасности.
    Чтобы автоматически установить переменную среды на сервере Linux, вы можете создать скрипт в каталоге /etc/profile.d/, чтобы он выполнялся, когда пользователь входит в систему следующим образом:
    sudo nano /etc/profile.d/mule-env.sh
    В файле мы поместили команду для установки среды переменная:
    export MULE_ENCRYPTION_PASSWORD=mulesoft
    после сохранения файла загрузите его для текущего пользователя:
    source /etc/profile
    если вам не нравится идея, что мастер-пароль установлен для каждого пользователя и сохранен в файле, вы можете попытаться установить переменную среды вручную для пользователя незадолго до того, как вы запустите Mule ESB. Я почти уверен, что могут быть лучшие способы сделать это, но я просто показываю, что сработало для меня.

  • Добавьте необходимые файлы в библиотеки Mule ESB
  • Я поместил jars-файлы Jasypt, которые соответствуют зависимостям в моем pom-файле проекта, в каталог ‘/ opt / mule / lib / shared / default’, где ‘/ opt / mule /’ — это каталог установки моего автономного Mule ESB. Таким образом, библиотеки Jasypt доступны всем приложениям Mule, развернутым на этом сервере.

  • Генерация зашифрованных паролей
  • Теперь сгенерируйте необходимые зашифрованные пароли с помощью следующей команды (убедитесь, что пароль совпадает с тем, который используется в переменной среды!):
    java -cp jasypt-1.9.1.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="XXXX" password=mulesoft algorithm=PBEWithMD5AndDES

    mulesoft / mulesoft дает:
    nBB7bPmx93lNmenRrriyjtt8zujZ/imH

  • Поместите пароли в файл свойств
  • Вывод должен быть помещен в файл свойств Mule вашего приложения следующим образом:
    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.