Поддержка типизированных engines в HashiCorp для секретов компонента Deploy tools (CDJE) и приложений#

Секреты CDJE и приложений могут храниться в типизированных engines начиная с версии CDJE 1.7.

Для секретов CDJE в файле pipeline_vault.conf#

Все секреты из хранилища с KV engine могут быть перенесены в хранилище с KV2 engine. Для этого в часть с расположением секрета нужно добавить инфикс /data/. Инфикс добавляется после корневого каталога хранилища, перед дочерними путями внутри хранилища.

Пример для KV:

{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathCommon = lookup('custom_vars', 'global.hashicorp.opsPathCommon') %}

{% set secmanUserPassCreds = lookup('community.hashi_vault.hashi_vault', opsPathCommon  + 'user_pass_tech',namespace=namespace_id, token=lookup('vars',credId)) %}

maven_username={{ secmanUserPassCreds['secretUsername'] }}
maven_password={{ secmanUserPassCreds['secretPassword'] }}

git_username={{ secmanUserPassCreds['secretUsername'] }}
git_password={{ secmanUserPassCreds['secretPassword'] }}

Пример для KV 2:

{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathCommon = lookup('custom_vars', 'global.hashicorp.opsPathCommon') %}

{% set secmanUserPassCreds = lookup('community.hashi_vault.hashi_vault', opsPathCommon + '/data/' + 'user_pass_tech',namespace=namespace_id, token=lookup('vars',credId)) %}

maven_username={{ secmanUserPassCreds['secretUsername'] }}
maven_password={{ secmanUserPassCreds['secretPassword'] }}

git_username={{ secmanUserPassCreds['secretUsername'] }}
git_password={{ secmanUserPassCreds['secretPassword'] }}

Для секретов типа «Сертификат» возможно использование хранилищ с PKI engine.

Для этого необходимо:

  • задать расположение секрета — указать корневой путь к целевому engine;

  • задать параметры сертификата;

  • обработать ответ от hashicopr : private_key, ca_chain, certificate;

Пример для KV:

{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathCommon = lookup('custom_vars', 'global.hashicorp.opsPathCommon') %}


{% set secmanGatewayClientCer = lookup('community.hashi_vault.hashi_vault', opsPathCommon  + 'gateway_client_cer',namespace='', token=lookup('vars',credId)) %}
gateway_client_cer={{ secmanGatewayClientCer['secretFileBase64'] | b64decode | b64encode }}

{% set secmanGatewayClientKey = lookup('community.hashi_vault.hashi_vault', opsPathCommon  + 'gateway_client_key',namespace='', token=lookup('vars',credId)) %}
gateway_client_key={{ secmanGatewayClientKey['secretFileBase64'] | b64decode | b64encode}}

{% set secmanGatewayClientKeystore = lookup('community.hashi_vault.hashi_vault', opsPathCommon  + 'gateway_client_keystore',namespace='', token=lookup('vars',credId)) %}
gateway_client_keystore={{ secmanGatewayClientKeystore['secretFileBase64'] | b64decode | b64encode }}

Пример для PKI:

{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathCommon = lookup('custom_vars', 'global.hashicorp.opsPathCommon') %}
{% set credId_infra = lookup('custom_vars','global.hashicorp.infraHashiCorpCred') %}

#  формируем параметры сертификата
{% set data = {
   'common_name': "sample1.dot.solution.sbt",
   'email': "Nigmatulin.Y.A@sbertech.ru",
   'format': "pem",
   'private_key_format': "pem",
   'alt_names': "dot.solution.sbt"
  }
%}
 
## Запрос в HashiCorp 
{% set gatewayClient = lookup('community.hashi_vault.vault_write','PKI/fetch/role-ga-secman-run4c-deploy', namespace=namespace_id,token=lookup('vars', credId_infra),data=data).data  %}
# обработка запроса и запись значения в параметры CDJE 
gateway_client_cer="{{ gatewayClient['certificate'] | b64encode  }}"
gateway_client_key="{{ gatewayClient['private_key'] | b64encode }}"
gateway_client_keystore="{{ gatewayClient['ca_chain'] | b64encode }}"

Для секретов приложений#

Пример для KV в файле environment_vault.conf:

{%- macro print(secret, token) -%}
{% if lookup('env', 'HASHI_VAULT_DEBUG') == 'true' %}
{{ lookup('pipe', 'echo \033[32m Обработка секрета path=' + secret + ' token=' + token + '  \033[0m > /dev/stderr') }}
{% endif %}
{%- endmacro -%}

# Объявление переменных для удобства 
{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathPasswordsConfKV_1 = lookup('custom_vars', 'global.hashicorp.opsPathPasswordsConfKV_1') %}


{{ lookup('pipe', 'echo \033[34m Адрес hashicorp: ' + lookup('env','VAULT_ADDR') + ' \033[0m > /dev/stderr') }}

{{ lookup('pipe', 'echo \033[32m Обрабатывается секрет в kv1 engine  \033[0m > /dev/stderr') }}
{{ lookup('pipe', 'echo \033[32m Обработка секрета path=' + opsPathPasswordsConfKV_1 + ' namespace=' + namespace_id + ' token=' + credId + '  \033[0m > /dev/stderr') }}
{% for secret_entry in lookup('community.hashi_vault.hashi_vault_list', 'path=' + opsPathPasswordsConfKV_1, namespace='',token=lookup('custom_vars', credId)).split(',') %}
{% if not secret_entry.endswith('/') %}
{{ print( opsPathPasswordsConfKV_1 + ':' + secret_entry,credId) }}
{% set results=lookup('community.hashi_vault.hashi_vault', 'secret=' + opsPathPasswordsConfKV_1 + secret_entry, namespace='',token=lookup('custom_vars', credId)) %}
{% for key, value in results.items() %}
{{ key }}={{ value }}
{% endfor %}
{% endif %}
{% endfor %}

{% endif %}

Пример для KV2:

{%- macro print(secret, token) -%}
{% if lookup('env', 'HASHI_VAULT_DEBUG') == 'true' %}
{{ lookup('pipe', 'echo \033[32m Обработка секрета path=' + secret + ' token=' + token + '  \033[0m > /dev/stderr') }}
{% endif %}
{%- endmacro -%}

# Объявление переменных для удобства 
{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathPasswordsConfKV_2 = lookup('custom_vars', 'global.hashicorp.opsPathPasswordsConfKV_2') %}
## где global.hashicorp.opsPathPasswordsConfKV_2=/<путь до хранилища kv2>/KV2 задан в _global.hashicorp.conf 


{{ lookup('pipe', 'echo \033[32m Обрабатывается секрет в kv2 engine  \033[0m > /dev/stderr') }}
{% for secret_entry in lookup('community.hashi_vault.hashi_vault_list', 'path=' + opsPathPasswordsConfKV_2, namespace=namespace_id,token=lookup('custom_vars', credId)).split(',') %}
{% if not secret_entry.endswith('/') %}
{{ print(secret_entry,credId) }}
{% set results=lookup('community.hashi_vault.hashi_vault', 'secret=' + opsPathPasswordsConfKV_2 +'/data/' + secret_entry, namespace=namespace_id,token=lookup('custom_vars', credId)) %}
{% for key, value in results.items() %}
{{ print(opsPathPasswordsConfKV_2 + '/' + secret_entry ,credId) }}
{{ key }}={{ value }}
{% endfor %}
{% endif %}
{% endfor %}

Для получения списка секретов в подкаталоге нужно использовать плагин community.hashi_vault.hashi_vault, добавив в запрос инфикс /metadata/ и параметр list=true в конце. Инфикс добавляется после корневого каталога хранилища, перед дочерними путями внутри хранилища:

{%- macro print(secret, token) -%}
{% if lookup('env', 'HASHI_VAULT_DEBUG') == 'true' %}
{{ lookup('pipe', 'echo \033[32m Обработка секрета path=' + secret + ' token=' + token + '  \033[0m > /dev/stderr') }}
{% endif %}
{%- endmacro -%}

# Объявление переменных для удобства 
{% set namespace_id = lookup('custom_vars', 'global.hashicorp.opsPathCommon').split('/')[1] %}
{% set credId = lookup('custom_vars','global.hashicorp.opsHashiCorpCred') %}
{% set opsPathPasswordsConfKV_2 = lookup('custom_vars', 'global.hashicorp.opsPathPasswordsConfKV_2') %}
## где global.hashicorp.opsPathPasswordsConfKV_2=/<путь до хранилища kv2>/KV2 задан в _global.hashicorp.conf 


{{ lookup('pipe', 'echo \033[32m Обрабатывается секрет в kv2 engine  \033[0m > /dev/stderr') }}
{% for secret_entry in lookup('community.hashi_vault.hashi_vault', 'secret=' + opsPathPasswordsConfKV_2 + '/metadata/folder_with_secrets/?list=true', namespace=namespace_id, token=lookup('custom_vars', credId)).data.keys %}
{% if not secret_entry.endswith('/') %}
{{ print(secret_entry,credId) }}
{% set results=lookup('community.hashi_vault.hashi_vault', 'secret=' + opsPathPasswordsConfKV_2 + '/data/' + secret_entry, namespace=namespace_id,token=lookup('custom_vars', credId)) %}
{% for key, value in results.items() %}
{{ print(opsPathPasswordsConfKV_2 + '/' + secret_entry ,credId) }}
{{ key }}={{ value }}
{% endfor %}
{% endif %}
{% endfor %}