如何在GitLab CI作业中获取Group Access Token的值?
GitLab CI中直接访问Group Access Token(GAT)的可行方案
问题背景
我在测试跨项目访问GitLab包和容器镜像仓库,不想逐个配置新项目的CI作业令牌白名单,所以选择用Group Access Token(GAT)。群组下有多个项目(含子群组),均为默认设置。我在一个仓库生成了基础镜像,想在另一个项目的CI作业中通过Dockerfile的FROM指令引用它。已创建拥有API权限和Developer角色的GAT,根据GitLab权限文档,该权限足够读写包和镜像。
CI作业配置
build-service: stage: build image: name: gcr.io/kaniko-project/executor:debug entrypoint: [''] tags: - asprunner rules: # Build base image only if the Dockerfile or CICD config file have changed and been pushed to the cloud branch - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "dev"' when: on_success script: - echo "Building image for service X using Kaniko" - | export BASE_REGISTRY_URL=registry.company.com/mygroup/base-service export BASE_TOKEN_NAME=CI_GROUP_API export BASE_TOKEN_VALUE=$(CI_GROUP_API) echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf \"%s:%s\" \"${CI_REGISTRY_USER}\" \"${CI_JOB_TOKEN}\" | base64 | tr -d '\n')\"},\"${BASE_REGISTRY_URL}\":{\"username\":\"${BASE_TOKEN_NAME}\",\"password\":\"${BASE_TOKEN_VALUE}\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context . --dockerfile Dockerfile --insecure --skip-tls-verify --skip-tls-verify-pull --insecure-pull --destination "${CI_REGISTRY_IMAGE}:v0.1"
其中registry.company.com/mygroup/base-service是存储基础镜像的容器仓库地址,被当前项目Dockerfile的FROM指令引用。
遇到的错误
$ export BASE_REGISTRY_URL=registry.company.com/mygroup/base-service # collapsed multi-line command /bin/sh: eval: line 147: CI_GROUP_API: not found CI_GROUP_API $ /kaniko/executor --context . --dockerfile Dockerfile --insecure --skip-tls-verify --skip-tls-verify-pull --insecure-pull --destination "${CI_REGISTRY_IMAGE}:v0.1" INFO[0000] Retrieving image manifest registry.company.com/mygroup/base-service:v1.0 INFO[0000] Retrieving image registry.company.com/mygroup/base-service:v1.0 from registry registry.company.com error building image: unable to complete operation after 0 attempts, last error: GET https://gitlab.company.com/jwt/auth?scope=repository%3Aiosb%2Fiad%2F3dpipeline%2Fbase-service%3Apull&service=container_registry: DENIED: access forbidden Cleaning up project directory and file based variables
核心疑问
我发现无法直接获取CI_GROUP_API的值,希望像使用CI_JOB_TOKEN一样直接调用GAT。目前只找到一种方案:创建和GAT同名同值的群组CI/CD变量,但这样会破坏令牌的过期时间等功能;用GitLab REST API自动化配置又太复杂,想问有没有更直接的方法在CI作业中访问GAT?
可行解决方案
方案1:优化版群组CI/CD变量存储GAT
虽然你担心破坏过期功能,但可以通过变量的掩码和保护属性降低风险,且令牌过期后只需更新一次群组变量即可:
- 进入群组设置的
CI/CD > 变量,添加变量CI_GROUP_API,值为GAT的令牌字符串 - 勾选掩码(防止日志泄露)和保护(仅在受保护分支/标签的作业中可用)
- 所有子群组和项目的CI作业都会继承这个变量,令牌本身的过期时间依然有效,过期后令牌自动失效,只需更新一次群组变量即可,不会破坏原有逻辑
方案2:使用GitLab 15.7+的group_access_token关键字动态生成临时令牌
如果你的GitLab版本在15.7及以上,可以在CI配置中直接定义临时群组访问令牌,无需手动创建和存储:
build-service: stage: build image: name: gcr.io/kaniko-project/executor:debug entrypoint: [''] tags: - asprunner rules: - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "dev"' when: on_success # 动态生成临时群组访问令牌 group_access_token: name: "ci-group-token-${CI_PIPELINE_ID}" expires_in: 1h scopes: ["api", "read_registry"] role: developer script: - echo "Building image for service X using Kaniko" - | export BASE_REGISTRY_URL=registry.company.com/mygroup/base-service # 直接使用自动生成的GROUP_ACCESS_TOKEN环境变量 export BASE_TOKEN_VALUE=$GROUP_ACCESS_TOKEN echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf \"%s:%s\" \"${CI_REGISTRY_USER}\" \"${CI_JOB_TOKEN}\" | base64 | tr -d '\n')\"},\"${BASE_REGISTRY_URL}\":{\"username\":\"gitlab-ci-token\",\"password\":\"${BASE_TOKEN_VALUE}\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context . --dockerfile Dockerfile --insecure --skip-tls-verify --skip-tls-verify-pull --insecure-pull --destination "${CI_REGISTRY_IMAGE}:v0.1"
这个方案的优势:
- 令牌是临时的,自动过期,无需手动管理
- 无需存储固定令牌值,安全性更高
- 自动在CI作业中注入
GROUP_ACCESS_TOKEN环境变量,直接使用即可
方案3:项目访问令牌配合群组继承
如果需要更细粒度的权限控制,可以在群组中开启项目访问令牌的继承模板,让子项目自动继承权限配置,比逐个配置白名单高效得多。
内容的提问来源于stack exchange,提问作者rbaleksandar
相关产品推荐
相关产品推荐

