Використання постачальника KMS для шифрування даних

Ця сторінка показує, як налаштувати постачальника Служби керування ключами (KMS) та втулок для шифрування конфіденційних даних. У Kubernetes 1.30 існують дві версії шифрування даних за допомогою KMS у спокої. Якщо це можливо, вам слід використовувати KMS v2, оскільки KMS v1 застарів (починаючи з Kubernetes v1.28) та є типово вимкненим (починаючи з Kubernetes v1.29). KMS v2 пропонує значно кращі характеристики продуктивності, ніж KMS v1.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Версія Kubernetes, яка вам потрібна, залежить від того, яку версію API KMS ви вибрали. Kubernetes рекомендує використовувати KMS v2.

  • Якщо ви вибрали KMS API v2, вам слід використовувати Kubernetes v1.30 (якщо ви запускаєте іншу версію Kubernetes, яка також підтримує API v2 KMS, перейдіть до документації для цієї версії Kubernetes).
  • Якщо ви вибрали KMS API v1 для підтримки кластерів до версії v1.27 або якщо у вас є застарілий плагін KMS, який підтримує лише KMS v1, будь-яка підтримувана версія Kubernetes буде працювати. Цей API є застарілим починаючи з Kubernetes v1.28. Kubernetes не рекомендує використовувати цей API.
Для перевірки версії введіть kubectl version.

KMS v1

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.28 [deprecated]
  • Потрібна версія Kubernetes 1.10.0 або пізніше.

  • Починаючи з версії 1.29, реалізація v1 KMS типово вимкнена. Щоб увімкнути функцію, встановіть --feature-gates=KMSv1=true, щоб налаштувати постачальника KMS v1.

  • Ваш кластер повинен використовувати etcd v3 або пізніше.

KMS v2

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.29 [stable]
  • Ваш кластер повинен використовувати etcd v3 або пізніше.

Шифрування KMS та ключі для кожного обʼєкта

Постачальник шифрування KMS використовує схему шифрування конвертів для шифрування даних в etcd. Дані шифруються за допомогою ключа шифрування даних (data encryption key — DEK). DEK шифруються за допомогою ключа шифрування ключа (key encryption key — KEK), який зберігається та обслуговується на віддаленому KMS.

Якщо ви використовуєте (застарілу) реалізацію v1 KMS, для кожного шифрування генерується новий DEK.

З KMS v2 для кожного шифрування генерується новий DEK: API-сервер використовує функцію похідного ключа для генерації ключів шифрування даних з одноразовим використанням секретного початкового елемента (seed — насіння) у поєднанні з випадковими даними. Ротація насіння відбувається при кожній зміні KEK (див. розділ Розуміння key_id та Ротація ключів нижче для докладніших відомостей).

Постачальник KMS використовує gRPC для звʼязку з певним втулком KMS через сокет UNIX-домену. Втулок KMS, який реалізований як сервер gRPC та розгорнутий на тих самих вузлах що і панель управління Kubernetes, відповідає за всі комунікації з віддаленим KMS.

Налаштування постачальника KMS

Для налаштування постачальника KMS на API-сервері включіть постачальника типу kms у масиві providers у файлі конфігурації шифрування і встановіть наступні властивості:

KMS v1

  • apiVersion: Версія API для постачальника KMS. Залиште це значення порожнім або встановіть його на v1.
  • name: Показує назву втулка KMS. Не може бути змінено після встановлення.
  • endpoint: Адреса прослуховування сервера gRPC (втулка KMS). Точка доступу — це сокет UNIX-домену.
  • cachesize: Кількість ключів шифрування даних (DEK), які будуть збережені в кеші у відкритому вигляді. Коли ключі DEK збережені в кеші, вони можуть бути використані без додаткового звертання до KMS; тоді як ключі DEK, які не збережені в кеші, потребують звертання до KMS для розшифрування.
  • timeout: Скільки часу kube-apiserver має чекати на відповідь від втулка kms, перш ніж сповістити про помилку (типово — 3 секунди).

KMS v2

  • apiVersion: Версія API для постачальника KMS. Встановіть це на v2.
  • name:Показує назву втулка KMS. Не може бути змінено після встановлення.
  • endpoint: Адреса прослуховування сервера gRPC (втулка KMS). Точка доступу — це сокет UNIX-домену.
  • timeout: Скільки часу kube-apiserver має чекати на відповідь від втулка kms, перш ніж сповістити про помилку (типово — 3 секунди).

KMS v2 не підтримує властивість cachesize. Всі ключі шифрування даних (DEK) будуть збережені в кеші у відкритому вигляді, як тільки сервер розкриє їх за допомогою звертання до KMS. Після збереження в кеші, ключі DEK можуть бути використані для виконання розшифрування нескінченно довго без звертання до KMS.

Дивіться Розуміння налаштування шифрування в спокої.

Реалізація втулка KMS

Для реалізації втулка KMS ви можете розробити новий сервер gRPC втулка або увімкнути втулок KMS, який вже надається вашим постачальником хмарних послуг. Потім ви інтегруєте втулок з віддаленим KMS та розгортаєте його на панелі управління Kubernetes.

Увімкнення KMS, що підтримується вашим постачальником хмарних послуг

Зверніться до вашого постачальника хмарних послуг для отримання інструкцій щодо увімкнення втулка KMS, який він надає.

Розробка сервера gRPC втулка KMS

Ви можете розробити сервер gRPC втулка KMS, використовуючи файл шаблону, доступний для мови програмування Go. Для інших мов програмування ви можете використовувати файл proto для створення файлу шаблону, який ви можете використовувати для написання коду сервера gRPC.

KMS v1

  • Використовуючи Go: Використовуйте функції та структури даних у файлі шаблону: api.pb.go для написання коду сервера gRPC.

  • Використовуючи інших мов програмування: Використовуйте компілятор protoc з файлом proto: api.proto для генерації файлу шаблону для конкретної мови програмування.

KMS v2

  • Використовуючи Go: Надається високорівнева бібліотека для спрощення процесу. Низькорівневі реалізації можуть використовувати функції та структури даних у файлі шаблону: api.pb.go для написання коду сервера gRPC.

  • Використовуючи інших мов програмування: Використовуйте компілятор protoc з файлом proto: api.proto для генерації файлу шаблону для конкретної мови програмування.

Потім використовуйте функції та структури даних у файлі шаблону для написання коду сервера.

Примітки

KMS v1
  • Версія втулка kms: v1beta1

    У відповідь на виклик процедури Version сумісний втулок KMS повинен повернути v1beta1 як VersionResponse.version.

  • Версія повідомлення: v1beta1

    Усі повідомлення від постачальника KMS мають поле версії встановлене на v1beta1.

  • Протокол: UNIX доменний сокет (unix)

    Втулок реалізований як сервер gRPC, який слухає UNIX доменний сокет. Розгортання втулка повинно створити файл у файловій системі для запуску зʼєднання gRPC unix domain socket. API-сервер (клієнт gRPC) налаштований на постачальника KMS (сервер gRPC) за допомогою точки доступу UNIX доменного сокета для звʼязку з ним. Може використовуватися абстрактний Linux сокет, точка доступу якого починається з /@, наприклад, unix:///@foo. Слід бути обережним при використанні цього типу сокета, оскільки вони не мають концепції ACL (на відміну від традиційних файлових сокетів). Однак вони підпадають під простір імен мережі Linux, тому будуть доступні лише контейнерам у тому ж самому Podʼі, якщо не використовується мережа хосту.

KMS v2
  • Версія втулка KMS: v2

    У відповідь на віддалений виклик процедури Status сумісний втулок KMS повинен повернути свою версію сумісності KMS як StatusResponse.version. У цій відповіді на статус також повинен бути включений "ok" як StatusResponse.healthz і key_id (ідентифікатор KEK віддаленого KMS) як StatusResponse.key_id. Проєкт Kubernetes рекомендує зробити ваш втулок сумісним зі стабільним v2 API KMS. Kubernetes 1.30 також підтримує v2beta1 API для KMS; майбутні релізи Kubernetes, швидше за все, будуть продовжувати підтримувати цю бета-версію.

    API-сервер надсилає віддалений виклик процедури Status приблизно кожну хвилину, коли все в справному стані, і кожні 10 секунд, коли втулок не справний. Втулки повинні пильнувати за оптимізацією цього виклику, оскільки він буде під постійним навантаженням.

  • Шифрування

    Виклик процедури EncryptRequest надає текст для шифрування та UID для цілей логування. У відповіді повинен бути включений шифротекст, key_id для використаного KEK та, опціонально, будь-які метадані, які потрібні втулку KMS для допомоги в майбутніх викликах DecryptRequest (через поле annotations). Втулок повинен гарантувати, що будь-який різний текст призводить до різної відповіді (шифротекст, key_id, annotations).

    Якщо втулок повертає непорожній масив annotations, всі ключі масиву повинні бути повністю кваліфікованими доменними іменами, такими як example.com. Приклад використання annotations — {"kms.example.io/remote-kms-auditid":"<audit ID використаний віддаленим KMS>"}

    API-сервер не виконує виклик процедури EncryptRequest на високому рівні. Реалізації втулків повинні все ж старатися, щоб зберегти час очікування кожного запиту менше 100 мілісекунд.

  • Розшифрування

    Виклик процедури DecryptRequest надає (ciphertext, key_id, annotations) з EncryptRequest та UID для цілей логування. Як і очікується, це протилежне виклику EncryptRequest. Втулки повинні перевірити, що key_id є тим, що вони розуміють — вони не повинні намагатися розшифрувати дані, якщо вони не впевнені, що вони були зашифровані ними раніше.

    API-сервер може виконати тисячі викликів процедури DecryptRequest під час запуску для заповнення свого кешу перегляду. Таким чином, реалізації втулків повинні виконати ці виклики якнайшвидше, і повинні старатися зберегти час очікування кожного запиту менше 10 мілісекунд.

  • Розуміння key_id та Ротації ключа

    key_id є публічним, незасекреченим імʼям віддаленого KEK KMS, який в цей момент використовується. Він може бути зареєстрований під час регулярної роботи API-сервера та, отже, не повинен містити ніяких приватних даних. Реалізації втулків повинні використовувати хеш, щоб уникнути витоку будь-яких даних. Метрики KMS v2 пильнують за хешуванням цього значення перед показом його через точку доступу /metrics.

    API-сервер вважає, що key_id, отриманий з виклику процедури Status, є авторитетним. Отже, зміна цього значення сигналізує API-серверу, що віддалений KEK змінився, і дані, зашифровані старим KEK, повинні бути позначені як застарілі при виконанні операція запису без операції (як описано нижче). Якщо виклик процедури EncryptRequest повертає key_id, який відрізняється від Status, відповідь відкидається, і втулок вважається несправним. Таким чином, реалізації повинні гарантувати, що key_id, що повертається зі Status, буде таким самим, як той, що повертається з EncryptRequest. Крім того, втулки повинні забезпечити стабільність key_id і не допускати перемикання між значеннями (тобто під час ротації віддаленого KEK).

    Втулки не повинні повторно використовувати key_id, навіть у ситуаціях, коли раніше використаний віддалений KEK був відновлений. Наприклад, якщо втулок використовував key_id=A, перемикнувся на key_id=B, а потім повернувся до key_id=A — замість того, щоб повідомити key_id=A, втулок повинен повідомити якесь похідне значення, таке як key_id=A_001 або використовувати нове значення, наприклад key_id=C.

    Оскільки API-сервер опитує Status приблизно кожну хвилину, ротація key_id не є миттєвою. Крім того, API-сервер буде користуватися останнім дійсним станом протягом приблизно трьох хвилин. Таким чином, якщо користувач хоче здійснити пасивний підхід до міграції зберігання (тобто, чекаючи), він повинен запланувати міграцію на 3 + N + M хвилин після ротації віддаленого KEK (N — це час, необхідний для того, щоб втулок помітив зміну key_id, і M — бажаний буфер, щоб дозволити обробку змін конфігурації, рекомендується мінімальне значення M в пʼять хвилин). Зазначте, що для виконання ротації KEK перезапуск API-сервера не потрібен.

  • Протокол: UNIX доменний сокет (unix)

    Втулок реалізований як сервер gRPC, який слухає UNIX доменний сокет. Розгортання втулка повинно створити файл у файловій системі для запуску зʼєднання gRPC unix domain socket. API-сервер (клієнт gRPC) налаштований на постачальника KMS (сервер gRPC) за допомогою точки доступу UNIX доменного сокета для звʼязку з ним. Може використовуватися абстрактний Linux сокет, точка доступу якого починається з /@, наприклад, unix:///@foo. Слід бути обережним при використанні цього типу сокета, оскільки вони не мають концепції ACL (на відміну від традиційних файлових сокетів). Однак вони підпадають під простір імен мережі Linux, тому будуть доступні лише контейнерам у тому ж самому Podʼі, якщо не використовується мережа хосту.

Інтеграція втулка KMS з віддаленим KMS

Втулок KMS може спілкуватися з віддаленим KMS за допомогою будь-якого протоколу, який підтримується KMS. Усі дані конфігурації, включаючи облікові дані автентифікації, які використовує втулок KMS для спілкування з віддаленим KMS, зберігаються і керуються втулком KMS незалежно. Втулок KMS може кодувати шифротекст з додатковими метаданими, які можуть бути потрібні перед відправленням його в KMS для розшифрування (KMS v2 робить цей процес простішим, надаючи спеціальне поле annotations).

Розгортання втулка KMS

Переконайтеся, що втулок KMS працює на тих самих хостах, що і сервер(и) API Kubernetes.

Шифрування даних за допомогою постачальника KMS

Для шифрування даних виконайте наступні кроки:

  1. Створіть новий файл EncryptionConfiguration, використовуючи відповідні властивості для постачальника kms, щоб шифрувати ресурси, такі як Secrets та ConfigMaps. Якщо ви хочете зашифрувати розширення API, яке визначено у визначенні CustomResourceDefinition, ваш кластер повинен працювати на Kubernetes v1.26 або новіше.

  2. Встановіть прапорець --encryption-provider-config на kube-apiserver, щоб вказати місце розташування файлу конфігурації.

  3. Аргумент --encryption-provider-config-automatic-reload типу boolean визначає, чи слід автоматично перезавантажувати файл, встановлений за допомогою --encryption-provider-config, у разі зміни вмісту на диску.

  4. Перезапустіть свій API-сервер.

KMS v1

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      - configmaps
      - pandas.awesome.bears.example
    providers:
      - kms:
          name: myKmsPluginFoo
          endpoint: unix:///tmp/socketfile-foo.sock
          cachesize: 100
          timeout: 3s
      - kms:
          name: myKmsPluginBar
          endpoint: unix:///tmp/socketfile-bar.sock
          cachesize: 100
          timeout: 3s

KMS v2

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      - configmaps
      - pandas.awesome.bears.example
    providers:
      - kms:
          apiVersion: v2
          name: myKmsPluginFoo
          endpoint: unix:///tmp/socketfile-foo.sock
          timeout: 3s
      - kms:
          apiVersion: v2
          name: myKmsPluginBar
          endpoint: unix:///tmp/socketfile-bar.sock
          timeout: 3s

Встановлення --encryption-provider-config-automatic-reload в true обʼєднує всі перевірки стану в одну точку доступу перевірки стану. Індивідуальні перевірки стану доступні тільки тоді, коли використовуються постачальники KMS v1 і конфігурація шифрування не перезавантажується автоматично.

Наступна таблиця містить підсумки точок доступу перевірки стану для кожної версії KMS:

Конфігурації KMSБез автоматичного перезавантаженняЗ автоматичним перезавантаженням
Тільки KMS v1Індивідуальні перевіркиОдна перевірка
Тільки KMS v2Одна перевіркаОдна перевірка
KMS v1 та KMS v2Індивідуальні перевіркиОдна перевірка
Без KMSНемаєОдна перевірка

Одна перевірка означає, що єдиною точкою доступу перевірки стану є /healthz/kms-providers.

Індивідуальні перевірки означає, що для кожного втулка KMS є асоційована точка доступу перевірки стану на основі його місця в конфігурації шифрування: /healthz/kms-provider-0, /healthz/kms-provider-1 тощо.

Ці шляхи точок доступу перевірки стану жорстко закодовані та генеруються/контролюються сервером. Індекси для індивідуальних перевірок відповідають порядку, у якому обробляється конфігурація шифрування KMS.

До виконання кроків, визначених у Забезпечення шифрування всіх секретів, список providers повинен закінчуватися постачальником identity: {}, щоб можна було читати незашифровані дані. Після шифрування всіх ресурсів постачальника identity слід видалити, щоб запобігти обробці незашифрованих даних сервером API.

Для отримання деталей про формат EncryptionConfiguration, будь ласка, перегляньте довідник API шифрування API сервера.

Перевірка того, що дані зашифровані

Коли шифрування даних у стані спокою правильно налаштовано, ресурси шифруються під час запису. Після перезапуску вашого kube-apiserver, будь-які новостворені або оновлені Secret чи інші типи ресурсів, налаштовані в EncryptionConfiguration, мають бути зашифровані при зберіганні. Щоб перевірити, ви можете використовувати програму командного рядка etcdctl для отримання вмісту ваших секретних даних.

  1. Створіть новий Secret з назвою secret1 в просторі імен default:

    kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
    
  2. Використовуючи командний рядок etcdctl, прочитайте цей Secret з etcd:

    ETCDCTL_API=3 etcdctl get /kubernetes.io/secrets/default/secret1 [...] | hexdump -C
    

    де [...] містить додаткові аргументи для підключення до сервера etcd.

  3. Переконайтеся, що збережений Secret починається з префікса k8s:enc:kms:v1: для KMS v1 або з префікса k8s:enc:kms:v2: для KMS v2, що вказує на те, що постачальник kms зашифрував результати даних.

  4. Перевірте, що Secret правильно розшифровується при отриманні через API:

    kubectl describe secret secret1 -n default
    

    Secret повинен містити mykey: mydata.

Забезпечення шифрування всіх секретів

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

Наведена нижче команда читає всі Secret, а потім оновлює їх для застосування шифрування на сервері. У разі помилки через конфліктний запис, повторіть команду. Для більших кластерів вам може знадобитися поділити Secret за просторами імен або написати скрипт для оновлення.

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

Перехід від локального постачальника шифрування до постачальника KMS

Щоб перейти від локального постачальника шифрування до постачальника kms та перешифрувати всі секрети:

  1. Додайте постачальника kms як перший запис у файлі конфігурації, як показано в наступному прикладі.

    apiVersion: apiserver.config.k8s.io/v1
    kind: EncryptionConfiguration
    resources:
      - resources:
          - secrets
        providers:
          - kms:
              apiVersion: v2
              name: myKmsPlugin
              endpoint: unix:///tmp/socketfile.sock
          - aescbc:
              keys:
                - name: key1
                  secret: <BASE 64 ENCODED SECRET>
    
  2. Перезапустіть усі процеси kube-apiserver.

  3. Виконайте наступну команду, щоб змусити всі секрети перешифруватися за допомогою постачальника kms.

    kubectl get secrets --all-namespaces -o json | kubectl replace -f -
    

Що далі

Якщо ви більше не хочете використовувати шифрування для даних, збережених в API Kubernetes, прочитайте розшифровування даних, які вже зберігаються у спокої.

Змінено June 20, 2024 at 12:44 PM PST: Sync changest from andygol/k8s-website (36d05bc8a1)