You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GitHub Actions中通过OIDC/IAM角色从AWS ECR拉取自定义容器?

使用GitHub Actions OIDC+IAM角色拉取AWS ECR镜像运行容器作业的简化方案

问题描述

我需要在GitHub Actions作业中使用自定义容器执行任务,目前能通过提供用户名密码凭证从AWS ECR拉取镜像,但希望改用OIDC和IAM角色实现。当前的方案是拆分两个作业,先获取短期凭证再传递给容器作业,代码如下:

---
name: Manual test
"on":
  workflow_dispatch:
jobs:
  get_creds:
    permissions:
      id-token: write # 用于请求JWT
      contents: read  # 用于actions/checkout
    runs-on: [self-hosted]
    steps:
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: arn:aws:iam::123456:role/GithubWorkflow
          aws-region: us-east-1  
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
        with:
          mask-password: 'false'
    outputs:
      docker_username: ${{ steps.login-ecr.outputs.docker_username_123456_dkr_ecr_us_east_1_amazonaws_com }}
      docker_password: ${{ steps.login-ecr.outputs.docker_password_123456_dkr_ecr_us_east_1_amazonaws_com }}

  job1:
      needs: [get_creds]
      permissions:
        id-token: write
        contents: read
      runs-on: [self-hosted]
      container:
        image: 123456.dkr.ecr.us-east-1.amazonaws.com/3rdparty/library/alpine:3.18.4
        credentials:
          username: ${{ needs.get_creds.outputs.docker_username }}
          password: ${{ needs.get_creds.outputs.docker_password }}
      steps:
        - name: Step1
          run: |
            cat /etc/os-release

(上述代码中的alpine仅为调试示例)

想问有没有更简便的实现方案?另外我考虑过把aws-actions/configure-aws-credentials和aws-actions/amazon-ecr-login放到Runner文档提到的prepare_job阶段,但不确定Runner是否具备承担对应角色所需的OIDC令牌,也看不懂这些Action的TypeScript代码逻辑。


简化方案一:利用自托管Runner的prepare_job钩子(推荐)

这种方案不需要拆分作业,直接在Runner拉取容器镜像前完成OIDC认证和ECR登录,彻底省去凭证传递的步骤:

  1. 配置自托管Runner的prepare_job钩子
    在自托管Runner的安装目录下,找到_work/_hooks文件夹,创建(或修改)prepare_job.sh(Linux/macOS)脚本,添加以下逻辑:

    #!/bin/bash
    # 确保Runner已安装aws-cli和jq
    # 获取GitHub OIDC令牌
    ID_TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" | jq -r '.value')
    
    # 通过OIDC Assume角色获取临时AWS凭证
    STS_RESPONSE=$(aws sts assume-role-with-web-identity \
      --role-arn arn:aws:iam::123456:role/GithubWorkflow \
      --role-session-name "github-runner-$(date +%s)" \
      --web-identity-token "$ID_TOKEN" \
      --duration-seconds 3600)
    
    # 导出临时凭证到环境变量
    export AWS_ACCESS_KEY_ID=$(echo "$STS_RESPONSE" | jq -r '.Credentials.AccessKeyId')
    export AWS_SECRET_ACCESS_KEY=$(echo "$STS_RESPONSE" | jq -r '.Credentials.SecretAccessKey')
    export AWS_SESSION_TOKEN=$(echo "$STS_RESPONSE" | jq -r '.Credentials.SessionToken')
    
    # 登录AWS ECR
    aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456.dkr.ecr.us-east-1.amazonaws.com
    

    注意:需要确保Runner的IAM身份(或实例角色)允许调用sts:AssumeRoleWithWebIdentity,且目标IAM角色的信任策略已配置为信任GitHub OIDC提供商。

  2. 简化作业配置
    此时作业无需处理凭证传递,直接指定镜像即可:

    name: Manual test
    on:
      workflow_dispatch:
    jobs:
      job1:
        permissions:
          id-token: write
          contents: read
        runs-on: [self-hosted]
        container:
          image: 123456.dkr.ecr.us-east-1.amazonaws.com/3rdparty/library/alpine:3.18.4
        steps:
          - name: Step1
            run: |
              cat /etc/os-release
    

简化方案二:优化多作业凭证传递

如果不想修改Runner钩子,可以优化现有多作业方案,利用amazon-ecr-login的通用输出变量,避免硬编码仓库名后缀:

name: Manual test
on:
  workflow_dispatch:
jobs:
  get_creds:
    permissions:
      id-token: write
      contents: read
    runs-on: [self-hosted]
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: arn:aws:iam::123456:role/GithubWorkflow
          aws-region: us-east-1  
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
    outputs:
      registry: ${{ steps.login-ecr.outputs.registry }}
      docker_username: ${{ steps.login-ecr.outputs.docker_username }}
      docker_password: ${{ steps.login-ecr.outputs.docker_password }}

  job1:
    needs: [get_creds]
    permissions:
      id-token: write
      contents: read
    runs-on: [self-hosted]
    container:
      image: ${{ needs.get_creds.outputs.registry }}/3rdparty/library/alpine:3.18.4
      credentials:
        username: ${{ needs.get_creds.outputs.docker_username }}
        password: ${{ needs.get_creds.outputs.docker_password }}
    steps:
      - name: Step1
        run: |
          cat /etc/os-release

关于prepare_job阶段的OIDC令牌问题

自托管Runner在执行prepare_job钩子时,会自动获取GitHub提供的OIDC令牌,相关环境变量ACTIONS_ID_TOKEN_REQUEST_URL和ACTIONS_ID_TOKEN_REQUEST_TOKEN会被注入到钩子的执行环境中,完全可以用来调用STS服务完成角色假设,无需额外配置。

内容的提问来源于stack exchange,提问作者Tomas Kouba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:34:53