Шифрование паролей и параметров

Эта статья описывает включение и настройку шифрования стартовых параметров системы, runtime-параметров.

Шифрование реализуется вспомогательной утилитой crypt-utils.jar (входит в дистрибутив системы). Когда система установлена, утилита сразу готова к работе.

Данные, обрабатываемые утилитой, хранятся в системе в зашифрованном виде. В запросах на изменение UI параметров значения передаются на BE в открытом виде.

Настройка состоит из этапов:

  • Создание keystore.

  • Задание параметров backend.properties.

Указанные этапы позволяют шифровать конфигурационные параметры системы. Для шифрования остальных данных требуется дополнительная настройка.

При шифровании на кластерных версиях генерацию ключа application_ks.p12 для кластерной сборки необходимо выполнить один раз, и затем подложить этот ключ на все ноды системы. Если генерировать ключи на всех нодах, то данный ключ будет уникален на всех нодах, вследствие чего появится ошибка шифрования пароля на всех нодах.

Создание keystore

Создайте keystore с секретным ключом, имеющим название application_secret:

  1. Используйте команду утилиты шифрования для создания пароля keystore:

java -jar crypt-utils.jar kpwd 'ключ-строка'
'ключ-строка' - строка, на основе который вычисляется пароль для keystore
Пример
java -jar crypt-utils.jar kpwd 70ac88aa-b90e-11ee-96b7-55a02820ba60
Результат: Yi4MTYMjYTjBwYBi_wiY
  1. При помощи утилиты keytool создайте keystore c паролем, полученным из утилиты:

keytool -genseckey -alias 'название ключа' -keyalg 'алгоритм' -keysize 'размер ключа' -keystore 'путь до keystore' -storepass 'пароль' -storetype 'тип keystore'
Пример
keytool -genseckey -alias application_secret -keyalg AES -keysize 256 -keystore /application_ks.p12 -storepass Yi4MTYMjYTjBwYBi_wiY -storetype PKCS12

Задание параметров backend.properties

  1. Если система устанавливалась вручную из дистрибутива, то измените параметры в файле <UNIVERSE_CONF_DIR>/backend.properties.

Пример
# Шифрование включено/выключено (true/false)
org.unidata.mdm.system.encryption.enabled=true

# Ключ инсталяции. Любая строка, на основе которой вычисляется пароль для keystore
org.unidata.mdm.system.installation.id=70ac88aa-b90e-11ee-96b7-55a02820ba60

# Путь до keystore
org.unidata.mdm.system.encryption.keystore.path=/application_ks.p12

# Название алгоритма шифрования. Если не задано, то значение AES. Поддерживаются все алгоритмы Java, алгоритм должен совпадать с алгоритмом, указанным при создании keystore
org.unidata.mdm.system.encryption.algorithm=
  1. Если система устанавливалась через Docker, то оптимальный способ конфигурирования - через файл docker-compose.yaml.

Пример
  environment:
    # Включение в системе механизма шифрования
    ENCRYPTION_ENABLED: true

    # Ключ-строка для вычисления пароля к keystore
    INSTALLATION_ID: 70ac88aa-b90e-11ee-96b7-55a02820ba60

    # Название алгоритма шифрования. Стандартное значение, если переменная не указана, AES
    ENCRYPTION_ALGORITHM: AES

    # Путь до файла keystore в контейнере
    ENCRYPTION_KEYSTORE_PATH: /opt/ks/application_ks.p12

Шифрование стартовых параметров

Если система только установлена и PostgreSQL, Opensearch, Orientdb еще не запускались, то зашифровать данные подключения этих сервисов стандартными способами невозможно. Для этого необходимо использовать утилиту шифрования.

java -jar crypt-utils.jar enc 'путь к keystore' 'ключ-строка' 'пароль' '[алгоритм]'
'[алгоритм]' - опциональный параметр с названием алгоритма шифрования. Стандартное значение AES
'ключ-строка' - строка, которая использовалась для генерации пароля к keystore
Пример
java -jar crypt-utils.jar enc /application_ks.p12 70ac88aa-b90e-11ee-96b7-55a02820ba60 postgres
Результат: @ENC(qR14awFmuwgyTNvmG+km5w==)

Зашифрованные значения необходимо указать в файле backend.properties, setenv.sh или .env:

setenv.sh
export POSTGRES_ADDRESS="localhost:5432"
export DATABASE_NAME="mdm"
export POSTGRES_USERNAME="postgres"
export POSTGRES_PASSWORD="@ENC(qR14awFmuwgyTNvmG+km5w==)"
backend.properties
com.unidata.mdm.ee.guest.role=guest
com.unidata.mdm.ee.guest.username=guest
com.unidata.mdm.ee.guest.password=@ENC(qR14awFmuwgyTNvmG+km5w==)
.env
DG_POSTGRES_USER=postgres
DG_POSTGRES_PASSWORD=@ENC(qR14awFmuwgyTNvmG+km5w==)
DG_POSTGRES_DB_NAME=postgres
POSTGRES_OUTER_PORT=15432

Работа с Docker версией

При работе с версией Docker необходимо генерировать ключи внутри контейнера, т.к. при появлении различий в java локальной ВМ и контейнере возникнет ошибка при пробросе ключей в контейнере.

Шаги настройки:

  1. Заведите в docker-compose новый volumes:

    ks-data:
    driver: local
    
  2. Пропишите volume к директории в контейнере для хранения keystore volumes:

    ${BACKEND_INTEGRATION:-./universe-integration}:/usr/local/tomcat/universe-integration
    ks-data:/opt/keys/
    
  3. Запустите контейнер.

  4. Выполните на хосте команду создания keystore:

    /opt/keys/application_ks.p12
    docker exec -it unidata-mdm-deploy-mdm-1 keytool -genseckey -alias application_secret -keyalg AES -keysize 256 -keystore /opt/keys/application_ks.p12 -storepass Yi4MTYMjYTjBwYBi_wiY -storetype pkcs12
    
  5. Выполните на хосте команду шифрования пароля:

    docker exec -it unidata-mdm-deploy-mdm-1 java -jar /usr/local/tomcat/webapps/universe-backend/WEB-INF/lib/org.universe.mdm.crypt-6.12.0-mdm-2-SNAPSHOT.jar enc /opt/keys/application_ks.p12 70ac88aa-b90e-11ee-96b7-55a02820ba60 postgres AES
    
  6. Перезапустите контейнер.

Шифрование runtime-параметров

Примечание

Ниже представлены дополнительные шаги настройки для разработчиков

Дополнительная настройка позволит шифровать строковые параметры, которые помечены как secret.

Пример регистрации шифруемого параметра:

ConfigurationProperty<String> EMAIL_PASSWORD = ConfigurationProperty.string()
            .key(CoreConfigurationConstants.PROPERTY_EMAIL_PASSWORD)
            .groupKey(CoreConfigurationConstants.PROPERTY_EMAIL_GROUP)
            .groupId(PROPERTY_EMAIL_GROUP_ID)
            .moduleId(CoreModule.MODULE_ID)
            .required(false)
            .readOnly(true)
            .secret(true)
            .build();