Vault — это фактически стандарт для хранения секретов в мире ИТ. И не только для хранения секретов. Ещё для управления сертификатами, шифрования as-a-service, подписания SSH-ключей, выдачи индивидуальных доступов для работы с базами данных. При этом Vault отлично интегрируется с внешними IdP — например, Keycloak или LDAP. А также он позволяет аутентифицировать приложения Kubernetes на основе JWT-токенов, а для «обычных» приложений можно использовать AppRole. Да и сам Vault может выступать как Identity Provider, если возникнет такая необходимость. Список его возможностей можно перечислять долго.
Представьте, что у вас есть Vault и нужно перенести данные из него в другой Vault. Причём сделать это безопасно, не расшифровывая данные в процессе. Например, перенести их из одного закрытого контура в другой на небезопасной флешке.
Ситуация становится ещё интереснее, если бэкенд хранения исходного Vault — PostgreSQL, а перенести данные мы хотим, например, в Raft. С такой проблемой мы столкнулись, когда начали мигрировать данные клиентов из Vault в наш продукт, построенный на основе Vault, — Deckhouse Stronghold.
Сложности миграции данных из Vault
В Stronghold мы используем Integrated Storage (Raft), чтобы эксплуатация сервиса была проще и понятнее. Не нужно думать отдельно про Vault и отдельно про настройку и обслуживание Postgres или Сonsul, потому что Stronghold сам хранит свои данные. С использованием Integrated Storage получается меньше взаимодействий между сервисами, меньше задержки, а инженерам требуется меньше знаний для обслуживания сервиса. Ну а ещё мы запускаем Stronghold в Kubernetes, и использование таких бэкендов хранения, как Postgres или MySQL, в нём доставляет определённые трудности, так как эти базы не являются изначально Cloud Native.
На просторах Open Source существуют утилиты по миграции данных между инстансами Vault, например medusa или vault-cp. В конце концов, можно написать что-то подобное на любом языке программирования: у Vault открытый API, и существует множество библиотек для создания своих решений.
Но у этого подхода есть несколько проблем:
-
При импорте из Vault данные расшифровываются. Их, конечно, можно сохранить на диск, перешифровав при сохранении (у той же medusa есть такой функционал), но тем не менее.
-
Для копирования данных вам нужен будет токен, имеющий доступ к секретам.
-
Такие утилиты поддерживают, как правило, только импорт/экспорт секретов, но часто копировать нужно ещё политики, PKI или ключи Transit.
-
PKI или ключи Transit могут быть неэкспортируемыми, поэтому их нельзя извлечь, используя API.
Если у нас в исходном Vault и целевом Stronghold бэкендом хранения был бы PostgreSQL, можно было бы перенести его дамп. Если бы в обоих случаях был Integrated Storage, можно было бы перенести снапшот Raft. Но исходные кластеры Vault у разных клиентов могли быть настроены по-разному, поэтому хотелось бы иметь универсальное решение.
Встроенное решение для миграции
Мало кто знает, но у Vault есть опция миграции из одного storage в другой. В документации ей посвящён целый раздел. Однако Google и ChatGPT не в курсе про миграцию между storage backend.
Поисковая выдача Google и ответ ChatGPT
Второй намёк на малоизвестность этой опции — само наличие таких инструментов, как medusa или vault-cp.
Но опция всё же есть. Поэтому всё, что нам нужно для переноса данных из Vault с бэкендом PostgreSQL в Stronghold с бэкендом Integrated Storage — это выполнить миграцию.
Создадим файл migrate.hcl:
storage_source "postgresql" { connection_url = "postgres://vault:vaultpassword@postgresql_server_ip/vault" ha_enabled = "true" } storage_destination "raft" { path = "/tmp/vault-data" }
Выполним команду vault operator migrate -config=migrate.hcl
.
Ну или в нашем случае d8 stronghold operator migrate -config=migrate.hcl
.
d8 — это консольная (CLI) утилита, закрывающая все потребности администратора платформы при работе с Deckhouse Kubernetes Platform, начиная от kubectl и доступа к registry и заканчивая управлением виртуализацией и API Stronghold.
После этого мы можем записать данные из каталога /tmp/vault-data
на внешний накопитель и перенести данные на нём в другой, закрытый, контур. Данные, сохранённые на накопителе, будут зашифрованы.
Вообще говоря, storage_source
и storage_destination
могут быть любыми. Не важно, Сonsul, MySQL или file. Vault прочитает данные из одного storage backend и сохранит as-is в другом.
Вот пример файла, который поможет перенести данные из Consul в file-storage:
storage_source "consul" { address = “counsul-server:8500” path = "vault" } storage_destination "file" { path = "/tmp/vault-data" }
В нашем случае — при миграции из Vault с бэкендом PostgreSQL в Stronghold с бэкендом Raft — нужно будет поместить данные с флешки в /var/lib/deckhouse/strongdhold
и включить модуль Stronghold в кластере Deckhouse Kubernetes Platform. При включении модуля будет создан кластер из трёх узлов Stronghold, в который будут импортированы полученные при миграции данные.
После этого достаточно распечатать один из узлов кластера — остальные его узлы будут распечатаны автоматически. Это, кстати, ещё одно отличие Stronghold от ванильного Vault: для auto unseal ему не требуется внешний KMS или Transit Vault, узлы кластера самостоятельно распечатывают своих соседей.
Наличие автораспечатывания значительно помогает в эксплуатации хранилища в среде Kubernetes, где перезапуск подов — это скорее норма, чем проблема. При этом, в отличие от операторов Vault вроде Bank-Vaults, мы не храним ключ распечатки в Kubernetes-секрете или где-либо ещё, кроме памяти процесса Stronghold. Это позволяет повысить безопасность хранилища секретов.
При переносе данных через operator migrate
будут перенесены все данные, в том числе неэкспортируемые ключи. Также операцию миграции сможет провести пользователь, который не должен иметь доступ к значениям секретов, — данные при переносе не расшифровываются.
Наши клиенты, которым по разным причинам требуется отечественное ПО или сертификат ФСТЭК России и которые ранее пользовались HashiCorp Vault, не подходящим под эти требования, могут абсолютно безопасно перенести свои данные из Vault в Stronghold, в том числе между закрытыми контурами.
P. S.
Если вы ничего не слышали про Stronghold ранее, то буквально в нескольких фразах:
-
мы пишем свой форк HashiCorp Vault;
-
мы не просто импортозамещаем, а переосмысливаем продукт: добавляем тот функционал, которого, на наш взгляд, не хватает для российского рынка;
-
мы в реестре отечественного ПО с 24 апреля 2024 года.
Подробнее обо всём этом можно послушать в записи вебинара «Мы умеем хранить секреты».
В целом миграция между storage backend Vault незаслуженно обделена вниманием на просторах интернета. Возможно, эта статья поможет кому-то с ответом на вопрос «Как безопасно перенести данные из Vault в другой Vault?».
ссылка на оригинал статьи https://habr.com/ru/articles/869290/
Добавить комментарий