Механизм секретов kv используется для хранения произвольных секретов в пределах хранилища Stronghold.

Имена ключей всегда должны быть строками. Если вы записываете нестроковые значения напрямую через CLI, они будут преобразованы в строки. Однако вы можете сохранить нестроковые значения, записав пары ключ/значение из JSON-файла или используя HTTP API.

Этот механизм секретов учитывает различие между операциями create и update в ACL-политиках. Также поддерживается функция patch, которая используется для выполнения частичных обновлений, в то время во время операции update выполняется полная перезапись.

Настройка

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

Механизам секретов v2 kv может быть включен с помощью команды:

d8 stronghold secrets enable -version=2 kv

Или вы можете передать kv-v2 в качестве типа механизма секретов:

d8 stronghold secrets enable kv-v2

Обновление с версии 1 на версию 2

Существующее хранилище kv версии 1 можно обновить до хранилища kv версии 2 с помощью CLI или API. Во время процесса миграции хранилище будет недоступно. Это может занять много времени, поэтому планируйте обновление заранее.

После обновления до версии 2 прежние пути, по которым можно было получить доступ к данным, больше не будут доступны. Вам нужно будет по новому настроить политики пользователей, чтобы восстановить доступ, как это описано в разделе Правила ACL. Аналогично, пользователям/приложениям необходимо будет обновить пути, по которым они взаимодействуют с данными kv после их обновления до версии 2.

Существующее хранилище kv версии 1 можно обновить до хранилища kv версии 2 с помощью команды CLI:

$ d8 stronghold kv enable-versioning secret/
Success! Tuned the secrets engine at: secret/

Правила ACL

Хранилище kv версии 2 использует API с префиксом, который отличается от API версии 1. Перед обновлением с версии 1 kv необходимо изменить правила ACL. Кроме того, различные пути в API версии 2 могут быть по-разному защищены ACL.

Пути для операций чтения и записи имеют префикс data/. Например, следующую политику для kv-v1:

path "secret/dev/team-1/*" {
  capabilities = ["create", "update", "read"]
}

Нужно заменить на:

path "secret/data/dev/team-1/*" {
  capabilities = ["create", "update", "read"]
}

Для kv-v2 существуют различные уровни удаления данных. Чтобы предоставить права на удаление последней версии ключа создайте такую политику:

path "secret/data/dev/team-1/*" {
  capabilities = ["delete"]
}

Чтобы разрешить удалять любую версию ключа:

path "secret/delete/dev/team-1/*" {
  capabilities = ["update"]
}

Чтобы разрешить восстанавливать удаленные версии:

path "secret/undelete/dev/team-1/*" {
  capabilities = ["update"]
}

Чтобы разрешить уничтожить значения ключей (без возможности восстановления):

path "secret/destroy/dev/team-1/*" {
  capabilities = ["update"]
}

Это политика, позволяющая получить список ключей:

path "secret/metadata/dev/team-1/*" {
  capabilities = ["list"]
}

Политика, позволяющая просматривать метаданные ключей:

path "secret/metadata/dev/team-1/*" {
  capabilities = ["read"]
}

Разрешить навсегда удалить все версии и метаданные ключа:

path "secret/metadata/dev/team-1/*" {
  capabilities = ["delete"]
}

Поля allowed_parameters, denied_parameters и required_parameters не поддерживаются для политик, используемых с хранилищем kv версии 2. Описание этих параметров см. в разделе Политики.

Использование

После того как механизм секретов включен и у пользователя/машины есть токен Stronghold с соответствующими правами, он может взаимдействовать с секретами. Синтаксис KV-v1, похожий на путь для ссылки на секрет (secret/foo), по-прежнему можно использовать в KV-v2, но мы рекомендуем использовать синтаксис с флагом -mount=secret, чтобы не перепутать его с реальным путем к секрету (реальный путь - secret/data/foo).

Запись/чтение произвольных данных

Запись ключей:

$ d8 stronghold kv put -mount=secret my-secret foo=a bar=b
Key              Value
---              -----
created_time     2024-06-19T17:20:22.985303Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          1

Чтение ключей:

$ d8 stronghold kv get -mount=secret my-secret
====== Metadata ======
Key              Value
---              -----
created_time     2024-06-19T17:20:22.985303Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          1

====== Data ======
Key         Value
---         -----
foo         a
bar         b
  • Запишите другую версию, при этом предыдущая версия будет по-прежнему доступна. Опционально может быть передан флаг -cas (check-and-set) для выполнения проверки, что ключ существует . Если флаг не установлен, запись будет разрешена. Если же флаг cas установленЮ, то для того чтобы запись была успешной, его значение должно соответствовать текущуей версию секрета. Если установлено значение 0, запись будет разрешена только в том случае, если ключ не существует, так как неустановленные ключи не имеют информации о версии. Также помните, что удаление “версии” не удаляет из хранилища исформацию о версиях. Таким образом, для записи в секрет, у которого были удаленные версии, параметр cas должен соответствовать текущей версии секрета.
$ d8 stronghold kv put -mount=secret -cas=1 my-secret foo=aa bar=bb
Key              Value
---              -----
created_time     2024-06-19T17:22:23.369372Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          2

Чтение вернет самую свежую версию данных:

$ d8 stronghold kv get -mount=secret my-secret
====== Metadata ======
Key              Value
---              -----
created_time     2024-06-19T17:22:23.369372Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          2

====== Data ======
Key         Value
---         -----
foo         aa
bar         bb

С помощью команды d8 stronghold kv patch может быть выполнено частичное обновление секрета. Команда первоначально попытается выполнить HTTP-запрос PATCH, который требует наличия ACL-возможности patch. Запрос PATCH будет неудачным, если используемый токен связан с политикой, которая не содержит возможности patch. В этом случае команда выполнит чтение, локальное обновление и последующую запись, для которых требуются возможности ACL read и update. Опционально может быть передан флаг -cas для выполнения проверки, что ключ существует. Он будет использоваться только в случае начального запроса PATCH. Вариант с последовательными чтением и записью будет использовать значение version из секрета, возвращенного при чтении, для выполнения проверки cas при последующей записи.

$ d8 stronghold kv patch -mount=secret -cas=2 my-secret bar=bbb
Key              Value
---              -----
created_time     2024-06-19T17:23:49.199802Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          3

Команда d8 stronghold kv patch также поддерживает флаг -method, который можно использовать чтобы указать, какой метод использовать, patch или rw.

Выполнить обновление секрета используя patch:

$ d8 stronghold kv patch -mount=secret -method=patch -cas=2 my-secret bar=bbb
Key              Value
---              -----
created_time     2024-06-19T17:23:49.199802Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          3

Выполнить обновление, используя rw, то есть сначала прочитать значение, а потом записать новую измененную версию:

$ d8 stronghold kv patch -mount=secret -method=rw my-secret bar=bbb
Key              Value
---              -----
created_time     2024-06-19T17:23:49.199802Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          3

Чтение вернет самую новую версию, в которой были обновлены только заданные значения:

$ d8 stronghold kv get -mount=secret my-secret
====== Metadata ======
Key              Value
---              -----
created_time     2024-06-19T17:23:49.199802Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          3

====== Data ======
Key         Value
---         -----
foo         aa
bar         bbb

Предыдущие врерсии секретов можно получить используя флаг -version:

$ d8 stronghold kv get -mount=secret -version=1 my-secret
====== Metadata ======
Key              Value
---              -----
created_time     2024-06-19T17:20:22.985303Z
custom_metadata  <nil>
deletion_time    n/a
destroyed        false
version          1

====== Data ======
Key         Value
---         -----
foo         a
bar         b

Также вы можете использовать [политику генерации паролей] чтобы создавать секреты.

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

$ d8 stronghold write sys/policies/password/example policy=-<<EOF

  length=20

  rule "charset" {
    charset = "abcdefghij0123456789"
    min-chars = 1
  }

  rule "charset" {
    charset = "!@#$%^&*STUVWXYZ"
    min-chars = 1
  }

EOF

Создать секрет, используя политику example:

$ d8 stronghold kv put -mount=secret my-generated-secret \
    password=$(d8 stronghold read -field password sys/policies/password/example/generate)
========= Secret Path =========
secret/data/my-generated-secret

======= Metadata =======
Key                Value
---                -----
created_time       2024-06-10T14:32:32.37354939Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

Прочитать созданный секрет:

$ d8 stronghold kv get -mount=secret my-generated-secret
========= Secret Path =========
secret/data/my-generated-secret

======= Metadata =======
Key                Value
---                -----
created_time       2024-06-10T14:32:32.37354939Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

====== Data ======
Key         Value
---         -----
password    !hh&be1e4j16dVc0ggae

Удаление (delete) и уничтожение (destroy) секретов

При удалении команда d8 stronghold kv delete будет выполнять «мягкое» удаление. Она пометит версию как удаленную и заполнит значение deletion_time в метаданных секрета. Мягкое удаление не удаляет данные версии из хранилища, и секрет можно восстановить с помощью команды d8 stronghold kv undelete.

Версия секрета удаляется навсегда только в том случае, если секрета имеет больше версий, чем разрешено настройкой max-versions, или при использовании команды d8 stronghold kv destroy. При использовании команды destroy данные версии будут удалены, а метаданные будут помечены как уничтоженные. Если версия очищена из-за превышения количества версий, метаданные версии также будут удалены.

Примеры:

Последняя версия ключа может быть удалена с помощью команды delete, которая также принимает флаг -versions для удаления предыдущих версий:

 $ d8 stronghold kv delete -mount=secret my-secret
 Success! Data deleted (if it existed) at: secret/data/my-secret

Версии могут быть восстановлены:

 $ d8 stronghold kv undelete -mount=secret -versions=2 my-secret
 Success! Data written to: secret/undelete/my-secret

 $ d8 stronghold kv get -mount=secret my-secret
 ====== Metadata ======
 Key              Value
 ---              -----
 created_time     2024-06-19T17:23:21.834403Z
 custom_metadata  <nil>
 deletion_time    n/a
 destroyed        false
 version          2

 ====== Data ======
 Key         Value
 ---         -----
 my-value    short-lived-s3cr3t

Уничтожение версии полностью удаляет все данные:

$ d8 stronghold kv destroy -mount=secret -versions=2 my-secret
Success! Data written to: secret/destroy/my-secret

Метаданные

Все версии и метаданные ключа можно посмотеть с помощью команды metadata или с помощью API. Удаление ключа metadata приведет к тому, что все метаданные и версии для этого ключа будут удалены навсегда.

Примеры:

Можно просмотреть все метаданные и версии для ключа:

$ d8 stronghold kv metadata get -mount=secret my-secret
========== Metadata ==========
Key                     Value
---                     -----
cas_required            false
created_time            2024-06-19T17:20:22.985303Z
current_version         2
custom_metadata         <nil>
delete_version_after    0s
max_versions            0
oldest_version          0
updated_time            2024-06-19T17:22:23.369372Z

====== Version 1 ======
Key              Value
---              -----
created_time     2024-06-19T17:20:22.985303Z
deletion_time    n/a
destroyed        false

====== Version 2 ======
Key              Value
---              -----
created_time     2024-06-19T17:22:23.369372Z
deletion_time    n/a
destroyed        true

Можно настроить параметры:

$ d8 stronghold kv metadata put -mount=secret -max-versions 2 -delete-version-after="3h25m19s" my-secret
Success! Data written to: secret/metadata/my-secret

Настройка delete-version-after будет применяться только к новым версиям, параметр max-versions будет применен при следующей операции записи.

$ d8 stronghold kv put -mount=secret my-secret my-value=newer-s3cr3t
Key              Value
---              -----
created_time     2024-06-19T17:31:16.662563Z
custom_metadata  <nil>
deletion_time    2024-06-19T20:56:35.662563Z
destroyed        false
version          4

Если у ключа больше версий, чем max-versionsб самые старые версии уничтожаются:

$ d8 stronghold kv metadata get -mount=secret my-secret
========== Metadata ==========
Key                     Value
---                     -----
cas_required            false
created_time            2024-06-19T17:20:22.985303Z
current_version         4
custom_metadata         <nil>
delete_version_after    3h25m19s
max_versions            2
oldest_version          3
updated_time            2024-06-19T17:31:16.662563Z

====== Version 3 ======
Key              Value
---              -----
created_time     2024-06-19T17:23:21.834403Z
deletion_time    n/a
destroyed        true

====== Version 4 ======
Key              Value
---              -----
created_time     2024-06-19T17:31:16.662563Z
deletion_time    2024-06-19T20:56:35.662563Z
destroyed        false

Метаданные ключа секрета могут содержать пользовательские метаданные, используемые для описания секрета, в виде пар ключ-значение. Флаг -custom-metadata можно указать несколько раз, чтобы добавить несколько пар ключ-значение.

Команда d8 stronghold kv metadata put может быть использована для полной перезаписи значения custom_metadata:

$ d8 stronghold kv metadata put -mount=secret -custom-metadata=foo=abc -custom-metadata=bar=123 my-secret
Success! Data written to: secret/metadata/my-secret

$ d8 stronghold kv get -mount=secret my-secret
====== Metadata ======
Key              Value
---              -----
created_time     2024-06-19T17:22:23.369372Z
custom_metadata  map[bar:123 foo:abc]
deletion_time    n/a
destroyed        false
version          2

====== Data ======
Key         Value
---         -----
foo         aa
bar         bb

Команда d8 stronghold kv metadata patch может быть использована для частичной перезаписи значения custom_metadata. Следующий вызов обновит поле custom_metadata foo, но оставит bar нетронутым:

$ d8 stronghold kv metadata patch -mount=secret -custom-metadata=foo=def my-secret
Success! Data written to: secret/metadata/my-secret
$ d8 stronghold kv get -mount=secret my-secret
====== Metadata ======
Key              Value
---              -----
created_time     2024-06-19T17:22:23.369372Z
custom_metadata  map[bar:123 foo:def]
deletion_time    n/a
destroyed        false
version          2

====== Data ======
Key         Value
---         -----
foo         aa
bar         bb

Полное уничтожение всех метаданных и версий для ключа:

$ d8 stronghold kv metadata delete -mount=secret my-secret
Success! Data deleted (if it existed) at: secret/metadata/my-secret