Hashicorp 金库 - 从一个金库导出密钥,导入另一个金库

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

我想从一个保管库导出密钥,然后将其导入到另一个保管库。

感觉应该有一种简单的方法可以从命令行执行此操作,但我没有看到一种抽象的简单方法来执行此操作,即完全导出,然后导入密钥。

有办法做到这一点吗?我更喜欢使用

vault
脚本的命令行解决方案。

hashicorp-vault
4个回答
5
投票

做到这一点的唯一方法是链接两个保险库命令,这实际上是从第一个保险库中读取值,然后将其写入第二个保险库。例如:

export VAULT_TOKEN=valid-token-for1
export VAULT_ADDR=https://vault1
JSON_DATA=$(vault kv get -format json -field data secret/foo)

export VAULT_TOKEN=valid-token-for2
export VAULT_ADDR=https://vault2
echo $JSON_DATA | vault kv put secret/foo -

3
投票

将数据从一个保管库导出到另一个保管库的唯一方法是对每个密钥(和每个路径)单独执行此操作。我编写了一个小的 bash 脚本来自动处理给定路径中的所有键。

此脚本从源保管库中轮询每个密钥(对于给定路径)的数据,并将其插入到目标保管库中。

您需要在下面的脚本中提供源和目标保管库的保管库 URL、令牌和 CA 证书(用于 https 身份验证)以及路径(包含密钥)-

#! /usr/bin/env bash

source_vault_url="<source-vault-url>"
source_vault_token="<source_vault_token>"
source_vault_cert_path="<source_vault_cert_path>"

destination_vault_url="<destination_vault_url>"
destination_vault_token="<destination_vault_token>"
destination_vault_cert_path="<destination_vault_cert_path>"

# secret_path is the path from which the keys are to be exported from source vault to destination vault
secret_path="<path-without-slash>"

function _set_source_vault_env_variables() {
    export VAULT_ADDR=${source_vault_url}
    export VAULT_TOKEN=${source_vault_token}
    export VAULT_CACERT=${source_vault_cert_path}
}

function _set_destination_vault_env_variables() {
    export VAULT_ADDR=${destination_vault_url}
    export VAULT_TOKEN=${destination_vault_token}
    export VAULT_CACERT=${destination_vault_cert_path}  
}

_set_destination_vault_env_variables

printf "Enabling kv-v2 secret at the path ${secret_path} in the destination vault -\n"
vault secrets enable -path=${secret_path}/ kv-v2 || true

_set_source_vault_env_variables

# getting all the keys in the given path from source vault
keys=$(vault kv list ${secret_path}/ | sed '1,2d')

# iterating though each key in source vault (in the given path) and inserting the same into destination vault
printf "Exporting keys from source vault ${source_vault_url} at path ${secret_path}/ ... \n" 
for key in ${keys}
do

    _set_source_vault_env_variables

    key_data_json=$(vault kv get -format json -field data ${secret_path}/${key})

    printf "${key} ${key_data_json}\n"

    _set_destination_vault_env_variables

    echo ${key_data_json} | vault kv put ${secret_path}/${key} -
done

printf "Export Complete!\n" 

# listing all the keys (in the given path) in the destination vault
printf "Keys in the destination vault ${destination_vault_url} at path ${secret_path}/ -\n"
vault kv list ${secret_path}

2
投票

我们正在开发一个开源 cli 工具,它完全可以满足您的需求。 该工具可以在导入和导出中处理一个秘密或完整的树结构。它还支持在 Vault 实例之间导出和导入之间对机密进行端到端加密。
https://github.com/jonasvinther/medusa

export VAULT_ADDR=https://192.168.86.41:8201
export VAULT_SKIP_VERIFY=true
export VAULT_TOKEN=00000000-0000-0000-0000-000000000000

./medusa export kv/path/to/secret --format="yaml" --output="my-secrets.txt"
./medusa import kv/path/to/new/secret ./my-secrets.txt

0
投票

Lakhan Saitejaanswer 中,“从源库获取给定路径中的所有密钥”可能会出现问题。

keys=$(vault kv list ${secret_path}/ | sed '1,2d')

该问题通过

hashicorp/vault
问题 5275“KV 引擎:递归地列出键”进行跟踪。

它提出了各种脚本,但在 2024 年第四季度,Palash Das 添加了以下评论

2024 年底,我们仍然没有得到这个。

上面共享的脚本工作正常,但有一定的限制,例如:

  1. 遇到 403 等错误时继续怎么样?在实际生产系统中,并非所有团队成员都可以访问所有密钥。因此,在进行遍历时,忽略 403 是安全的
  2. 大量密钥:是的,并非所有系统都是 localhost:8200,生产系统可能包含 10,000+ 个密钥。所以需要性能。
  3. 并非所有公司都有兴趣支付 LetEncrypt 费用,因此他们使用自签名证书。
    VAULT_SKIP_VERIFY
    完成工作。

我制作了一个 hacky 脚本(只有性能,没有可读性),只需几秒钟即可列出 10K+ 个密钥。

列表递归并行

list_recur_par() {
  local root="${1:-secret/}" conc="${2:-32}" out_file="${3:-all_paths}"

  echo "$root" > "$out_file"
  dq='"'
  tail -n +1 -f "$out_file" \
    | (grep --line-buffered '/$' || grep '/$') \
    | xargs -P "$conc" -I _KEY bash -E -c "
        export data=\$( vault kv list  '_KEY' | awk -v pref='_KEY' ' NR>=3 { print pref\$0 }' || true );
        flock $out_file -c  ' echo $dq\$data$dq >> $out_file'
      "
}

export VAULT_ADDR=https://......:8200
export VAULT_TOKEN='hvs....'

list_recur_par secret/ 128 /tmp/all_keys
# List all subkeys under "secret/" in 128 parallel processes and save to  /tmp/all_keys, then hang indefinitely (See TODO).

OSX 用户注意事项

  1. 安装
    flock
    brew install flock
    (我不是熟练的开发人员,因此我无法使用
    mkfifo
  2. -S 2048
    添加到
    xargs
    ,是的,并非每个实现都与原始 Linux 二进制文件一样好。大型保管库密钥在 OSX
    xargs
    中失败。它也不尊重
    ARGS_MAX
    env 变量
  3. 使用
    bash
    的最新版本
    zsh
    ,OSX的旧bash在2024年无法使用。

适用于〜我的〜❌每台✅机器

使用码头工人

docker run -v $PWD:/work  --rm -it --dns ...(dns only if your company's vault is in VPN') \
       -e VAULT_SKIP_VERIFY=true -e VAULT_ADDR=https://...:8200 -e VAULT_TOKEN='hvs....' \
       --entrypoint bash bitnami/vault:1.18.3-debian-12-r0

或原始的高山图像(真正的开发人员从不使用

alpine
busybox
,它们对
grep
awk
子命令的实现很可悲)。

docker run -v $PWD:/work  --rm -it --dns ...(dns only if your company's vault is in VPN') \
           -e VAULT_SKIP_VERIFY=true -e VAULT_ADDR=https://...:8200 -e VAULT_TOKEN='hvs....' \
           hashicorp/vault:1.18  sh

apk add bash
# ... The script goes here

# (grep --line-buffered '/$' || grep '/$') is used to fallback to busybox grep and you may see error for unknown argument --line-buffered, but that is ok. busybox grep does not have --line-buffered, and awk does not have -W interactive . 

待办事项

这个脚本是不完整的,它是一条无限的蛇,它吃掉了自己的尾巴。当没有处于稳定状态的

vault
二进制文件的子进程时,例如 5 秒,您可以终止脚本,因为它已完成。将来它将更新为在 shell 脚本中进行正确的多进程队列管理。

© www.soinside.com 2019 - 2024. All rights reserved.