Управление секретами IT-инфраструктуры

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

Какой ещё секрет?

Секрет — это конфиденциальная строка текста, которая даёт прямой или косвенный доступ к информационным ресурсам. Например, строка подключения к базе данных (БД), которая даёт доступ к информации в БД.

Что вы получите от статьи?

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

Зачем это нужно?

У компании, в которой я проходил практику, есть около 60 веб-сервисов и приложений, которые продолжают улучшаться и поддерживаться. У каждого сервиса есть в среднем около 15–20 секретов, например: логин и пароль от админки, API-ключи, строки подключения к БД, ключи шифрования и т.д. Обычно они хранятся в специальных файлах конфигурации проекта (appsettings.json) либо прямо в коде. Управлять ими в таком формате, когда они разбросаны по разным репозиториям и файлам, проблематично. Под «управлять» я имею в виду такие действия, как получение и периодическое обновление секретов. Передаются эти секреты между разработчиками обычно через мессенджеры, что приводит к их расползанию.

Что бы сдать этот диплом решить эти проблемы, я сделал свой сервис для управления секретами.

Да похожие системы уже давно существуют, например, HashiCorp Vault и Passwork. Но эта статья не про них. Однако коротко скажу, почему я не использовал их:

  1. «Сложно» настраивать или дорого покупать.

  2. Диплом с готовым решением вряд ли защитил бы.

  3. Хотел попробовать изобрести свой велосипед, сделанный на стеке компании: C#, ASP.NET, Angular.

Что требуется от системы?

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

Вот что мы будем реализовывать:

  1. Передачу данных между клиентом и сервером в зашифрованном виде с использованием асимметричного шифрования (RSA).

  2. Хранение данных в зашифрованном виде, чтобы компрометация БД не приводила к компрометации всех секретов. Для этого будем дополнительно использовать симметричное шифрование (AES).

  3. Надёжное распределение и передача секретов пользователям и системам.

Как будем реализовывать?

Используем такой стек: C#, ASP.NET, Angular с TypeScript. Рассмотрим, как безопасно передавать информацию от клиента к серверу.

Во-первых, перед отправкой нужно шифровать данные. Мы можем использовать симметричное шифрование, когда для шифрования и расшифровки используется один ключ, либо асимметричное шифрование, когда для шифрования и расшифровки используются разные ключи. Объясню, почему мы не можем использовать симметричное шифрование. Допустим, мы на клиенте сгенерировали ключ, с помощью этого ключа зашифровали данные и отправили этот шифр на сервер. Злоумышленник не сможет расшифровать его без ключа клиента, но и сервер не сможет его расшифровать для отправки другим клиентам. Если отправлять и ключ, то смысла от шифрования не будет. Поэтому выбираем асимметричное шифрование.

Для расшифровки секретов серверу нужны ключи. Они будут храниться в таблице «Safe». Каждый секрет относится к какому-то сейфу. Сейф имеет два ключа — публичный и приватный. Приватный ключ перед сохранением в БД шифруется с помощью симметричного алгоритма, а ключ от него хранится на сервере (не в БД).

Чтобы получить доступ к секрету, нужно иметь соответствующие разрешения и нужный ключ для «открытия» сейфа. Название проекта — Bank of Secrets (BOS) — аналогия с банком, безопасность и надежность.

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

Предварительные действия перед отправкой секрета на сервер:

  • Клиент отправляет запрос на создание сейфа.

  • Сервер создаёт сейф и генерирует два ключа (приватный и публичный). Перед сохранением в БД приватный ключ шифруется с помощью AES. Пример кода:

    //endpoint: api/safe/create
    var keys = asymmetricCrypto.GenerateKeys();
    string PublicKeyPem = keys.publicKeyPem;
    string PrivateKeyPem = keys.privateKeyPem;
    // Encrypt private key before saving
    string EPrivateKeyPem = cryptorService.EncryptWithSecretKey(PrivateKeyPem);
    // save keys

    Метод EncryptWithSecretKey использует ключ из конфигурации проекта (appsettings.json) и методы из пространства имён System.Security.Cryptographyи получает шифр для ключа.

Теперь, когда RSA ключи готовы, мы можем приступить к шифрованию. Ниже представлены диаграммы потока данных (DFD), показывающие схему безопасного обмена информацией между клиентом и сервером.

Создание и отправка секрета на сервер

Процесс создание секрета

Cоздание секрета

  1. Клиент получает публичный ключ из сейфа.

  2. Шифрует введённые данные с помощью асимметричного шифрования.

  3. Хэширует шифр и асимметрично шифрует его с помощью публичного ключа (формируется цифровая подпись).

  4. Шифр + хэш шифра (подпись) + публичный ключ (для проверки подписи) отправляются на сервер.

  5. Сервер проверяет подпись и сохраняет секрет в БД точно в том же виде, как он пришёл на сервер.

Получение секрета на клиенте

Получение секрета

Получение секрета

  1. Клиент формирует пару RSA ключей, прикрепляет к запросу публичный ключ и отправляет запрос на получение секрета.

  2. Сервер проверяет все разрешения пользователя.

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

  4. Полученный шифр отправляется клиенту.

  5. Клиент расшифровывает его с помощью своего приватного ключа.

Такой подход обеспечивает отправку и получение записи в зашифрованном виде, гарантируя, что никто, кроме сервера и клиента, не сможет её расшифровать, даже в случае перехвата запроса или трафика. Благодаря цифровой подписи, данные защищены от атак типа «человек посередине» (MITM) и подмены информации. Комбинирование асимметричного и симметричного шифрования защищает нас от компрометации базы данных: даже если злоумышленники получат доступ к БД, они не смогут воспользоваться этими данными.

Что следует учитывать?

  • Риски, связанные с централизацией секретов. Ну, сами подумайте: все ваши секреты хранятся на одном сервере, компрометация которого приведёт к компрометации всей IT-инфраструктуры компании. Надёжные бэкапы и жёсткая политика безопасности данного сервиса, возможно, помогут вам.

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

  • Как оказалось, для использования криптографических алгоритмов необходимо получить сертификат от ФСБ. Они не хотят просто наблюдать за тем, как вы обмениваетесь непонятными символами, они хотят знать всё. Вероятно, от вас потребуют предоставить все ключи, чтобы при необходимости иметь возможность расшифровать любое ваше сообщение.

  • Формирование парных ключей для каждого запроса и использование асимметричного метода шифрования данных — считается плохой практикой. Лучше использовать асимметричное шифрование только для формирования общего симметричного ключа, так как симметричное шифрование работает значительно быстрее. Это особенно важно, если объём данных большой.

  • Обратите большое внимание на формат ключей, они бывают разных видов. Если вы создаёте ключи на клиенте в PEM формате, а на сервере для алгоритма используется PKCS 8 формат, то у вас будет ошибка.

Заключение

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

Телеграм: https://t.me/khayka

Описание и исходный код проекта

Habrahabr.ru прочитано 1330 раз