拆分GitHub Action后TF_API_TOKEN不可用,如何解决Terraform认证失败问题?
解决共享工作流中Terraform认证401未授权问题
我原本有一个代码冗长、重复内容多的GitHub Action,为优化结构,用workflow_call拆分成多个共享工作流。之前能通过仓库里的TF_API_TOKEN Secret(存储Terraform Cloud API密钥)完成Terraform CLI认证,但现在运行共享工作流时,执行terraform -chdir=deploy/environments/dev/bucket init命令出现401未授权错误,无法从app.terraform.io获取模块版本,推测是共享工作流无法访问该Secret,求解决方法。
相关工作流代码如下:
分支工作流:branch-feature.yml
name: Deploy Feature Branch on: pull_request: types: [opened, synchronize] branches: - develop workflow_dispatch: jobs: build: if: startsWith(github.head_ref, 'feature/') || github.head_ref == 'master' uses: ./.github/workflows/step-build.yml deploy-to-dev: needs: [build] uses: ./.github/workflows/step-deploy.yml with: deploy-env: dev deploy-branch: ${{ github.head_ref }}
部署步骤工作流:step-deploy.yml
on: workflow_call: inputs: deploy-env: required: true description: 'Environment to deploy to' type: string deploy-branch: required: true description: 'Branch to deploy' type: string jobs: get-version: uses: ./.github/workflows/step-version.yml deploy-infrastructure: uses: ./.github/workflows/step-deploy-infrastructure.yml with: deploy-env: ${{ inputs.deploy-env }} deploy-branch: ${{ inputs.deploy-branch }} script-directory: bucket
基础设施部署工作流:step-deploy-infrastructure.yml
on: workflow_call: inputs: deploy-env: required: true description: 'Environment to deploy to' type: string deploy-branch: required: true description: 'Branch to deploy' type: string script-directory: required: true description: 'Directory to run terraform from' type: string terraform-args: required: false description: 'Additional arguments to pass to terraform' type: string default: "" outputs: bucket-name: description: 'The name of the s3 bucket created' value: ${{ jobs.deploy.outputs.bucket-name }} jobs: deploy: runs-on: ubuntu-latest environment: ${{ inputs.deploy-env }} outputs: bucket-name: ${{ steps.bucket_name.outputs.stdout }} steps: - uses: actions/checkout@v3 with: ref: ${{ inputs.deploy-branch }} - name: Configure Environment based on branches run: | echo "TF-DIRECTORY=deploy/environments/${{ inputs.deploy-env }}/${{ inputs.script-directory }}" >> $GITHUB_ENV - name: Setup terraform uses: hashicorp/setup-terraform@v2 with: cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} - name: Terraform Format id: fmt run: terraform -chdir=${{ env.TF-DIRECTORY }} fmt -check - name: Terraform Init id: init run: terraform -chdir=${{ env.TF-DIRECTORY }} init - name: Terraform Validate id: validate run: terraform -chdir=${{ env.TF-DIRECTORY }} validate -no-color - name: Terraform Plan id: plan run: terraform -chdir=${{ env.TF-DIRECTORY }} plan -no-color continue-on-error: true - name: Update Pull Request uses: actions/github-script@v6.4.1 env: PLAN: "terraform\n${{ steps.plan.outputs.stdout }}" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\` #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\` #### Terraform Plan 📖\`${{ steps.plan.outcome }}\` #### Terraform Validation 🤖\`${{ steps.validate.outputs.stdout }}\` <details><summary>Show Plan</summary> \`\`\`\n ${process.env.PLAN} \`\`\` </details> *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output }) - name: Terraform Plan Status if: steps.plan.outcome == 'failure' run: exit 1 - name: Terraform Apply ${{ inputs.deploy-env }} run: terraform -chdir=${{ env.TF-DIRECTORY }} apply -auto-approve ${{ inputs.terraform-args }} - name: Get Bucket Name id: bucket_name run: terraform -chdir=${{ env.TF-DIRECTORY }} output -raw bucket_name
解决方案
GitHub共享工作流不会自动继承调用方的Secrets,必须在每一层工作流中显式定义并传递所需的Secret。按以下步骤修改:
1. 修改step-deploy-infrastructure.yml,添加Secret定义
在on.workflow_call下新增secrets配置,声明需要接收TF_API_TOKEN:
on: workflow_call: inputs: deploy-env: required: true description: 'Environment to deploy to' type: string deploy-branch: required: true description: 'Branch to deploy' type: string script-directory: required: true description: 'Directory to run terraform from' type: string terraform-args: required: false description: 'Additional arguments to pass to terraform' type: string default: "" secrets: TF_API_TOKEN: required: true description: 'Terraform Cloud API Token' outputs: bucket-name: description: 'The name of the s3 bucket created' value: ${{ jobs.deploy.outputs.bucket-name }}
2. 修改step-deploy.yml,添加Secret定义并传递给下层工作流
首先在on.workflow_call中添加Secret声明:
on: workflow_call: inputs: deploy-env: required: true description: 'Environment to deploy to' type: string deploy-branch: required: true description: 'Branch to deploy' type: string secrets: TF_API_TOKEN: required: true
然后在调用step-deploy-infrastructure.yml时,显式传递Secret:
deploy-infrastructure: uses: ./.github/workflows/step-deploy-infrastructure.yml with: deploy-env: ${{ inputs.deploy-env }} deploy-branch: ${{ inputs.deploy-branch }} script-directory: bucket secrets: TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }}
3. 修改branch-feature.yml,在调用step-deploy.yml时传递Secret
deploy-to-dev: needs: [build] uses: ./.github/workflows/step-deploy.yml with: deploy-env: dev deploy-branch: ${{ github.head_ref }} secrets: TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }}
原理说明
共享工作流作为独立的执行单元,默认无法直接访问调用方仓库的Secrets。通过在每一层workflow_call中定义需要的Secrets,并在调用时显式传递,就能让最底层的工作流获取到TF_API_TOKEN,完成Terraform Cloud的认证,解决401错误。
内容的提问来源于stack exchange,提问作者baynezy
相关产品推荐
相关产品推荐

