从环境变量传递证书到 curl

Passing certs to curl from an environment variable

我正在为我的应用程序开发 CORS 监视器,需要执行以下操作:

  1. 从我们的 Hashicorp Vault 实例下载证书
  2. 使用这些证书卷曲端点
  3. 评估响应

我目前可以这样做:

vault kv get -field crt my/cert/path/CACERT > CACERT.crt
vault kv get -field crt my/cert/path/TESTCERT > CERT.crt
vault kv get -field key my/cert/path/TESTCERT > KEY.key

curl -v\
    --cacert CACERAT.crt \
    --cert CERT.crt \
    --key KEY.key \
    --location \
    --request GET 'https://my.end.point'
# <evaluate here>
rm CACERT.crt CERT.crt KEY.key

虽然这可行,但我宁愿不将证书写入文件,而是将它们保存在内存中,例如使用环境变量或一些我不知道的 bash-ism .

在我看来它看起来更像这样:

CACERT=$(vault kv get -field crt my/cert/path/CACERT)
CERT=$(vault kv get -field crt my/cert/path/TESTCERT)
KEY=$(vault kv get -field key my/cert/path/TESTCERT)

curl -v\
    --cacert $CACERT \
    --cert $CERT \
    --key $KEY \
    --location \
    --request GET 'https://my.end.point'
# <evaluate here>

显然这行不通,因为 curl 需要文件路径,但出于说明目的,这可能吗?如果可能的话,这是一个糟糕的方法吗?也许还有另一种我没有考虑过的方法来解决这个问题?我知道我可以相对容易地使用 python 完成上述操作,但是如果可能的话,我更愿意坚持使用 bash + curl。

只有 POSIX shell,可以用显式创建的命名管道替换进程替换。

后台任务将不同的密钥和证书流式传输到它们的专用命名管道。

#!/usr/bin/env sh

# These are the randomly named pipes
cacert_pipe=$(mktemp -u)
cert_pipe=$(mktemp -u)
key_pipe=$(mktemp -u)

# Remove the named pipes on exit
trap 'rm -f -- "$cacert_pipe" "$cert_pipe" "$key_pipe"' EXIT

# Create the named pipes
mkfifo -- "$cacert_pipe" "$cert_pipe" "$key_pipe" || exit 1

# Start background shells to stream data to the respective named pipes
vault kv get -field crt my/cert/path/CACERT >"$cacert_pipe" &
vault kv get -field crt my/cert/path/TESTCERT >"$cert_pipe" &
vault kv get -field key my/cert/path/TESTCERT >"$key_pipe" &

curl -v\
    --cacert "$cacert_pipe" \
    --cert "$cert_pipe" \
    --key "$key_pipe" \
    --location \
    --request GET 'https://example.com/my.end.point'

与Bash的进程替换方法相比的缺点是;在使用命名管道作为文件参数调用 curl 之前,需要明确地重新启动流式传输任务。

Bash 使用 <(cmd) 语法支持 process substitution。这会导致 cmd 的输出被替换为文件名。这允许您将命令输出作为参数传递给需要文件名的地方。

在你的例子中,你会做这样的事情:

CACERT=$(vault kv get -field crt my/cert/path/CACERT)
CERT=$(vault kv get -field crt my/cert/path/TESTCERT)
KEY=$(vault kv get -field key my/cert/path/TESTCERT)

curl -v \
    --cacert <(echo "$CACERT") \
    --cert <(echo "$CERT") \
    --key <(echo "$KEY") \
    --location \
    --request GET 'https://my.end.point'