如何使用 HashiCorp 的 Vault API 通过一次 API 调用从目录中获取所有秘密值

问题描述 投票:0回答:3

我正在使用 Postman 调用 Vault API。

现在我正在对此端点进行 API 调用

https://vault.something.com/v1/kv/data/ENV/DEV/secret1

我在正文中传递了 roleId 和 SecretId,在标头中传递了 X-Vault-Namespace 和 X-Vault-Token,并且我在此路径中获取了密钥的值。

我也可以通过打电话来获得所有钥匙

https://vault.something.com/v1/kv/metadata/ENV/DEV?list=true

我需要使用单个 API 调用从 ENV/DEV/ 获取所有秘密的值。你能给我一个主意吗?我被现有的文档困住了。

hashicorp-vault
3个回答
1
投票

如果可以放宽“一次API调用”的要求,那么只需按照以下两个步骤即可实现:

  1. 使用 https://vault.something.com/v1/kv/metadata/ENV/DEV?list=true列出 ENV/DEV/ 中的所有密钥并将它们放入列表中
  2. 循环遍历上面的列表,对于每个项目,调用 https://vault.something.com/v1/kv/data/ENV/DEV/ 提取所有秘密并将其存储在字典中,如secrets[] = { '键1':'值1','键2':'值2'}

1
投票

这是不可能的,Hashicorp 在这个问题上已经有一个“开放问题”四年多了,而且没有任何迹象表明会解决这个问题。 许多人已经构建了处理递归的代码,并且只需锤炼 Vault API 直到完全探索目录树即可。检查上面链接的 GitHub 问题,寻找已发布解决方案的有帮助的人。


0
投票
issue 5275:“KV 引擎:递归列出键”

Shehab El-Deen Alalkamy 提出

我有一个用例,可以导出给定路径的所有 KV 秘密并将其保存在本地的
secrets.json

文件中。我重构它以导出秘密而不是列出它们。

我的 Vault 位于 Cloudflare 零信任后面,我调整了脚本以选择性地传递 CF_TOKEN 来绕过 Cloudflare,认为人们可能会发现这对他们的用例有帮助:

#!/usr/bin/env bash # vault-kv-export.sh set -eo pipefail readonly ARB_TEMP_SECRETS_FILE="arbitrary_temp_secrets.json" readonly TEMP_SECRETS_FILE="temp_secrets.json" readonly SECRETS_FILE="secrets.json" log() { local log_type="$1" local message="$2" local timestamp timestamp=$(date +"%Y-%m-%d %H:%M:%S") echo "[$log_type] [$timestamp] $message" } log_info() { log "INFO" "$1" } log_error() { log "ERROR" "$1" exit 1 } traverse() { local path="$1" local result local headers=() if [[ -n "${CF_TOKEN}" ]]; then headers+=("-header" "cf-access-token=${CF_TOKEN}") fi result=$(vault kv list -format=json "${headers[@]}" "${path}" 2>&1) || log_error "Failed to list secrets: ${result}" while IFS= read -r secret; do if [[ "${secret}" == */ ]]; then traverse "${path}${secret}" else local secret_data secret_data=$(vault kv get -format=json "${headers[@]}" "${path}${secret}" | jq -r '.data') || log_error "Failed to get secret data: ${secret_data}" if [[ "${secret_data}" != "null" ]]; then echo "{\"path\":\"${path}${secret}\",\"value\":{\"data\":${secret_data}}}," >>"${ARB_TEMP_SECRETS_FILE}" fi fi done < <(echo "${result}" | jq -r '.[]') } main() { log_info "Starting secrets retrieval process." [[ -f "${ARB_TEMP_SECRETS_FILE}" ]] && rm -f "${ARB_TEMP_SECRETS_FILE}" [[ -f "${TEMP_SECRETS_FILE}" ]] && rm -f "${TEMP_SECRETS_FILE}" [[ -f "${SECRETS_FILE}" ]] && rm -f "${SECRETS_FILE}" if [[ -n "${CF_TOKEN}" ]]; then log_info "CF_TOKEN detected." else log_info "CF_TOKEN not provided. Headers will not be attached to Vault requests." fi local vaults if [[ "$1" ]]; then vaults=("${1%"/"}/") log_info "Retrieving all secrets under ${vaults[*]}.." else local headers=() if [[ -n "${CF_TOKEN}" ]]; then headers+=("-header" "cf-access-token=${CF_TOKEN}") fi log_info "No secret engine provided. Retrieving all secrets.." result=$(vault secrets list -format=json "${headers[@]}" 2>&1) || log_error "Failed to list secrets engines: ${result}" mapfile -t vaults < <(echo "${result}" | jq -r 'to_entries[] | select(.value.type=="kv") | .key') fi for vault in "${vaults[@]}"; do traverse "${vault}" done echo "[" >"${TEMP_SECRETS_FILE}" sed '$s/,$//' "${ARB_TEMP_SECRETS_FILE}" >>"${TEMP_SECRETS_FILE}" echo "]" >>"${TEMP_SECRETS_FILE}" jq . "${TEMP_SECRETS_FILE}" >"${SECRETS_FILE}" rm "${ARB_TEMP_SECRETS_FILE}" "${TEMP_SECRETS_FILE}" log_info "Secrets retrieval completed and saved to ${SECRETS_FILE}" } [[ "$0" == "${BASH_SOURCE[0]}" ]] && main "$@"
示例输出:

$ ./vault-kv-export.sh secret2/confluent_cloud [INFO] [2023-11-03 15:06:15] Starting secrets retrieval process. [INFO] [2023-11-03 15:06:15] CF_TOKEN detected. [INFO] [2023-11-03 15:06:15] Retrieving all secrets under secret2/confluent_cloud/.. [INFO] [2023-11-03 15:06:27] Secrets retrieval completed and saved to secrets.json

与:

$ cat secrets.json

[
  {
    "path": "secret2/confluent_cloud/global-creds",
    "value": {
      "data": {
        "data": {
          "confluent_cloud_token": "REDACTED"
        },
        "metadata": {
          "created_time": "2023-11-02T13:14:09.616943342Z",
          "custom_metadata": null,
          "deletion_time": "",
          "destroyed": false,
          "version": 1
        }
      }
    }
  },
  {
    "path": "secret2/confluent_cloud/service/credentials",
    "value": {
      "data": {
        "data": {
          "api_key": "REDACTED",
          "api_secret": "REDACTED"
        },
        "metadata": {
          "created_time": "2023-11-02T13:14:10.336792836Z",
          "custom_metadata": null,
          "deletion_time": "",
          "destroyed": false,
          "version": 1
        }
      }
    }
  },
...
© www.soinside.com 2019 - 2024. All rights reserved.