经过一堆故障排除后,我设法让我的gitlab CICD管道连接到GCP,而不需要我的服务帐户使用JSON密钥。但是,由于以下错误,我无法使用远程状态文件对管道中的Terraform做任何事情:
Error: Failed to get existing workspaces: querying Cloud Storage failed: googleapi: Error 403: Insufficient Permission, insufficientPermissions
我gitlab-ci。Yml文件定义如下:
stages:
- auth
- validate
gcp-auth:
stage: auth
image: google/cloud-sdk:slim
script:
- echo ${CI_JOB_JWT_V2} > .ci_job_jwt_file
- gcloud iam workload-identity-pools create-cred-config ${GCP_WORKLOAD_IDENTITY_PROVIDER}
--service-account="${GCP_SERVICE_ACCOUNT}"
--output-file=.gcp_temp_cred.json
--credential-source-file=.ci_job_jwt_file
- gcloud auth login --cred-file=`pwd`/.gcp_temp_cred.json
- gcloud auth list
tf-stuff:
stage: validate
image:
name: hashicorp/terraform:light
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
before_script:
- export TF_LOG=DEBUG
- cd terraform
- rm -rf .terraform
- terraform --version
- terraform init
script:
- terraform validate
我的gcp-auth
作业从我所看到的运行成功:
Authenticated with external account credentials for: [[MASKED]].
我还在gcp-auth
作业中添加了gsutil cp
命令,以确保我可以按预期访问所需的桶,我可以。我可以成功地编辑存储我的地形状态文件的桶的内容。
我对gitlab CICD管道相当陌生。我需要做些什么才能将gcp-auth
工作绑定到tf-stuff
工作?这就像该作业不知道管道先前使用服务帐户进行了身份验证。
谢谢!
就像其他海报提到的那样,gitlab作业独立运行,不共享环境变量或文件系统。因此,为了在作业之间保持登录状态,您必须以某种方式保持状态。
我写了一篇博客,其中有一个工作示例:https://ael-computas.medium.com/gcp-workload-identity-federation-on-gitlab-passing-authentication-between-jobs-ffaa2d51be2c
我已经做到了,就像github的行动是这样做的,通过存储(tmp)凭证作为工件。通过设置正确的环境变量,您应该能够"保持"登录状态(gcp将隐式刷新您的令牌),而无需创建包含所有内容的基本映像。所有作业都必须运行gcp_auth_before方法,或者扩展验证作业以使其工作。并且在作业之间保留_auth/artifacts
在下面的示例中,您可以看到在两个作业中保留了登录状态,但只有在第一个作业中实际登录。我已经将它与地形图像一起使用了进一步的步骤,到目前为止,它的工作就像一个魅力。
这是非常早期的,因此可能需要在生产中进行硬化。
希望这个例子能给你一些如何解决这个问题的想法!
.gcp_auth_before: &gcp_auth_before
- export GOOGLE_APPLICATION_CREDENTIALS=$CI_PROJECT_DIR/_auth/.gcp_temp_cred.json
- export CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=$CI_PROJECT_DIR/_auth/.gcp_temp_cred.json
- export GOOGLE_GHA_CREDS_PATH=$CI_PROJECT_DIR/_auth/.gcp_temp_cred.json
- export GOOGLE_CLOUD_PROJECT=$(cat $CI_PROJECT_DIR/_auth/.GOOGLE_CLOUD_PROJECT)
- export CLOUDSDK_PROJECT=$(cat $CI_PROJECT_DIR/_auth/.GOOGLE_CLOUD_PROJECT)
- export CLOUDSDK_CORE_PROJECT=$(cat $CI_PROJECT_DIR/_auth/.GOOGLE_CLOUD_PROJECT)
- export GCP_PROJECT=$(cat $CI_PROJECT_DIR/_auth/.GOOGLE_CLOUD_PROJECT)
- export GCLOUD_PROJECT=$(cat $CI_PROJECT_DIR/_auth/.GOOGLE_CLOUD_PROJECT)
.gcp-auth:
artifacts:
paths:
- _auth/
before_script:
*gcp_auth_before
stages:
- auth
- debug
auth:
stage: auth
image: "google/cloud-sdk:slim"
variables:
SERVICE_ACCOUNT_EMAIL: "... service account email ..."
WORKLOAD_IDENTITY_PROVIDER: "projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL/providers/PROVIDER"
GOOGLE_CLOUD_PROJECT: "... project id ...."
artifacts:
paths:
- _auth/
script:
- |
mkdir -p _auth
echo "$CI_JOB_JWT_V2" > $CI_PROJECT_DIR/_auth/.ci_job_jwt_file
echo "$GOOGLE_CLOUD_PROJECT" > $CI_PROJECT_DIR/_auth/.GOOGLE_CLOUD_PROJECT
gcloud iam workload-identity-pools create-cred-config
$WORKLOAD_IDENTITY_PROVIDER
--service-account=$SERVICE_ACCOUNT_EMAIL
--service-account-token-lifetime-seconds=600
--output-file=$CI_PROJECT_DIR/_auth/.gcp_temp_cred.json
--credential-source-file=$CI_PROJECT_DIR/_auth/.ci_job_jwt_file
gcloud config set project $GOOGLE_CLOUD_PROJECT
- "export GOOGLE_APPLICATION_CREDENTIALS=$CI_PROJECT_DIR/_auth/.gcp_temp_cred.json"
- "gcloud auth login --cred-file=$GOOGLE_APPLICATION_CREDENTIALS"
- gcloud auth list # DEBUG!!
debug:
extends: .gcp-auth
stage: debug
image: "google/cloud-sdk:slim"
script:
- env
- gcloud auth list
- gcloud storage ls
您的两个Gitlab
作业为Kubernetes
运行器在单独的pod
上运行。
tf-stuff
作业没有看到在gcp-auth
作业中完成的身份验证。
为了解决这个问题,您可以在单独的Shell
脚本中添加认证代码逻辑,然后在两个Gitlab
作业中重用该脚本,例如:
AuthenticationShell
scriptgcp_authentication.sh
:
echo ${CI_JOB_JWT_V2} > .ci_job_jwt_file
gcloud iam workload-identity-pools create-cred-config ${GCP_WORKLOAD_IDENTITY_PROVIDER}
--service-account="${GCP_SERVICE_ACCOUNT}"
--output-file=.gcp_temp_cred.json
--credential-source-file=.ci_job_jwt_file
gcloud auth login --cred-file=`pwd`/.gcp_temp_cred.json
gcloud auth list
# Check if you need to set GOOGLE_APPLICATION_CREDENTIALS env var on `pwd`/.gcp_temp_cred.json
对于tf-stuff
,您可以创建包含gcloud
和Terraform
的自定义Docker
图像,因为图像hashicorp/terraform
本地不包含gcloud
cli
。
您的Docker
图像可以添加到Gitlab
注册表
您的Gitlab
yml
文件:
stages:
- auth
- validate
gcp-auth:
stage: auth
image: google/cloud-sdk:slim
script:
- . ./gcp_authentication.sh
tf-stuff:
stage: validate
image:
name: yourgitlabregistry/your-custom-image:1.0.0
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
before_script:
- . ./gcp_authentication.sh
- export TF_LOG=DEBUG
- cd terraform
- rm -rf .terraform
- terraform --version
- terraform init
script:
- terraform validate
说明:
- 相同的
Shell
脚本已经在2个Gitlab
作业中使用:gcp_authentication.sh
- 在与
Terraform
部分相关的作业中创建了Terraform
和gcloud
cli
的自定义Docker
映像。此图像可以添加到Gitlab
注册表 - 在认证
Shell
脚本中,检查是否需要在pwd
/. gcp_temp_credit .json上设置GOOGLE_APPLICATION_CREDENTIALS
env var
你必须给你的服务帐户所需的权限使用Gitlab工作负载标识:
roles/iam.workloadIdentityUser
您可以查看这个示例项目和文档