39 KiB
Obsidian Cloud KMS Encryption
Плагин для Obsidian, обеспечивающий прозрачное шифрование секретных блоков и бинарных файлов с использованием AWS KMS.
Оглавление
- Зачем
- Ключевые принципы
- Как работает
- Команды
- Использование
- Поведение
- Установка
- Настройки
- Безопасность
- Тестирование безопасности
- Воспроизводимые сборки
- Проверка целостности релизов
- On-Disk Format
- Управление доступом к ключу
- CLI-расшифровка (без Obsidian)
- Сравнение с альтернативами
- Работа с Git
- Индикатор статуса KMS
- Известные ограничения
- Development
- Лицензия
Зачем
Если вы храните Obsidian-хранилище в S3, Git или любом другом удалённом хранилище — содержимое заметок доступно любому, кто получит доступ к storage. Этот плагин реализует модель Zero Trust Storage: на диске и в remote всегда лежит только шифротекст. Расшифровка происходит локально, в памяти, только при наличии доступа к Cloud KMS.
Ключевые принципы
- Envelope Encryption — каждый блок/файл шифруется уникальным DEK (AES-256-GCM), а сам DEK оборачивается CMK в облачном KMS
- Identity-based Auth — никаких паролей; используются системные credentials (AWS SSO, IAM Role,
~/.aws/credentials) - Local-First Crypto — симметричное шифрование выполняется локально через WebCrypto API; в KMS уходит только DEK для wrap/unwrap
- Zero Cleartext on Disk — расшифрованный контент существует только в оперативной памяти процесса Obsidian
- Transparent — шифрование/расшифровка происходит автоматически при чтении/записи файлов (monkey-patch vault adapter)
- Nested Content — маркеры
%%secret-start%%/%%secret-end%%не конфликтуют с code fences, позволяя вкладыватьmermaid,js и любой другой markdown
Как работает
Markdown-файлы (секретные блоки)
Плагин перехватывает чтение и запись файлов на уровне Obsidian vault adapter:
- При записи на диск: все блоки между
%%secret-start%%и%%secret-end%%автоматически шифруются → на диске хранятся какocke-v1блок - При чтении с диска: все
ocke-v1блоки автоматически расшифровываются → в редакторе показываются между%%secret-start%%/%%secret-end%%
Бинарные файлы (PDF, изображения, аудио)
- Команда "Encrypt current file" шифрует файл на месте (имя не меняется)
- При открытии — файл расшифровывается в памяти (Blob URL), Obsidian показывает его как обычно
- На диске всегда зашифрованные байты в формате OCKE
- В file explorer зашифрованные файлы отмечены 🔒
Команды
| Команда | Описание |
|---|---|
| Wrap selection in secret block | Оборачивает выделенный текст в %%secret-start%% / %%secret-end%% |
| Unwrap secret block | Убирает маркеры шифрования, оставляя plaintext |
| Encrypt current file with AWS KMS | Шифрует бинарный файл (PDF, PNG, MP3) на месте |
| Decrypt current file with AWS KMS (permanent) | Расшифровывает бинарный файл навсегда (записывает plaintext на диск) |
Использование
Шифрование текста в заметках
- Выделите текст в заметке
Ctrl+P→ "Wrap selection in secret block"- Текст оборачивается в
%%secret-start%%/%%secret-end%%маркеры - При сохранении — автоматически шифруется на диске
Ручное создание секретного блока
Просто оберните текст в маркеры:
# Моя заметка
Это публичный текст.
%%secret-start%%
Это секретный контент — будет зашифрован при сохранении.
Пароли, токены, приватные заметки — всё что угодно.
%%secret-end%%
А это снова публичный текст.
Вложенные code fences (mermaid, code и т.д.)
Маркеры %% — это Obsidian-комментарии, невидимые в Reading view. Содержимое между ними — обычный markdown, который рендерится нормально:
%%secret-start%%
# Секретная архитектура
```mermaid
graph TD
A[Client] --> B[API Gateway]
B --> C[Lambda]
C --> D[DynamoDB]
```
```bash
export SECRET_KEY="my-super-secret-key"
aws s3 cp secret.tar.gz s3://my-bucket/
```
Пароль от продакшена: `P@ssw0rd123!`
%%secret-end%%
После сохранения весь блок (включая mermaid-диаграмму и код) будет зашифрован на диске. При открытии — расшифрован, и mermaid отрендерится как диаграмма в Reading view.
Шифрование бинарных файлов
- Откройте PDF, изображение или другой бинарный файл
Ctrl+P→ "Encrypt current file with AWS KMS"- Файл зашифрован на месте (имя не меняется, в file explorer появляется 🔒)
- При следующем открытии — расшифровывается в памяти, отображается как обычно
Для постоянной расшифровки (записать plaintext обратно на диск):
Ctrl+P→ "Decrypt current file with AWS KMS (permanent)"
Удаление шифрования текста
- Выделите весь блок (от
%%secret-start%%до%%secret-end%%) Ctrl+P→ "Unwrap secret block"- Маркеры убираются, текст остаётся как обычный markdown (больше не шифруется)
Поведение
| Ситуация | Результат |
|---|---|
Сохранение .md с %%secret-start%% блоками |
Блоки шифруются → на диске ocke-v1 блок |
Открытие .md с ocke-v1 блоками (ключ доступен) |
Расшифровываются → в редакторе %%secret-start%%...%%secret-end%% |
Открытие .md с ocke-v1 блоками (ключ НЕ доступен) |
Остаются как ocke-v1 (зашифрованный base64) |
| Открытие зашифрованного PDF/PNG (ключ доступен) | Расшифровывается в памяти → отображается нормально |
| Открытие зашифрованного PDF/PNG (ключ НЕ доступен) | Obsidian не может отрендерить файл |
| KMS недоступен при сохранении | Файл сохраняется как есть, ошибка показывается |
| Каждый блок/файл | Шифруется независимо (свой DEK) |
| File explorer | Зашифрованные бинарные файлы отмечены 🔒 |
Установка
Требования
- Obsidian ≥ 1.4.0 (desktop)
- AWS credentials настроены (
~/.aws/credentialsилиaws sso login)
Из GitHub Releases
- Перейдите в Releases
- Скачайте из последнего релиза:
main.js,manifest.json,styles.css - Создайте папку
.obsidian/plugins/cloud-kms-encryption/в вашем хранилище - Положите скачанные файлы в эту папку
- Перезапустите Obsidian → Settings → Community Plugins → включите "Cloud KMS Encryption"
Из исходников
git clone https://github.com/ViktorUJ/obsidian-cloud-kms.git
cd obsidian-cloud-kms
npm install
npm run build
Скопируйте main.js, manifest.json и styles.css в .obsidian/plugins/cloud-kms-encryption/.
Настройка AWS
-
Создайте KMS-ключ:
aws kms create-key --key-spec SYMMETRIC_DEFAULT --key-usage ENCRYPT_DECRYPT --region eu-north-1 -
Скопируйте ARN ключа (формат:
arn:aws:kms:{region}:{account}:key/{key-id}) -
В Obsidian: Settings → Cloud KMS Encryption → вставьте ARN
-
Убедитесь, что credentials доступны:
aws sts get-caller-identity
Примечание: регион извлекается из ARN автоматически — не нужно настраивать
AWS_REGION.
Настройки
| Параметр | Описание | По умолчанию |
|---|---|---|
| AWS KMS Key ARN | ARN ключа для шифрования | — |
| Auto-decrypt blocks | Автоматическая расшифровка при чтении | ✅ |
Безопасность
Подробный threat model, криптографический дизайн и ограничения описаны в SECURITY.md.
Ключевые моменты:
- Расшифрованные данные никогда не записываются на диск — adapter patch шифрует перед записью
- Бинарные файлы расшифровываются в Blob URL (RAM), не на диск
- DEK обнуляется сразу после использования
- Каждый блок/файл использует уникальный DEK + nonce
- AES-256-GCM с 96-bit nonce и 128-bit auth tag
- Encryption context привязан к vault name + file path + format version
- Все KMS-вызовы логируются в AWS CloudTrail
- LRU-кеш на 20 расшифрованных бинарных файлов (старые вытесняются из памяти)
- Никакой телеметрии, никаких внешних вызовов кроме AWS KMS
- Credentials не хранятся в плагине — используется стандартная AWS credential chain
Проверка целостности релизов
Каждый релиз криптографически подписан. Вы можете проверить что скачанные артефакты подлинные и не модифицированы:
Проверка SLSA Provenance
# Установите GitHub CLI, затем:
gh attestation verify main.js --repo ViktorUJ/obsidian-cloud-kms
Проверка подписи Cosign
# Установите cosign: https://docs.sigstore.dev/cosign/system_config/installation/
# Скачайте main.js и main.js.bundle из релиза, затем:
cosign verify-blob main.js \
--bundle main.js.bundle \
--certificate-identity-regexp "github.com/ViktorUJ/obsidian-cloud-kms" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
Если проверка успешна — файл собран в GitHub Actions этого репозитория, не модифицирован после сборки.
Проверка SBOM
Каждый релиз включает sbom.spdx.json — полный список всех зависимостей с версиями и лицензиями. Используйте для:
- Сканирования на известные уязвимости:
grype sbom.spdx.json - Проверки лицензий:
trivy sbom sbom.spdx.json
On-Disk Format
Markdown (секретные блоки)
На диске секретные блоки хранятся как:
````ocke-v1
<base64-encoded encrypted data>
````
Бинарные файлы
Файл целиком заменяется на OCKE бинарный формат:
[Magic: "OCKE" 4B][Version: uint16 BE][ProviderIdLen: 1B][ProviderId]
[CmkIdLen: uint16 BE][CmkId][WrappedDekLen: uint16 BE][WrappedDek]
[Nonce: 12B][AuthTag: 16B][CiphertextLen: uint32 BE][Ciphertext]
Сравнение с альтернативами
| Возможность | Cloud KMS Encryption | SOPS | git-crypt | Meld Encrypt | HashiCorp Vault |
|---|---|---|---|---|---|
| Шифрование at rest | ✅ | ✅ | ✅ | ✅ | ✅ |
| Без паролей | ✅ (IAM) | ✅ (IAM/PGP) | ✅ (GPG) | ❌ (пароль) | ✅ (токены) |
| Гранулярность на уровне блока | ✅ | ✅ | ❌ (весь файл) | ✅ | N/A |
| Мульти-ключ / мульти-команда | ✅ | ✅ | ✅ | ❌ | ✅ |
| Git-safe (шифротекст в репо) | ✅ | ✅ | ✅ | ✅ | N/A |
| Прозрачное редактирование | ✅ | ❌ (CLI) | ✅ | ❌ (модальное окно) | N/A |
| Шифрование бинарных файлов | ✅ | ❌ | ✅ | ❌ | N/A |
| Интеграция с Obsidian | ✅ нативная | ❌ | ❌ | ✅ нативная | ❌ |
| Аудит (CloudTrail) | ✅ | ✅ | ❌ | ❌ | ✅ |
| Внешний аудит / сертификация | ❌ | ❌ | ❌ | ❌ | ✅ |
| HSM-уровень безопасности | ❌ | ❌ | ❌ | ❌ | ✅ |
Лучшее применение:
- Cloud KMS Encryption — командные базы знаний с IAM-контролем доступа, DevOps-секреты в Obsidian
- SOPS — секреты CI/CD в YAML/JSON, GitOps-воркфлоу
- git-crypt — шифрование целых файлов в Git-репозиториях
- Meld Encrypt — личные заметки с паролем, один пользователь
- HashiCorp Vault — секреты продакшен-инфраструктуры, compliance-требования
Работа с Git
Плагин спроектирован для vault'ов, хранящихся в Git. На диске всегда только шифротекст — безопасно коммитить и пушить.
Начальная настройка
# Клонируем vault
git clone git@github.com:your-org/team-vault.git
cd team-vault
# Открываем в Obsidian, настраиваем плагин (ARN ключа)
# Убеждаемся что AWS credentials доступны:
aws sts get-caller-identity
Ежедневный workflow
# Подтягиваем изменения (на диске — шифротекст)
cd /path/to/vault
git pull
# Открываем Obsidian — плагин расшифровывает блоки прозрачно
# Редактируем заметки как обычно — секретные блоки показывают расшифрованный текст
# Закрываем Obsidian или переключаемся в терминал
# Коммитим и пушим (в Git уходит только шифротекст)
git add -A
git status # проверяем: нет plaintext в diff
git commit -m "update finance Q3 notes"
git push
Проверка что plaintext не утекает в Git
# Смотрим что реально лежит в файле на диске:
cat notes/budget.md
# Должны видеть: ocke-v1 блок с base64 — НЕ plaintext
# Проверяем diff перед коммитом:
git diff --cached
# Зашифрованные блоки показываются как base64-изменения, не читаемый текст
# Для бинарных файлов:
file attachments/report.pdf
# Должно показать: "data" (не "PDF document") — это зашифрованные байты
Онбординг нового участника команды
# Новый участник:
# 1. Клонирует vault
git clone git@github.com:your-org/team-vault.git
# 2. Настраивает AWS credentials
aws configure
# или: aws sso login --profile team
# 3. Устанавливает плагин в Obsidian, указывает тот же ARN ключа
# 4. IAM-админ выдаёт kms:Decrypt на нужный ключ(и)
# 5. Открывает vault в Obsidian — блоки, к которым есть доступ, расшифровываются
# Блоки без доступа остаются как зашифрованный base64
Разрешение конфликтов
# Если Git показывает merge conflict в зашифрованном блоке:
# НЕ пытайтесь мержить base64 вручную — это бинарные данные
# Вариант 1: Принять их или нашу версию
git checkout --theirs notes/budget.md
# или
git checkout --ours notes/budget.md
# Вариант 2: Перешифровать после разрешения в Obsidian
# 1. Принять одну версию
# 2. Открыть в Obsidian, отредактировать расшифрованный контент
# 3. Сохранить — плагин перешифрует с новым DEK
# 4. Закоммитить
Рекомендации для .gitignore
# Obsidian workspace (состояние открытых файлов, не секреты)
.obsidian/workspace.json
.obsidian/workspace-mobile.json
# Данные плагина (содержит ARN ключа — не секрет, но персональное)
.obsidian/plugins/obsidian-cloud-kms-encryption/data.json
# Никогда не игнорируйте эти файлы (это и есть зашифрованный vault):
# !*.md
# !attachments/
Pre-commit hook: защита от утечки plaintext
Если плагин был выключен, credentials истекли, или файл редактировался вне Obsidian — маркеры %%secret-start%% могут оказаться на диске незашифрованными. Pre-commit hook предотвращает случайный коммит plaintext в Git:
# Установить hook
cp tools/pre-commit-hook.sh .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Что делает:
- При каждом
git commitпроверяет все staged.mdфайлы - Если в файле найден
%%secret-start%%— блокирует коммит - Показывает какой файл содержит незашифрованный контент и как исправить
Пример вывода при обнаружении plaintext:
ERROR: Plaintext secret block found in staged file: notes/budget.md
The file contains %%secret-start%% markers which means
the encryption plugin did not encrypt before save.
Fix: Open the file in Obsidian with the plugin enabled,
save it, then stage again.
Commit blocked: plaintext secrets detected.
Это страховочная сетка — если всё работает правильно,
%%secret-start%%никогда не должен появляться на диске (adapter patch шифрует его вocke-v1блок перед записью). Hook ловит edge cases.
CLI-расшифровка (без Obsidian)
Для disaster recovery, CI/CD пайплайнов или проверки бэкапов — можно расшифровать файлы без Obsidian через CLI.
Важно: Encryption context (
vault-nameиfile-path) должен совпадать с тем, что использовался при шифровании. Vault name — это имя папки вашего Obsidian vault. File path — путь относительно корня vault (например,folder/note.md).
Вариант 1: Bash + AWS CLI + Python
Без Node.js. Требуется: aws CLI, python3, pip install cryptography.
# Расшифровать бинарный файл (PDF, изображение)
./tools/ocke-decrypt.sh report.pdf --vault-name my-vault --file-path report.pdf -o decrypted-report.pdf
# Расшифровать markdown-блоки (вывод в stdout)
./tools/ocke-decrypt.sh notes/secret.md --vault-name my-vault --file-path notes/secret.md
# Через переменные окружения
OCKE_VAULT_NAME="my-vault" OCKE_FILE_PATH="notes/secret.md" ./tools/ocke-decrypt.sh notes/secret.md -o decrypted.md
Вариант 2: Node.js CLI
Требуется: Node.js >= 18, @aws-sdk/client-kms.
# Установить зависимости (один раз)
npm install @aws-sdk/client-kms @aws-sdk/credential-provider-ini
# Расшифровать бинарный файл
node tools/ocke-decrypt.mjs report.pdf --vault-name my-vault --file-path report.pdf -o decrypted-report.pdf
# Расшифровать markdown-блоки
node tools/ocke-decrypt.mjs notes/secret.md --vault-name my-vault --file-path notes/secret.md
# Через переменные окружения
OCKE_VAULT_NAME="my-vault" OCKE_FILE_PATH="notes/secret.md" node tools/ocke-decrypt.mjs notes/secret.md -o decrypted.md
Параметры
| Параметр | Описание | Обязательный |
|---|---|---|
<file> |
Путь к зашифрованному файлу | Да |
-o <output> |
Записать результат в файл (по умолчанию: stdout) | Нет |
--vault-name |
Имя Obsidian vault (имя папки) | Да |
--file-path |
Путь файла относительно корня vault (как при шифровании) | Да |
Или через переменные окружения: OCKE_VAULT_NAME, OCKE_FILE_PATH.
Как узнать правильные значения:
vault-name— имя папки vault (например, если vault в/home/user/my-vault/, имя —my-vault)file-path— путь относительно корня vault (например,notes/secret.md,attachments/report.pdf)
Когда использовать CLI
- Disaster recovery — Obsidian недоступен, нужен доступ к зашифрованным данным
- CI/CD пайплайны — расшифровка секретов при деплое без GUI
- Проверка бэкапов — убедиться что зашифрованные бэкапы валидны
- Миграция — массовая расшифровка при переходе с плагина
Ротация ключей / Миграция (ocke-rekey)
Перешифровка всего vault новым KMS-ключом — для миграции на новый AWS-аккаунт, ротации ключей или смены региона. Перешифровывается только wrapped DEK (быстро), ciphertext не меняется.
# Установить зависимости
npm install @aws-sdk/client-kms @aws-sdk/credential-provider-ini
# Dry run — посмотреть что изменится
node tools/ocke-rekey.mjs /path/to/vault \
--new-key arn:aws:kms:eu-west-1:NEW_ACCOUNT:key/new-key-id \
--vault-name my-vault \
--dry-run
# Выполнить миграцию
node tools/ocke-rekey.mjs /path/to/vault \
--new-key arn:aws:kms:eu-west-1:NEW_ACCOUNT:key/new-key-id \
--vault-name my-vault
# Мигрировать только блоки, зашифрованные конкретным старым ключом
node tools/ocke-rekey.mjs /path/to/vault \
--new-key arn:aws:kms:eu-west-1:NEW_ACCOUNT:key/new-key-id \
--old-key arn:aws:kms:eu-north-1:OLD_ACCOUNT:key/old-key-id \
--vault-name my-vault
Требования:
- AWS credentials с
kms:Decryptна старом ключе Иkms:Encryptна новом - Оба ключа должны быть доступны одновременно во время миграции
- После миграции обновите настройки плагина с новым ARN ключа
Примечание: На Windows используйте Git Bash или WSL для корректной работы с Unicode-путями. Оба инструмента используют те же AWS credentials что и плагин (
~/.aws/credentials). ARN ключа хранится внутри зашифрованных данных — конфигурация ключа не нужна.
Индикатор статуса KMS
Плагин отображает индикатор состояния соединения в нижней панели Obsidian:
| Индикатор | Значение |
|---|---|
| 🔓 KMS | Соединение OK — шифрование/расшифровка доступны |
| 🔒 KMS ⚠️ | KMS недоступен — секретные блоки НЕ будут зашифрованы при сохранении! |
| ⏳ KMS | Проверка соединения... |
Поведение:
- Проверяет доступность KMS при загрузке плагина
- Перепроверяет каждые 5 минут в фоне
- Клик по индикатору — ручная перепроверка
- При наведении — подробный tooltip
Почему это важно:
Если KMS недоступен (проблемы с сетью, истёкшие credentials, сбой AWS), плагин не может зашифровать %%secret-start%% блоки при сохранении. Файл будет сохранён с plaintext-маркерами. Индикатор статуса даёт мгновенную видимость этого риска — если видите 🔒 ⚠️, не сохраняйте файлы с секретными блоками до восстановления связи.
Известные ограничения
Monkey-patching Vault Adapter
Плагин перехватывает vault.adapter.read() и vault.adapter.write() для обеспечения прозрачного шифрования. Это тот же подход, что использует gpgCrypt — единственный способ гарантировать zero-plaintext-on-disk без официального encryption API от Obsidian.
Потенциальные конфликты с другими плагинами:
- Если другой плагин тоже патчит
adapter.read()илиadapter.write(), два патча могут конфликтовать - Плагин корректно вызывает оригинальный метод после обработки (chaining), но порядок инициализации имеет значение
- При проблемах попробуйте отключить другие плагины, модифицирующие файловый I/O
Меры защиты:
- Патч обрабатывает только
.mdфайлы для текстового шифрования (бинарные проверяются по magic bytes) - Файлы без маркеров
%%secret-start%%или OCKE magic bytes проходят без изменений (нулевой overhead) - При выгрузке плагина оригинальные методы adapter полностью восстанавливаются
- Патч прозрачен — другие плагины, работающие с незашифрованными файлами, не затрагиваются
Если обновление Obsidian сломает плагин:
- Ваши данные в безопасности — файлы остаются зашифрованными на диске в документированном формате OCKE
- Используйте CLI-инструменты для расшифровки без Obsidian
- Плагин будет обновлён под новые internals Obsidian
Development
npm test # Запуск тестов
npm run build # Production build
npm run dev # Dev build (watch)
make ci # Full CI pipeline
Управление доступом к ключу
Мульти-ключевая архитектура
В организациях разным командам нужен доступ к разным секретам. Плагин поддерживает несколько KMS-ключей, обеспечивая гранулярный контроль доступа:
Кейс: Общий vault компании, расшаренный между командами:
- Финансовый отдел — доступ к бюджетам, зарплатам, контрактам
- R&D — доступ к патентам, исследованиям, техническим секретам
- CTO — доступ ко всему (все ключи)
Каждый секретный блок шифруется конкретным ключом. IAM-политики на стороне AWS контролируют, кто может расшифровать что. Разработчик из R&D физически не может расшифровать финансовые данные — даже если у него есть доступ к файлам vault.
Настройки плагина:
{
"keys": [
{ "alias": "finance", "arn": "arn:aws:kms:eu-north-1:790660747904:key/aaa-111" },
{ "alias": "rnd", "arn": "arn:aws:kms:eu-north-1:790660747904:key/bbb-222" },
{ "alias": "cto", "arn": "arn:aws:kms:eu-north-1:790660747904:key/ccc-333" }
],
"defaultKeyAlias": "finance"
}
В заметках — указываем алиас ключа в маркере:
%%secret-start:finance%%
Бюджет Q3: $2.4M
Зарплаты: ...
%%secret-end%%
%%secret-start:rnd%%
Патент на новый алгоритм: ...
%%secret-end%%
%%secret-start:cto%%
Root credentials продакшена: ...
%%secret-end%%
Поведение:
- При шифровании: если настроено несколько ключей — появляется picker для выбора
- При расшифровке: ARN ключа записан внутри зашифрованных данных — плагин использует его автоматически
- Если у пользователя есть IAM-доступ к ключу → блок расшифровывается
- Если нет → блок остаётся зашифрованным (graceful degradation)
- В одной заметке могут быть блоки, зашифрованные разными ключами
Настройка IAM на стороне AWS:
- Финансовый отдел → IAM-политика разрешает только
kms:Decryptнаkey/aaa-111 - R&D → IAM-политика разрешает только
kms:Decryptнаkey/bbb-222 - CTO → IAM-политика разрешает
kms:Decryptна все три ключа
Пользователь из того же AWS-аккаунта
Добавьте IAM-политику пользователю/роли:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:eu-north-1:790660747904:key/YOUR-KEY-ID"
}
]
}
aws iam put-user-policy \
--user-name colleague \
--policy-name kms-vault-access \
--policy-document file://policy.json
Для read-only доступа (только расшифровка) — уберите kms:GenerateDataKey.
Пользователь из той же AWS Organization (другой аккаунт)
Шаг 1. Обновите Key Policy на стороне владельца ключа — разрешите доступ из другого аккаунта:
{
"Sid": "AllowCrossAccountDecrypt",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "*"
}
# Получить текущую политику ключа
aws kms get-key-policy --key-id YOUR-KEY-ID --policy-name default --output text > key-policy.json
# Добавить Statement выше в key-policy.json, затем:
aws kms put-key-policy --key-id YOUR-KEY-ID --policy-name default --policy file://key-policy.json
Шаг 2. На стороне другого аккаунта (111122223333) — добавьте IAM-политику пользователю:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:eu-north-1:790660747904:key/YOUR-KEY-ID"
}
]
}
Оба условия обязательны: Key Policy разрешает аккаунт, IAM Policy разрешает пользователя.
Пользователь из сторонней организации (внешний AWS-аккаунт)
Аналогично cross-account, но с дополнительными ограничениями через Condition:
Шаг 1. Key Policy — разрешите конкретного пользователя/роль (не весь аккаунт):
{
"Sid": "AllowExternalPartnerDecrypt",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::444455556666:user/partner-user"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:EncryptionContext:vaultName": "shared-vault"
}
}
}
Рекомендации для внешних партнёров:
- Указывайте конкретный Principal (user/role ARN), не
rootаккаунта- Давайте только
kms:Decrypt(безGenerateDataKey) — только чтение- Используйте
Conditionсkms:EncryptionContextдля ограничения доступа к конкретному vault- Включите CloudTrail для аудита всех обращений к ключу
Шаг 2. Партнёр добавляет IAM-политику на своей стороне (как в cross-account выше).
Шаг 3. Партнёр настраивает плагин с тем же ARN ключа и получает доступ к расшифровке.
Проверка доступа
# От имени пользователя, которому дали доступ:
aws kms describe-key --key-id arn:aws:kms:eu-north-1:790660747904:key/YOUR-KEY-ID
# Если вернёт метаданные ключа — доступ есть
# Если AccessDeniedException — проверьте Key Policy + IAM Policy
Лицензия
MIT © Viktar Mikalayeu