Spec-Zone.ru › Ansible

Переход с lookup hashi_vault

Это руководство по переходу с hashi_vault плагина lookup на более новые компоненты этой коллекции.

Чтобы понять причины, см. эту страницу, где описана история плагина и его будущее.

  • Примечание о lookup-плагинах и модулях
  • Общие изменения

    • Параметры: прямое указание и строка term
    • Обращение к ключам
    • Формат возвращаемых данных
  • Чтение из Vault KV

    • Структура ответа KV1 и KV2
    • Пути API KV1 и KV2
    • Версии секретов KV2
    • Замена операций получения данных KV
    • Примеры
  • Общее чтение (не KV)

Примечание о lookup-плагинах и модулях

Поскольку плагин hashi_vault является lookup-плагином, обычно проще всего заменить его другими lookup-плагинами. Ранее варианта с модулем не было, но теперь он доступен.

Хотя это может потребовать дополнительных усилий, рассмотрите каждый сценарий использования и определите, не будет ли модуль более подходящим вариантом.

Дополнительные сведения см. в руководстве по lookup-плагинам.

Общие изменения

В этом разделе рассматриваются некоторые общие различия, не связанные с конкретными сценариями.

Параметры: прямое указание и строка term

Долгое время lookup-плагин hashi_vault принимал все параметры в виде строк name=value внутри строки term, поэтому для выполнения lookup использовалась одна строка, например secret/data/path auth_method=userpass username=my_user password=somepass.

Такой способ передачи параметров не рекомендуется. Плагин hashi_vault был обновлён (ещё до появления этой коллекции), чтобы принимать параметры в виде отдельных именованных аргументов. Способ со строкой term сохранили для обратной совместимости.

Примечание

Другие lookup-плагины этой коллекции не поддерживают старый синтаксис строк term, поэтому настоятельно рекомендуется перейти на прямое указание параметров.

Если в существующих lookup-плагинах параметры указаны в строке term, возможно, прежде чем менять плагин, стоит сначала перейти на прямое указание параметров, особенно если вы планируете и дальше использовать lookup-плагины вместо модулей.

Примеры использования строк term:

- name: Term string style
  vars:
    user: my_user
    pass: '{{ my_secret_password }}'
    mount: secret
    relpath: path
  ansible.builtin.debug:
    msg:
      - "Static: {{ lookup('community.hashi_vault.hashi_vault', 'secret/data/path auth_method=userpass username=my_user password=somepass') }}"
      - "Variables: {{ lookup('community.hashi_vault.hashi_vault', mount ~ '/data/' ~ path ~ ' auth_method=userpass username=' ~ user ~ ' password=' ~ pass) }}"
      #                                          note these necessary but easy to miss spaces ^                                          ^

Те же lookup-плагины с прямым указанием параметров:

- name: Direct option style
  vars:
    user: my_user
    pass: '{{ my_secret_password }}'
    mount: secret
    relpath: path
  ansible.builtin.debug:
    msg:
      - "Static: {{ lookup('community.hashi_vault.hashi_vault', 'secret/data/path', auth_method='userpass', username='my_user', password='somepass') }}"
      - "Variables: {{ lookup('community.hashi_vault.hashi_vault', mount ~ '/data/' ~ path, auth_method='userpass', username=user, password=pass) }}"

Обращение к ключам

В этих примерах предполагается, что наш словарь результата имеет следующую структуру:

key_1: value1
'key-2': 2
'key three': three

hashi_vault также поддерживал синтаксис обращения к элементам словаря с двоеточием :, поэтому часто можно было встретить такой вариант:

- ansible.builtin.debug:
    msg:
      - "KV1 (key1): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret:key_1') }}"
      - "KV2 (key1): {{ lookup('community.hashi_vault.hashi_vault', 'kv2_mount/data/path/to/secret:key_1') }}"

При использовании приведённого выше синтаксиса возвращается только значение key_1. Обратите внимание, что key three нельзя было получить таким способом, поскольку пробел использовался как разделитель параметров строки term.

Примечание

Синтаксис с двоеточием : не поддерживается другими lookup-плагинами коллекции, и его использование не рекомендуется.

Использование двоеточия : не связано с фильтрацией на стороне сервера или другими оптимизациями, поэтому, кроме компактности синтаксиса, преимуществ у него нет.

Синтаксис с двоеточием : всегда можно было заменить прямым обращением в шаблоне Jinja2. Прямое обращение можно выполнить с помощью синтаксиса Jinja2 с точкой . (у которого есть ограничения на имена ключей) или квадратных скобок [], например (версия KV не имеет значения):

- vars:
    k1: key_1
    k2: key-2
    k3: key three
  ansible.builtin.debug:
    msg:
      - "KV1 (key1, dot): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret').key_1 }}"
      - "KV1 (key1, [ ]): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret')['key_1'] }}"
      - "KV1 (var1, [ ]): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret')[k1] }}"
      - "KV1 (key2, [ ]): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret')['key-2'] }}"
      - "KV1 (var2, [ ]): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret')[k2] }}"
      - "KV1 (key3, [ ]): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret')['key three'] }}"
      - "KV1 (var3, [ ]): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret')[k3] }}"

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

Кроме того, синтаксис с двоеточием : побуждал выполнять несколько lookup-запросов к одному секрету только для получения разных ключей, что приводило к нескольким одинаковым запросам к Vault. Приведённый выше пример также страдает от этой проблемы.

Более лаконичный вариант может выглядеть так:

- vars:
    secret: "{{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret') }}"
    k1: key_1
    k2: key-2
    k3: key three
  ansible.builtin.debug:
    msg:
      - "KV1 (key1, dot): {{ secret.key_1 }}"
      - "KV1 (key1, [ ]): {{ secret['key_1'] }}"
      - "KV1 (var1, [ ]): {{ secret[k1] }}"
      - "KV1 (key2, [ ]): {{ secret['key-2'] }}"
      - "KV1 (var2, [ ]): {{ secret[k2] }}"
      - "KV1 (key3, [ ]): {{ secret['key three'] }}"
      - "KV1 (var3, [ ]): {{ secret[k3] }}"

С точки зрения читаемости этот вариант выглядит намного лучше, но на самом деле он работает точно так же: новый запрос выполняется при каждой ссылке на secret. Это связано с ленивым вычислением шаблонов в Ansible и подробнее рассматривается в руководстве по lookup-плагинам. Эту проблему можно решить, используя ansible.builtin.set_fact для задания переменной secret или выполнив чтение с помощью модуля.

Если вы широко используете синтаксис с двоеточием :, рекомендуется обновить его до перехода на другие плагины.

Формат возвращаемых данных

Примечание

Параметр return_format не будет поддерживаться другими плагинами. Если вы используете его сейчас, рекомендуется заменить его средствами Jinja2.

Lookup-плагин hashi_vault принимает параметр return_format, значение по умолчанию которого — dict. Lookup-плагин всегда ищет поле data (подробнее см. сведения об ответе KV), и именно оно возвращается по умолчанию.

Значение raw параметра return_format возвращает необработанный ответ API на запрос. Например, это можно использовать для получения метаданных из запроса KV2, которые обычно удаляются. Также этот режим можно использовать для чтения по пути, не относящемуся к KV, если ответ имеет структуру, похожую на ответ KV (с одной или несколькими структурами data), и поэтому интерпретируется как ответ KV.

Для чтения путей, не относящихся к KV, доступны другие варианты.

Сведения о доступе к метаданным KV2 см. в разделе о замене операций KV.

Параметру return_format также можно задать значение values, чтобы возвращать список значений словаря.

Это можно заменить средствами Jinja2. Снова используем наш пример секрета:

key_1: value1
'key-2': 2
'key three': three

Рассмотрим варианты использования с return_format:

# show a list of values, ['value1', 2, 'three']
- ansible.builtin.debug:
    msg:
      - "KV1: {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret', return_format='values') }}"

# run debug once for each value
- ansible.builtin.debug:
    msg: "{{ item }}"
  loop: "{{ query('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret', return_format='values') }}"

То же самое можно сделать с помощью Jinja2:

# show a list of values
- ansible.builtin.debug:
    msg:
      - "KV1: {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret').values() | list }}"

# run debug once for each value
- ansible.builtin.debug:
    msg: "{{ item }}"
  loop: "{{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret').values() | list }}"

Чтение из Vault KV

Наиболее распространённый способ использования lookup-плагина hashi_vault — чтение секретов из хранилища секретов KV.

- ansible.builtin.debug:
    msg:
      - "KV1: {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret') }}"
      - "KV2: {{ lookup('community.hashi_vault.hashi_vault', 'kv2_mount/data/path/to/secret') }}"

В обоих случаях возвращается словарь пар ключ/значение из секрета без дополнительной информации из ответа API и метаданных (для KV2).

Структура ответа KV1 и KV2

Внутренний формат ответа для версий 1 и 2 хранилища KV различается.

Пример ответа KV1:

{
    "auth": null,
    "data": {
        "Key1": "val1",
        "Key2": "val2"
    },
    "lease_duration": 2764800,
    "lease_id": "",
    "renewable": false,
    "request_id": "e26a7521-e512-82f1-3998-7cc494f14e86",
    "warnings": null,
    "wrap_info": null
}

Пример ответа KV2:

{
    "auth": null,
    "data": {
        "data": {
            "Key1": "val1",
            "Key2": "val2"
        },
        "metadata": {
            "created_time": "2022-04-21T15:56:58.8525402Z",
            "custom_metadata": null,
            "deletion_time": "",
            "destroyed": false,
            "version": 2
        }
    },
    "lease_duration": 0,
    "lease_id": "",
    "renewable": false,
    "request_id": "15538d55-0ad9-1c39-2f4b-dcbb982f13cc",
    "warnings": null,
    "wrap_info": null
}

Lookup-плагин hashi_vault традиционно возвращал поле data из прочитанных данных. Позже плагин обновили: теперь он ищет вложенную структуру data.data и, если она найдена, возвращает только внутреннее поле data. Это позволяет всегда возвращать данные секретов KV1 и KV2 в согласованном формате, но не даёт доступа к дополнительной информации из метаданных KV2.

Пути API KV1 и KV2

В KV1 путь к секрету напрямую добавлялся к точке монтирования. Например, если движок KV1 смонтирован по пути kv/v/1 (пути монтирования могут содержать /), а секрет создан в этом хранилище по пути app/deploy_key, то полный путь будет kv/v/1/app/deploy_key.

В KV2 для данных и метаданных секрета используются отдельные пути, поэтому между точкой монтирования и путём нужно добавить компонент /data/ или /metadata/.

Например, если хранилище KV2 смонтировано по пути kv/v/2, а секрет находится по пути app/deploy_key, путь для чтения данных секрета будет kv/v/2/data/app/deploy_key. Для операций с метаданными он будет kv/v/2/metadata/app/deploy_key.

Поскольку hashi_vault выполняет общий запрос чтения к пути API, пользователям этого плагина нужно знать, что эти компоненты необходимо вставлять в путь, что часто вызывает путаницу.

Версии секретов KV2

Поскольку KV2 — это версионируемое хранилище секретов, обычно существует несколько версий одного секрета. Lookup-плагин hashi_vault не предоставлял отдельного способа получить версию, отличную от последней (используемой по умолчанию), однако в документации предлагалось добавлять ?version=2 к пути, чтобы получить версию секрета 2. Это работало, но напрямую изменяло путь API, поэтому такой вариант не считался стабильным. Выделенные компоненты KV2 в коллекции поддерживают эту возможность как полноценный параметр.

Замена операций получения данных KV

Начиная с версии коллекции 2.5.0 добавлены lookup-плагины и модули vault_kv1_get и vault_kv2_get:

  • vault_kv1_get lookup-плагин
  • vault_kv2_get lookup-плагин
  • vault_kv1_get модуль
  • vault_kv2_get модуль

Эти специализированные плагины чётко разделяют операции KV1 и KV2. Благодаря этому их поведение понятно и предсказуемо.

Что касается путей API, эти плагины используют подход, принятый в большинстве клиентских библиотек Vault и рекомендованный HashiCorp: точка монтирования передаётся как параметр (engine_mount_point) отдельно от пути для чтения. Благодаря этому путь формируется корректно, и вызывающему коду не нужно вставлять /data/ для KV2.

KV-плагины больше не возвращают непосредственно секрет. Вместо этого возвращаемые значения для KV1 и KV2, как в виде модуля, так и lookup-плагина, унифицированы и обеспечивают удобный раздельный доступ к секрету, полному ответу API и другим частям ответа.

Возвращаемые значения описаны непосредственно в документации каждого плагина, в разделах о возвращаемых данных и примерах.

Примеры

Ниже приведены примеры использования KV до и после перехода.

Вернёмся к нашему примеру секрета:

key_1: value1
'key-2': 2
'key three': three

И рассмотрим несколько вариантов использования:

- name: Reading secrets with hashi_vault and colon dereferencing
  ansible.builtin.debug:
    msg:
      - "KV1 (key1): {{ lookup('community.hashi_vault.hashi_vault', 'kv1_mount/path/to/secret:key_1') }}"
      - "KV2 (key1): {{ lookup('community.hashi_vault.hashi_vault', 'kv2_mount/data/path/to/secret:key_1') }}"

- name: Replacing the above
  ansible.builtin.debug:
    msg:
      - "KV1 (key1): {{ lookup('community.hashi_vault.vault_kv1_get', 'path/to/secret', engine_mount_point='kv1_mount').secret.key_1 }}"
      - "KV2 (key1): {{ lookup('community.hashi_vault.vault_kv2_get', 'path/to/secret', engine_mount_point='kv2_mount').secret.key_1 }}"

- name: Reading secret version 7 (old)
  ansible.builtin.debug:
    msg:
      - "KV2 (v7): {{ lookup('community.hashi_vault.hashi_vault', 'kv2_mount/data/path/to/secret?version=7') }}"

- name: Reading secret version 7 (new)
  ansible.builtin.debug:
    msg:
      - "KV2 (v7): {{ lookup('community.hashi_vault.vault_kv2_get', 'path/to/secret', engine_mount_point='kv2_mount', version=7).secret }}"

- name: Reading KV2 metadata (old)
  ansible.builtin.debug:
    msg:
      - "KV2 (metadata): {{ lookup('community.hashi_vault.hashi_vault', 'kv2_mount/data/path/to/secret', return_format='raw').data.metadata }}"

- name: Reading KV2 metadata (new)
  ansible.builtin.debug:
    msg:
      - "KV2 (metadata): {{ lookup('community.hashi_vault.vault_kv2_get', 'path/to/secret', engine_mount_point='kv2_mount').metadata }}"

Общее чтение (не KV)

Поскольку lookup-плагин hashi_vault выполняет общий запрос чтения, его можно использовать для чтения других путей, не относящихся к KV, например для чтения из cubbyhole или получения идентификатора роли AppRole.

В будущем ожидается появление компонентов для более специализированных задач, например плагинов для получения идентификатора роли. Для задач, которые пока не охвачены, доступны lookup-плагин и модуль vault_read:

  • vault_read lookup-плагин
  • vault_read модуль

Они всегда выполняют прямое чтение и возвращают необработанный результат, не пытаясь дополнительно интерпретировать ответ. Примеры см. в документации к ним.

© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/collections/community/hashi_vault/docsite/migration_hashi_vault_lookup.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API