如何将GitLab CI的Vault集成封装为可复用的横向模板?
问题描述
我有一个可正常运行的GitLab CI配置,用于从Vault获取密钥:
variables: VAULT_SERVER_URL: https://my-vault.com VAULT_NAMESPACE: my-namespace # Vault EE Only VAULT_AUTH_PATH: jwt VAULT_AUTH_ROLE: gitlab-ci vault_test: id_tokens: VAULT_ID_TOKEN: aud: $VAULT_SERVER_URL secrets: TEST_HELLO: vault: engine: name: kv-v2 path: gitlab-ci path: test field: hello file: false script: - echo $TEST_HELLO
现在需要将这段配置封装为可复用的模板,让多个仓库能引用并指定不同的path和field来获取特定密钥,期望的模板和引用方式如下(但不确定是否可行):
模板文件(/cicd/templates/vault/secrets.yaml):
variables: VAULT_SERVER_URL: https://my-vault.com VAULT_NAMESPACE: my-namespace # Vault EE Only VAULT_AUTH_PATH: jwt VAULT_AUTH_ROLE: gitlab-ci get_secret: id_tokens: VAULT_ID_TOKEN: aud: $VAULT_SERVER_URL secrets: TEST_HELLO: vault: engine: name: kv-v2 path: gitlab-ci path: test field: hello file: false
引用仓库的gitlab.yml:
include: - project: 'cicd/templates' file: '/vault/secrets.yaml' build: ## 希望传入参数引用模板获取特定密钥,比如类似这样的写法(目前不可用) ## secrets: !reference [.get_secret, path: test, field: hello] script: - echo $TEST_HELLO
请问有可行的实现思路或示例吗?
可行解决方案
GitLab CI的!reference语法不支持直接传递参数,但可以通过以下几种方式实现模板复用和动态密钥获取:
方法一:变量驱动的可扩展模板作业
将模板中的密钥参数定义为可覆盖的变量,引用时通过设置变量自定义密钥信息。
模板文件(/cicd/templates/vault/secrets.yaml)
variables: VAULT_SERVER_URL: https://my-vault.com VAULT_NAMESPACE: my-namespace # Vault EE Only VAULT_AUTH_PATH: jwt VAULT_AUTH_ROLE: gitlab-ci # 默认参数,可被引用仓库覆盖 VAULT_SECRET_ENV: TEST_HELLO VAULT_KV_ENGINE_PATH: gitlab-ci VAULT_KV_SECRET_PATH: test VAULT_KV_FIELD: hello .get_secret_template: id_tokens: VAULT_ID_TOKEN: aud: $VAULT_SERVER_URL secrets: $VAULT_SECRET_ENV: vault: engine: name: kv-v2 path: $VAULT_KV_ENGINE_PATH path: $VAULT_KV_SECRET_PATH field: $VAULT_KV_FIELD file: false
引用仓库的gitlab.yml
include: - project: 'cicd/templates' file: '/vault/secrets.yaml' # 获取默认密钥 build: extends: .get_secret_template script: - echo $TEST_HELLO # 获取自定义密钥 deploy: extends: .get_secret_template variables: VAULT_SECRET_ENV: DB_PASSWORD VAULT_KV_SECRET_PATH: prod/db VAULT_KV_FIELD: password script: - echo $DB_PASSWORD
方法二:复用认证逻辑,自定义密钥列表
将Vault认证的id_tokens部分单独作为模板,引用时复用认证逻辑,然后自定义需要获取的密钥。
模板文件(/cicd/templates/vault/secrets.yaml)
variables: VAULT_SERVER_URL: https://my-vault.com VAULT_NAMESPACE: my-namespace # Vault EE Only VAULT_AUTH_PATH: jwt VAULT_AUTH_ROLE: gitlab-ci .vault_auth_template: id_tokens: VAULT_ID_TOKEN: aud: $VAULT_SERVER_URL
引用仓库的gitlab.yml
include: - project: 'cicd/templates' file: '/vault/secrets.yaml' build: # 复用认证逻辑 id_tokens: !reference [.vault_auth_template, id_tokens] # 自定义需要获取的多个密钥 secrets: TEST_HELLO: vault: engine: name: kv-v2 path: gitlab-ci path: test field: hello file: false DB_PASSWORD: vault: engine: name: kv-v2 path: gitlab-ci path: prod/db field: password file: false script: - echo $TEST_HELLO - echo $DB_PASSWORD
方法三:Vault CLI动态获取(灵活度最高)
如果需要更复杂的密钥操作,可封装Vault认证脚本,通过CLI动态获取密钥,支持任意参数组合。
模板文件(/cicd/templates/vault/secrets.yaml)
variables: VAULT_SERVER_URL: https://my-vault.com VAULT_NAMESPACE: my-namespace # Vault EE Only VAULT_AUTH_PATH: jwt VAULT_AUTH_ROLE: gitlab-ci .vault_cli_setup: before_script: - | # 使用ID Token完成Vault认证 curl -sSfL "$VAULT_SERVER_URL/v1/auth/$VAULT_AUTH_PATH/login" \ -H "Content-Type: application/json" \ -d '{"jwt":"'"$VAULT_ID_TOKEN"'","role":"'"$VAULT_AUTH_ROLE"'"}' \ | jq -r '.auth.client_token' > /tmp/vault_token export VAULT_TOKEN=$(cat /tmp/vault_token) export VAULT_NAMESPACE="$VAULT_NAMESPACE" id_tokens: VAULT_ID_TOKEN: aud: $VAULT_SERVER_URL
引用仓库的gitlab.yml
include: - project: 'cicd/templates' file: '/vault/secrets.yaml' build: extends: .vault_cli_setup script: # 动态获取指定密钥并设置为环境变量 - export TEST_HELLO=$(vault kv get -field=hello gitlab-ci/test) - export DB_PASSWORD=$(vault kv get -field=password gitlab-ci/prod/db) - echo $TEST_HELLO - echo $DB_PASSWORD
方法对比
- 方法一:适合标准化单密钥场景,配置简洁,完全基于GitLab CI原生特性,无需额外工具。
- 方法二:适合多密钥场景,复用认证逻辑的同时保留密钥定义灵活性。
- 方法三:灵活度最高,支持Vault高级操作(如批量获取、动态密钥),但需要安装Vault CLI和
jq工具。
内容的提问来源于stack exchange,提问作者louis amoros
相关产品推荐
相关产品推荐

