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

Рассказываем, как команда VK Cloud создавала сервис шифрования данных в покое для своего клиента, что вошло в его архитектуру и как работать с решением.

Запрос и вводные данные


Многие клиенты VK Cloud выбирают в качестве основной инфраструктуры для своих проектов частное облако, которое позволяет использовать сервисы и функциональность публичного облака, но разворачивать облачную среду On‑Premises, то есть на своих ЦОДах.

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

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

Стек и архитектура решения


После анализа доступных решений мы выбрали в качестве основы для реализации системы следующий стек.

  1. Утилита cryptsetup. Она устанавливается на целевые машины в частном облаке VK Cloud, на которых надо шифровать данные. Утилита запускается при старте системы во время монтирования раздела с данными. Для шифрования мы выбрали алгоритм aes-xts-plain64 с длиной ключа 512 бит.
  2. Утилита vaultlocker. Она является надстройкой над системной утилитой cryptsetup и позволяет автоматизировать обращения системной утилиты cryptsetup и API-сервиса хранения сертификатов Vault, а также обращаться к API Vault через POST-запросы и передавать утилите cryptsetup результат работы.
  3. Система доступа к сертификатам Hashicorp Vault. Для безопасного доступа к секретам инструмент разворачивается в корпоративной сети. При этом перед отправкой данных в постоянное хранилище все данные шифруются с помощью алгоритма aes gcm, 256 бит.
  4. База данных HashiCorp Consul. Инструмент предоставляет функциональность обнаружения сервисов, проверки работоспособности, балансировки нагрузки, графика сервисов, взаимного применения идентификации TLS и хранилища конфигурационных ключей. В нашей реализации HashiCorp Consul используется в качестве постоянного хранилища для зашифрованных данных.

Сервис шифрования на базе этих решений получил следующую архитектуру и схему обмена данными:



Алгоритм работы с реализованным сервисом шифрования данных


Теперь подробнее остановимся на том, как работать с полученной реализацией — от установки до подготовки всех компонентов системы. Поскольку решение не подразумевает использование web-интерфейса для управления и настройки системы, для наглядности я дам описание алгоритмов в формате пошаговой инструкции на примере условной компании Company и ее условным тестовым окружением, развернутым на условной инфраструктуре в частном облаке VK Cloud.

Вместе с тем сразу оговорюсь, что в целом алгоритм и реализацию можно считать универсальными, поэтому при незначительных доработках аналогичное решение можно развернуть и использовать даже на Bare Metal.

Дисклеймер: Все персонажи являются вымышленными, а совпадения — случайными. Все действия выполнены профессионалами!

Итак, приступим. 

Установка и настройка компонента Hashicorp Consul


1. Установка и настройка компонента Hashicorp Consul

1.1. Копируем артефакт consul_1.17.0_linux_amd64.zip на VM s001tst-hcv01.company.local (10.2.92.40), после чего поочередно выполняем команды:

unzip путь/до/файла/consul_1.17.0_linux_amd64.zip
sudo mv путь/до/файла/consul /usr/local/bin/
sudo chown a001-consul:a001-consul /usr/local/bin/consul
sudo chmod +x /usr/local/bin/consul

Создаем каталоги:

mkdir -p /etc/consul
mkdir -p /etc/consul.d/scripts
mkdir -p /etc/consul.d/certs
mkdir /var/consul
mkdir /var/log/consul
mkdir -p /var/consul/data
chown a001-consul:a001-consul /var/consul -R
chown a001-consul:a001-consul /etc/consul.d –R
chown a001-consul:a001-consul /etc/consul.d/certs -R
chown a001-consul:a001-consul /etc/consul -R
chown a001-consul:a001-consul /var/log/consul -R

Генерируем безопасный ключ:

consul keygen

Полученное значение encrypt важно записать.

Создаем файл конфигурации:

sudo touch /etc/consul.d/config.json

Приводим файл конфигурации к следующему виду:

{
    "node_name": "s001tst-hcc01.company.local",
    "bootstrap_expect": 1,
    "client_addr": "0.0.0.0",
    "datacenter": "vkdc1",
    "data_dir": "/var/consul",
    "domain": "",
    "enable_script_checks": true,
    "disable_update_check": true,
    "dns_config": {
        "enable_truncate": true,
        "only_passing": true
    },
"ports": {
    "http": -1,
    "https": 8501
},
    "enable_syslog": true,
    "encrypt": " //Вставить значение encrypt, полученное ранее командой consul keygen//",
    "leave_on_terminate": true,
"rejoin_after_leave": true,
    "server": true,
    "start_join": [
    "s001tst-hcc01.company.local"
    ],
    "ui_config": {
      "enabled": false
    }
}

1.2. Установка сертификата

Размещаем сертификаты:

s001tst-hcc01.company.local.pem
s001tst-hcc01.company.local.crt
s001tst-hcc01.company.local.key

по пути /etc/consul.d/certs/

Приводим конфигурационный файл /etc/consul.d/config.json к следующему виду:

{
    "tls": {
       "defaults": {
          "ca_file": "/etc/consul.d/certs/s001tst-hcc01.company.local.pem",
          "cert_file": "/etc/consul.d/certs/s001tst-hcc01.company.local.crt",
          "key_file": "/etc/consul.d/certs/s001tst-hcc01.company.local.key",
          "verify_outgoing": true,
          "verify_incoming": false
       },
       "internal_rpc": {
        "verify_server_hostname": true
       }
    },
    "auto_encrypt": {
      "allow_tls": true
    }

1.3. Настройка логирования

Приводим конфигурационный файл /etc/consul.d/config.json к следующему виду:

{
    "log_file": "/var/log/consul/consul.log",
    "log_level": "DEBUG",
    "log_json": false,
    "log_rotate_duration": "24h",
    "log_rotate_max_files": -1,
    }

1.4. Настройка доступа к DB по токену

Приводим конфигурационный файл /etc/consul.d/config.json к следующему виду:

acl {
"enabled" = "true"
"default_policy" = "deny"
"down_policy" = "extend-cache"
"tokens": {
"agent": "<AGENT_TOKEN>"
}

1.5. Настройка Consul Agent

Размещаем сертификат s001tst-hcv01.company.local.pem по пути /etc/consul.d/certs/.

Создаем файл конфигурации «client.json» с помощью команды sudo touch /etc/consul/client.json

Приводим файл конфигурации /etc/consul/client.json к следующему виду:

{
    "tls": {
       "defaults": {
          "ca_file": "/etc/consul/certs/s001tst-hcc01.company.local.pem",
          "verify_outgoing": true,
          "verify_incoming": false
       },
       "internal_rpc": {
        "verify_server_hostname": true
       }
    },
  "auto_encrypt": {
    "tls": true
  },
  "server": false,
  "datacenter": "VKDC1",
  "node_name": "s001tst-hcc01.company.local",
  "data_dir": "/var/consul/data",
  "bind_addr": "10.2.92.40",
  "client_addr": "127.0.0.1",
  "disable_update_check": true,
  "retry_join": ["s001tst-hcc01.company.local"],
  "encrypt": "//Вставить значение encrypt, полученное ранее командой consul keygen//",
  "log_level": "DEBUG",
  "enable_syslog": true,
  }
}

1.6. Настройка запуска Consul в качестве службы

Создаем файл «consul.service» с помощью команды sudo touch /etc/systemd/system/consul.service.

Приводим конфигурационный файл /etc/systemd/system/consul.service к следующему виду:

[Unit]
Description=Consul Startup process
After=network.target
 
[Service]
User= a001-consul
Group= a001-consul
Type=simple
ExecStart=/bin/bash -c '/usr/local/bin/consul agent -config-dir /etc/consul.d/'
TimeoutStartSec=0
 
[Install]
WantedBy=default.target

Настойка запуска Consul Agent в качестве службы

Создаем файл «consul-agent.service» с помощью команды sudo touch /etc/systemd/system/consul-agent.service.

Приводим конфигурационный файл /etc/systemd/system/consul-agent.service
к следующему виду:

[Unit]
Description=Consul client agent
Requires=network-online.target
After=network-online.target
[Service]
User=a001-consul
Group=a001-consul
PIDFile=/var/run/consul/consul.pid
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /var/run/consul
ExecStartPre=/bin/chown -R a001-consul:a001-consul /var/run/consul
ExecStart=/usr/local/bin/consul agent \
-config-file=/etc/consul/client.json \
-pid-file=/var/run/consul/consul.pid
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target

1.7. Выполняем запуск Consul Agent в качестве службы

С помощью команды consul validate /etc/consul.d проверяем, что в конфигурации нет ошибок

Поочередно выполняем команды:

sudo systemctl daemon-reload
sudo systemctl enable consul
sudo systemctl enable consul-agent
sudo systemctl start consul
sudo systemctl start consul-agent

Проверяем, что службы запущены, поочередно выполняем команды:

sudo systemctl status consul
sudo systemctl status consul -agent

Статус должен быть «active».

1.8. Создание токенов и полиси

Включаем авторизацию по токену:

export CONSUL_HTTP_ADDR=https://s001tst-hcc01.company.local:8501
consul acl bootstrap

Важно сохранить полученные токены: AccessorID и SecretID, который является загрузочным токеном, токеном администратора.

export CONSUL_HTTP_TOKEN=«//SECRET_ID, полученный командой выше//»
consul acl token create -description "Agent token for node hcc01" -node-identity "s001tst-hcc01.company.local:VKDC1"

Записываем полученное значение «Agent token for node hcc01».

Вносим полученный токен в файле /etc/consul.d/config.json в строку «agent»: "<AGENT_TOKEN>"

Создаем токен и полиси для Vault

Создаем файл vault-policy.hcl:

touch vault-policy.hcl

Приводим файл vault-policy.hcl к следующему виду:

service "vault" { policy = "write" }
key_prefix "vault/" { policy = "write" }
agent_prefix "" { policy = "read" }
session_prefix "" { policy = "write" }
path "vaultlocker/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

Поочередно выполняем команды:

consul acl policy create -name vault-service -rules @vault-policy.hcl
consul acl token create -description "Vault Service Token" -policy-name vault-service
consul acl policy create -name vault-policy -rules @vault-policy.hcl
consul acl token create -description "Token for Vault Service" -policy-name vault-policy
rm vault-policy.hcl

Записываем полученное значение Token for Vault Service.

Используем данный токен при подключении Vault к Consul.

Создаем токен и полиси для системы мониторинга Prometheus

Создаем файл monitoring-policy.hcl с помощью команды touch monitoring-policy.hcl.

Приводим файл monitoring-policy.hcl к следующему виду:

node_prefix "" {
policy = "read"
}
service "consul" {
policy = "read"
}
agent_prefix "" {
policy = "read"
}
session_prefix "" {
policy = "read"
}

Поочередно выполняем команды:

consul acl policy create –description "Consul ACL for Prometheus" -name monitoring-policy -rules @monitoring-policy.hcl
consul acl token create -description "Consul Token for Prometheus" -policy-name monitoring-policy
rm monitoring-policy.hcl

Записываем полученное значение Consul Token for Prometheus — этот токен будем предоставлять по запросу от ИБ.

2. Установка и настройка компонента Hashicorp Vault

2.1. Копируем артефакт vault_1.15.2_linux_amd64.zip на VM s001tst-hcv01.company.local (10.2.92.40), поочередно выполняем команды:

unzip vault_1.15.2_linux_amd64.zip
mv путь/до/файла/vault /usr/local/bin/
chown a001-vault:a001-vault /usr/local/bin/vault
chmod +x /usr/local/bin/vault

Создаем каталоги:

sudo mkdir -p /etc/vault
sudo mkdir -p /var/log/vault
chown a001-vault:a001-vault /etc/vault -R
chown a001-vault:a001-vault /var/log/vault -R

С помощью команды sudo touch /etc/vault/config.json создаем файл конфигурации «config.json».

Приводим файл конфигурации к следующему виду:

{
"listener": [{
"tcp": {
"address" : "0.0.0.0:8200",
}
}],
"api_addr": "https://s001tst-hcv01.company.local:8200",
},
"max_lease_ttl": "10h",
"default_lease_ttl": "10h",
"ui":false
}

2.2. Установка сертификата

Подготавливаем сертификат s001tst-hcv01.company.local.crt, добавляем к сертификату корневой CA.

Размещаем сертификаты s001tst-hcv01.company.local.crt и s001tst-hcv01.company.local.key по пути /etc/certs/.

Приводим конфигурационный файл /etc/vault/config.json к следующему виду:

"listener": [{
"tcp": {
"tls_cert_file" = "/etc/certs/s001tst-hcv01.company.local.crt"
"tls_key_file" = "/etc/certs/s001tst-hcv01.company.local.key"
"tls_min_version" = "tls12"
"tls_disable" : 0,

}

2.3. Настройка логирования

Приводим конфигурационный файл /etc/vault/config.json к следующему виду:

log_level = "info"

Включаем логирование:

vault audit enable file file_path="/var/log/vault/vault-audit.log"

Выполняем проверку:

vault audit list -detailed

2.4. Настройка мониторинга

Приводим конфигурационный файл /etc/vault/config.json к следующему виду:

telemetry {
  prometheus_retention_time = "8h"
  disable_hostname = true
  enable_hostname_label = "true"
  metrics_prefix = "vault"
}

В Vault создаем полисер и токен для сервиса мониторинга Prometheus:

Поочередно выполняем команды:

cat <<EOF > metrics.hcl
path "/sys/metrics" 
{capabilities = ["read"]} 
EOF
vault policy write prometheus-metrics - metrics.hcl
vault token create \
  -field=token \
  -policy prometheus-metrics

Записываем полученное значение «Vault Token for Prometheus» — этот токен может понадобиться по запросу ИБ. 

2.5. Настройка подключения к db Consul по токену

Приводим конфигурационный файл /etc/vault/config.json к следующему виду:

"storage": {
  "consul" : {
  "address" : "https://s001tst-hcc01.company.local:8501",
  "path": "vault",
  "token": "//Token for Vault Service полученный в п.1.7//"
  }
}

2.6. Запуск в качестве службы

С помощью команды sudo touch /etc/systemd/system/vault.service создаем файл «vault.service».

Приводим конфигурационный файл /etc/systemd/system/vault.service к следующему виду:

[Unit]
Description=vault service
Requires=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/vault/config.json

[Service]
User=a001-vault
Group=a001-vault
ProtectSystem=full
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
SecureBits=keep-caps
StartLimitInterval=60
StartLimitIntervalSec=60
StartLimitBurst=3
AmbientCapabilities=CAP_IPC_LOCK
Capabilities=CAP_IPC_LOCK+ep
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
NoNewPrivileges=yes
RestartSec=5
TimeoutStopSec=30
LimitNOFILE=65536
LimitMEMLOCK=infinity
EnvironmentFile=-/etc/sysconfig/vault
Environment=GOMAXPROCS=2
Restart=on-failure
ExecStart=/usr/local/bin/vault server -config=/etc/vault/config.json ExecReload=/bin/kill --signal HUP $MAINPID
StandardOutput=/var/log/vault/output.log
StandardError=/var/log/vault/error.log
LimitMEMLOCK=infinity
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT 
KillMode=process 

[Install]
WantedBy=multi-user.target

StartLimitIntervalSec=60
StartLimitBurst=3

2.7. Запуск службы

sudo systemctl daemon-reload
sudo systemctl enable vault
sudo systemctl start vaul

Выполняем команду sudo systemctl status vault, чтобы убедиться, что службы запущены. Статус должен быть «active».

Выполняем инициализацию Vault и получаем ключи, выполнив команду:

vault operator init

Вывод это команды важно сохранить, поскольку больше получить ключи не получится.

Пример вывода:

Unseal Key 1: qqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Unseal Key 2: wwwwwwwwwwwwwwwwwwww
Unseal Key 3: eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Unseal Key 4: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Unseal Key 5: tttttttttttttttttttttttttttttttttttttttttttttttttttr
Initial Root Token: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

Выполняем распечатку (unsealing) хранилища Vault, поочередно выполняя команды:

vault operator unseal «значение Unseal Key 1»
vault operator unseal «значение Unseal Key 2»
vault operator unseal «значение Unseal Key 3»

Получаем возможность работы с API Vault, выполнив команду: 

export VAULT_TOKEN=//значение Initial Root Token//

Разрешаем доступ по паролю и создаем служебного пользователя:

vault auth enable userpass
vault write auth/userpass/users/a001-vault-adm policies=default password=«Пароль в соответствии с требованиями компании»

Создаем хранилище секретов:

vault secrets enable -path=vaultlocker kv

Создаем политику:

cat <<EOF > vaultlocker.hcl
> path "/vault/*" {
> capabilities = ["create", "read", "update", "delete", "list"]
> }
> EOF
vault policy write vaultlocker vaultlocker.hcl
rm vaultlocker.hcl

Создаем приложение:

vault auth enable approle
vault write auth/approle/role/vaultlocker bound_cidr_list=10.24.14.22/32,10.24.13.139/32 token_bound_cidrs=10.24.14.22/32,10.24.13.139/32 policies=vaultlocker
vault write auth/approle/role/vaultlocker bind_secret_id=false

Значение approle-id обязательно сохраняем — его может запросить команда ИБ.

Скрипт по распечатыванию при старте:

Создаем файл «creds.txt», выполнив команду:

mkdir /etc/autounseal
mkdir -p /var/log/vault/unseal
chown a001-vault-unseal:a001-vault-unseal /etc/autounseal -R
chown a001-vault-unseal:a001-vault-unseal /var/log/vault/unseal -R
touch /etc/autounseal/creds.txt
chmod 700 /etc/autounseal/creds.txt

Вписываем в файл /etc/autounseal/creds.txt значения ключей:

Unseal Key 1
Unseal Key 2
Unseal Key 3

Создаем файл «autounseal.sh» и делаем его исполняемым, поочередно выполняя команды:

touch /etc/autounseal/autounseal.sh
chown a001-vault-unseal:a001-vault-unseal /etc/autounseal/autounseal.sh
chmod 700 /etc/autounseal/autounseal.sh

Приводим конфигурационный файл /etc/autounseal/autounseal.sh к следующему виду:

#!/bin/bash

echo "Vault autounseal запущен" >> /var/log/vault/unseal/unseal.log


export VAULT_ADDR=https://s001tst-hcv01.company.local:8200

# Путь к файлу с ключами
CREDENTIALS_FILE="/etc/autounseal/creds.txt"

# Путь к исполняемому файлу Vault
VAULT_EXECUTABLE="/usr/local/bin/vault"

if [[ ! -f "$CREDENTIALS_FILE" ]]; then
    echo "Файл ключей не найден: $CREDENTIALS_FILE" >> /var/log/vault/unseal/unseal.log
    exit 1
fi

if [[ ! -x "$VAULT_EXECUTABLE" ]]; then
    echo "Vault не установлен или не найден в PATH" >> /var/log/vault/unseal/unseal.log
    exit 1
fi
echo "HELLO"
echo $VAULT_EXECUTABLE
echo $CREDENTIALS_FILE
# Читаем ключи и кладем их в Vault для снятия блокировки
sleep 40
while read -r key; do
    echo "Unsealing Vault..."
    echo $key
    echo $VAULT_EXECUTABLE operator unseal $key
    $VAULT_EXECUTABLE operator unseal $key
done < "$CREDENTIALS_FILE"
echo "Vault autounseal завершен" >> /var/log/vault/unseal/unseal.log

Запуск в качестве службы

С помощью команды sudo touch /etc/systemd/system/autounseal.service создаем файл «autounseal.service».

Приводим конфигурационный файл /etc/systemd/system/autounseal.service к следующему виду:

[Unit]
Description=Vault autounseal
After=network.target network-online.target vault.service

[Service]
User=a001-vault-unseal
Group=a001-vault-unseal
Type=simple
ExecStart=/bin/bash -c 'VAULT_ADDR=https://s001tst-hcv01.company.local:8200 exec /etc/autounseal/autounseal.sh'

[Install]
WantedBy=multi-user.target
Выполнить запуск в качестве службы, поочередно выполнить команды:
sudo systemctl daemon-reload
sudo systemctl enable autounseal
sudo systemctl start autounseal

Выполняем проверку автораспечатывания хранилища после перезагрузки сервера.

Перезагружаем VM s001tst-hcv01.company.local, после чего выполняем команду: vault status.

В выводе команды должно быть:

Unseal Progress 3/5
Sealed false

3. Установка и настройка компонента Fluent-bit

Выполняем установку Fluent-bit

Копируем артефакт на VM, поочередно выполняем команды:

unzip fluent-bit-rpm.zip
yum localinstall fluent-bit.rpm

Выполняем запуск от служебной учетной записи

Приводим конфигурационный файл /fluent-bit/etc/fluent-bit.conf к следующему виду:

[SERVICE]
user a001-fluenbit

Настраиваем передачу логируемых событий в SIEM

Приводим конфигурационный файл /etc/fluent-bit/fluent-bit.conf к следующему виду:

[INPUT]
    Name        tail
    Tag       Consul
    Path        /var/log/consul/consul.log

[INPUT]
    Name        tail
    Tag       Vault-audit
    Path        /var/log/vault/vault-audit.log

[INPUT]
    Name        tail
    Tag       Vault-stdout
    Path        /var/log/vault/output.log

[INPUT]
    Name        tail
    Tag       Vault-stderr
    Path        /var/log/vault/error.log

[INPUT]
    Name        tail
    Tag       Vault-unseal-stdout
    Path        /var/log/vault/unseal/output.log

[INPUT]
    Name        tail
    Tag       Vault-unseal-stderr
    Path        /var/log/vault/unseal/error.log

INPUT]
    Name        tail
    Tag       Vault-unseal
    Path        /var/log/vault/unseal/unseal.log

[OUTPUT]
    name                 syslog
    match                Vault-audit, Vault-stdout, Vault-stderr, Vault-unseal-stdout, Vault-unseal-stderr, Vault-unseal
    host                 10.2.16.90
    port                 514
    mode                 udp
    syslog_format        rfc5424
    syslog_maxsize       2048
    syslog_hostname_key  s001tst-hcv01.company.local
    syslog_appname_key   Vault
    syslog_procid_key    procid
    syslog_msgid_key     msgid 
    syslog_sd_key        uls@0
    syslog_message_key   log

[OUTPUT]
    name                 syslog
    match                Consul
    host                 10.2.16.90
    port                 514
    mode                 udp
    syslog_format        rfc5424
    syslog_maxsize       2048
    syslog_hostname_key  s001tst-hcc01.company.local
    syslog_appname_key   Vault
    syslog_procid_key    procid
    syslog_msgid_key     msgid 
    syslog_sd_key        uls@0
    syslog_message_key   log

Выполняем запуск

Выполняем команды:

systemctl enable fluent-bit
systemctl start fluent-bit

Чтобы убедиться, что сервис запущен, выполняем команду systemctl status fluent-bit. Статус должен быть «active». 

Установка Vaultlocker


Установка Vaultlocker на серверах компании.

Устанавливаем пакеты и зависимости из локального репозитория:

epel-release 7-11
python3-pip 9.0.3-8.el7
cruptsetup

Зависимости:

python3 3.6.8-19.el7_9
python3-libs 3.6.8-19.el7_9
python3-setuptools 39.2.0-10.el7

Устанавливаем Vaultlocker:

pip3 install vaultlocker --index-url=https://repo-test.company.local/api/pypi/pypi-remote/simple --trusted-host repo-test.company.local -v

Создаем каталоги:

sudo mkdir /etc/vaultlocker

Создаем файл конфигурации «vaultlocker.conf», выполнив команду:

sudo touch /etc/vaultlocker/vaultlocker.conf

Приводим конфигурационный файл /etc/vaultlocker/vaultlocker.conf к следующему виду:

[vault]
url = https://s001tst-hcv01.company.local:8200
approle = //Запросить у ИБ значение Approle-ID//
secret_id = yyy-ttt-rrr-eee-www (любое значение, не используется, но требуется в конфигурации)
backend = /vaultlocker
ca_bundle=/путь/до/публичного корневого CA.

Активация шифрования дисков с ПД


Для каждой VM выполняем следующую последовательность действий.

В админ панели VK Cloud:

  1. Создаем диск для БД с нужными параметрами.
  2. Создаем таблицу разделов.
  3. Создаем файловую систему.
  4. Премонтируем диски к соответствующей VM.

На VM:

Останавливаем зависимый сервис с помощью команды Systemctl stop docker.service docker.socket.

Создаем временную директорию для данных /tmpdb, выполняем копирование данных во временную директорию:

mkdir /tempdb
rsync -arv //Директория// /tempdb

Убеждаемся в отсутствии ошибок при копировании, удаляем директорию со всем содержимым:

rm -rf //Директория// 

Получаем список всех дисков с их UDID:

ls -lash /dev/disk/by-uuid/

Шифруем требуемый диск с помощью команды:

vaultlocker encrypt --uuid //uuid требуемого диска// //путь до раздела диска//

После выполнения команды будет создан сервис «vaultlocker-decrypt@.service».

Повторно создаем файловую систему на диске /dev/mapper/crypt-uuid. Закрываем диск и выполняем команду cryptsetup close crypt-//uuid//.

Приводим конфигурационный файл /usr/local/lib/systemd/system/vaultlocker-decrypt@.service к следующему виду:

[Unit]
Description=vaultlocker retrieve: %i
DefaultDependencies=no
After=networking.service
Before=//Название зависимого сервиса//
[Service]

Type=oneshot
KillMode=none
Environment=VAULTLOCKER_TIMEOUT=10000
ExecStart=/bin/sh -c 'vaultlocker --retry $VAULTLOCKER_TIMEOUT decrypt %i && /usr/bin/mount /dev/mapper/crypt-%i //Указать шифруемую директорию//'

Запускаем сервис vaultlocker-decrypt@.service. Проверяем доступность директории. При необходимости создаем символические ссылки на директории.

Выполняем копирование данных из временной директории /tmpdb:

rsync –arv /tempdb // Указать шифруемую директорию //

Запускаем зависимый сервис с помощью команды Systemctl start docker.service.

Убеждаемся в работе сервиса с директорией с данными, после чего удаляем временную директорию /tmpdb со всем содержимым с помощью команды rm -rf /tmpdb.

Настройка сбора метрик


Размещаем значения токенов «Consul Token for Prometheus» и «Vault Token for Prometheus» и CA сертификатов s001tst-hcc01 и s001tst-hcv01 в секретах неймспейса кластера k8s Test (Тестовое окружение (TEST)).

В неймспейсе в Prometheus Operator размещаем конфигурационные файлы для сбора метрик Consul и Vaut. 

Пример scrape_configs файлов:

  • Hasicorp Cosul:

scrape_configs:
  - job_name: Consul
    metrics_path: "/v1/agent/metrics"
    scheme: https
    tls_config:
      ca_file: /etc/prometheus/s001tst-hcc01.company.local.pem
    bearer_token_file: /etc/prometheus/prometheus-token-consul
    static_configs:
    - targets: [s001tst-hcc01.company.local:8501']

  • Hasicorp Vault:

# prometheus.yml
scrape_configs:
  - job_name: 'Vault'
    metrics_path: "/v1/sys/metrics"
    scheme: https
    tls_config:
      ca_file: /etc/prometheus/s001tst-hcv01.company.local.pem
    bearer_token_file: /etc/prometheus/prometheus-token
    static_configs:
    - targets: ['vault_server_ip:8200']

Перезапускаем конфигурацию мониторинга, после чего проверяем получение метрик от Consul и Vault в системе мониторинга.

Итоги реализации


С помощью такой конфигурации мы смогли реализовать для клиента сервис шифрования, который надежно защищает данные на его дисках. Что важно, нам удалось выстроить понятный и прозрачный процесс создания ключа для шифрования диска.


Диаграмма процесса создания и сохранения ключа для шифрования диска

В дешифровке диска и его монтировании тоже удалось обойтись без «костылей» и сложных реализаций: основные этапы подготовки мы выполняем на стороне облачной платформы VK Cloud, а саму работу с данными — в контуре пользователя.


Диаграмма процесса дешифровки и монтирования диска

Для сервиса хранения сертификатов были созданы отдельный VLAN и подсеть. Для дополнительной безопасности доступ к Consul организован с использованием авторизации по токену, а взаимодействие между компонентами решения организовано с использованием защищенных протоколов.

Важно, что доступы к реализованному сервису тоже ограничены: и инфраструктурные, и функциональные администраторы могут работать с ней только после подтверждения прав доступа и полномочий.

Вместо выводов


При умелом использовании и понимании принципов реализовать сервис для защиты данных в состоянии покоя можно практически из «подручных материалов» в виде общедоступных инструментов — не надо углубляться в разработку с нуля и изобретать велосипед. В таком случае основной пул задач сводится к выстраиванию взаимодействия между выбранными сервисами, отладке рабочих процессов, реализации всей механики и интеграциям.

Реализовать сервис с учетом всех требований заказчика в нашем случае сильно помогло и то, что как частное, так и публичное облако VK Cloud легко интегрируются со сторонними решениями и реализациями, не требуя сложных архитектурных надстроек.

Комментарии (1)


  1. Meklon
    10.06.2024 23:18

    Коллеги, а зачем такое хулиганство с хранением фрагментов ключей Шамира на узле с Vault? Фактически, атакующему будет достаточно получить доступ к любой ВМ с Vault, чтобы собрать ключ, шифрующий мастер-ключ от всего крипто хранилища в Consul.

    Банально, такую атаку сможет осуществить любой сотрудник, имеющий доступ к бэкапу ВМ.

    Там же весь смысл разделяемых ключей в том, что никто из сотрудников не имеет достаточно данных в руках для расшифровки базы в одиночку.