我试图在作业之间传递 JWT 令牌,但有些东西阻止它正确传递。根据文档,如果我想在作业之间传递变量,我需要使用
outputs
,如here所述。我正在做的事情如下:
name: CI
on:
pull_request:
branches:
- main
jobs:
get-service-url:
...does something not interesting to us...
get-auth-token:
runs-on: ubuntu-latest
outputs:
API_TOKEN: ${{ steps.getauthtoken.outputs.API_TOKEN }}
steps:
- name: Get Token
id: getauthtoken
run: |
API_TOKEN:<there is a full JWT token here>
echo -n "API_TOKEN=$API_TOKEN" >> $GITHUB_OUTPUT
use-token:
runs-on: ubuntu-latest
needs: [get-service-url,get-auth-token]
name: Run Tests
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
newman run ${{ github.workspace }}/tests/collections/my_collection.json --env-var "service_url=${{needs.get-service-url.outputs.service_URL}}" --env-var "auth_token=${{needs.get-auth-token.outputs.API_TOKEN}}"
因此,在运行期间,在我的输出中我看到:
Run newman run /home/runner/work/my-repo/my-repo/tests/collections/my_collection.json --env-var "service_url=https://test.net" --env-var "auth_token="
起初我以为在作业之间传递令牌本身有问题。因此我尝试了 放置一个虚拟令牌并将其导出到输出中。在我的
get-auth-token
工作中,对输出的调用变成了:
echo -n "API_TOKEN=test" >> $GITHUB_OUTPUT
我在日志中看到了它:
--env-var "auth_token=test"
所以我在工作中传递它的方式很好。此外,令牌存在并且是正确的,因为我硬编码了一个令牌以简化我的测试。事实上,如果在我的
get-auth-token
工作中我尝试 echo $API_TOKEN
我在日志中看到 ***
这让我明白 Github 正确地混淆了它。
然后我试着不要在工作之间传递它。因此,我在 newman run
命令之前创建了相同的硬编码令牌,并直接在 newman run
中引用它,tada!现在的日志是:
Run newman run /home/runner/work/my-repo/my-repo/tests/collections/my_collection.json --env-var "service_url=https://test.net" --env-var "auth_token=***"
所以令牌就在那里!但我需要它来自另一份工作。有一些东西阻止令牌在作业之间传递,我不知道如何实现这一点。
找到了实现这一目标的技巧。包括暂时“混淆”Github 眼中的秘密。
在检索秘密的工作中,我对其进行编码并将其导出到
GITHUB_OUTPUT
:
API_TOKEN_BASE64=`echo -n <my_secret> | base64 -w 0`
echo -n "API_TOKEN=$API_TOKEN_BASE64" >> $GITHUB_OUTPUT
在我需要秘密的工作中,我对其进行解码(并在需要的地方使用):
API_TOKEN=`echo -n ${{needs.get-auth-token.outputs.API_TOKEN}} | base64 --decode`
为了确保我们不泄露秘密,可以使用加密。
我找到并成功使用的最简单方法是使用
gpg
和 base64
:
创建一个 GPG 密码并设置为名为
PASSPHRASE
的秘密(确保其强度强)。
创建加密和编码的输出(请忽略旧的输出语法),例如:
jobs:
build:
name: Build Docker image
...
outputs:
IMAGE_PATH: ${{ steps.out.outputs.IMAGE_PATH }}
steps:
- name: Process env vars
run: |
echo "IMAGE_PATH=/tmp/my-image.tar" >> "$GITHUB_ENV"
- name: Create outputs
id: out
run: |
echo "::set-output name=IMAGE_PATH::$(echo -n '${{ env.IMAGE_PATH }}' | gpg --symmetric --quiet --batch --passphrase ${{ secrets.PASSPHRASE }} --output - | base64 -w0)"
release-to-dev:
needs: build
...
steps:
- name: Process outputs
run: |
echo "IMAGE_PATH=$(echo -n '${{ needs.build.outputs.IMAGE_PATH }}' | base64 -d | gpg --decrypt --quiet --batch --passphrase ${NOT_A_PASSPHRASE} --output -)" >> $GITHUB_ENV
原始
IMAGE_PATH
值现在将在其他作业中以环境变量中的明文形式提供,如 ${IMAGE_PATH}
或 ${{ env.IMAGE_PATH }}
。
根据 GitHub Actions 文档,推荐的方法是使用秘密存储:
如果您想在作业或工作流程之间传递隐藏的机密,则应将机密存储在存储中,然后在后续作业或工作流程中检索它。
设置:
- 设置一个秘密存储来存储您将在工作流程中生成的秘密。例如,Vault。
- 生成用于读取和写入该秘密存储的密钥。将密钥存储为存储库机密。在以下示例工作流程中, 秘密名称是 SECRET_STORE_CREDENTIALS。有关更多信息,请参阅 “在 GitHub Actions 中使用机密。”