我目前正在为Azure DevOps创建管道,以验证Terraform配置并将其应用于其他订阅。
我的terraform配置使用模块,这些模块与terraform配置“托管”在同一Azure DevOps项目的其他存储库中。
可悲的是,当我尝试执行terraform init
来获取那些模块时,管道任务“挂起”在那里,等待凭据输入。
根据Pipeline Documentation on Running Git Commands in a script的要求,我尝试使用checkout
属性添加一个persistCredentials:true
步骤。
根据我在任务日志中看到的信息(请参见下面的信息),凭据信息专门添加到当前存储库中,不能用于其他存储库。
添加persistCredentials:true
2018-10-22T14:06:54.4347764Z ##[command]git config http.https://my-org@dev.azure.com/my-org/my-project/_git/my-repo.extraheader "AUTHORIZATION: bearer ***"
terraform初始化任务的输出
2018-10-22T14:09:24.1711473Z terraform init -input=false
2018-10-22T14:09:24.2761016Z Initializing modules...
2018-10-22T14:09:24.2783199Z - module.my-module
2018-10-22T14:09:24.2786455Z Getting source "git::https://my-org@dev.azure.com/my-org/my-project/_git/my-module-repo?ref=1.0.2"
如何设置git凭据以用于其他存储库?
答案 0 :(得分:1)
我遇到了同样的问题,我最终要做的是在Terraform配置中标记SYSTEM_ACCESSTOKEN
。我在Azure DevOps中使用了令牌化任务,其中__
前缀和后缀用于标识和替换具有实际变量的令牌(它是可自定义的,但我发现最好使用双下划线来不干扰任何我拥有的代码)
- task: qetza.replacetokens.replacetokens-task.replacetokens@3
displayName: 'Replace tokens'
inputs:
targetFiles: |
**/*.tfvars
**/*.tf
tokenPrefix: '__'
tokenSuffix: '__'
如果您无法为自己的DevOps组织安装自定义扩展,则类似find $(Build.SourcesDirectory)/ -type f -name 'main.tf' -exec sed -i 's~__SYSTEM_ACCESSTOKEN__~$(System.AccessToken)~g' {} \;
的方法也可以使用。
我的Terramain main.tf看起来像这样:
module "app" {
source = "git::https://token:__SYSTEM_ACCESSTOKEN__@dev.azure.com/actualOrgName/actualProjectName/_git/TerraformModules//azure/app-service?ref=__app-service-module-ver__"
....
}
虽然不漂亮,但可以完成工作。模块源(在编写本文时)不支持从terraform输入变量。因此,我们可以做的是使用Terrafile,这是一个开源项目,通过在代码旁边保留一个简单的YAML文件,可以帮助您与可能使用的模块以及同一模块的不同版本保持同步。似乎它不再被主动维护,但是它可以正常工作:https://github.com/coretech/terrafile 我的Terrafile示例:
app:
source: "https://token:__SYSTEM_ACCESSTOKEN__@dev.azure.com/actualOrgName/actualProjectName/_git/TerraformModules"
version: "feature/handle-twitter"
app-stable:
source: "https://token:__SYSTEM_ACCESSTOKEN__@dev.azure.com/actualOrgName/actualProjectName/_git/TerraformModules"
version: "1.0.5"
默认情况下,Terrafile将模块下载到./vendor目录,因此您可以将模块源指向类似以下内容的文件:
module "app" {
source = "./vendor/modules/app-stable/azure/app_service"
....
}
现在,您只需要弄清楚如何在存在Terrafile的目录中执行terrafile
命令。
我的azure.pipelines.yml示例:
- script: curl -L https://github.com/coretech/terrafile/releases/download/v0.6/terrafile_0.6_Linux_x86_64.tar.gz | tar xz -C $(Agent.ToolsDirectory)
displayName: Install Terrafile
- script: |
cd $(Build.Repository.LocalPath)
$(Agent.ToolsDirectory)/terrafile
displayName: Download required modules
答案 1 :(得分:1)
您基本上有两种方法可以做到这一点。
确保您阅读并根据您的需要应用“在脚本中运行 Git 命令”文档中的 Enable scripts to run Git commands 部分。
System.AccessToken
(或 PAT,但我不推荐它)您可以通过:
__SYSTEM_ACCESSTOKEN__
之类的替换标记(如 Nilsas 建议的那样)并使用一些标记替换代码或 qetza.replacetokens.replacetokens-task.replacetokens
任务来插入值。此解决方案的缺点是,当您在本地运行 terraform
时,您还必须替换令牌。git::https://dev.azure.com
文本替换为 git::https://YOUR_ACCESS_TOKEN@dev.azure.com
。我通过使用以下 bash 任务脚本使用了第二种方法(它搜索 terragrunt
文件,但您可以适应 terraform
文件而无需太多更改):
- bash: |
find $(Build.SourcesDirectory)/ -type f -name 'terragrunt.hcl' -exec sed -i 's~git::https://dev.azure.com~git::https://$(System.AccessToken)@dev.azure.com~g' {} \;
Abu Belai 提供了一个 PowerShell 脚本来执行类似的操作。
但是,如果您的 terraform
模块 git
存储库中的模块将自己称为另一个 git
存储库中的模块(我们就是这种情况),则此类解决方案不起作用。
extraheader
模块 terraform
存储库的 url git
中全局添加访问令牌这样,由您的代码直接调用或由被调用模块的代码间接调用的所有模块的存储库都将能够使用您的访问令牌。为此,我在您的 terraform
/terragrunt
调用之前添加了以下步骤:
- bash: |
git config --global http.https://dev.azure.com/<your-org>/<your-first-repo-project>/_git/<your-first-repo>.extraheader "AUTHORIZATION: bearer $(System.AccessToken)"
git config --global http.https://dev.azure.com/<your-org>/<your-second-repo-project>/_git/<your-second-repo>.extraheader "AUTHORIZATION: bearer $(System.AccessToken)"
您需要为每个调用的 extraheader
存储库设置 git
。
请注意,如果您的管道在同一个工作器上多次设置 extraheader
,您可能需要在 terraform
调用后取消设置 extraheader
。这是因为 git
可能会与多个 extraheader
声明混淆。您可以通过添加以下步骤来完成此操作:
- bash: |
git config --global --unset-all http.https://dev.azure.com/<your-org>/<your-first-repo-project>/_git/<your-first-repo>.extraheader
git config --global --unset-all http.https://dev.azure.com/<your-org>/<your-second-repo-project>/_git/<your-second-repo>.extraheader
答案 2 :(得分:0)
我认为你不能。通常,您创建另一个构建,并链接到该构建中的工件,以在当前定义中使用它。这样,您无需连接到其他Git存储库
答案 3 :(得分:0)
问题的主要症结在于,下载模块的Terraform git
操作不在管道正在构建的存储库的上下文中发生。为了使Terraform git
操作通过Azure Repos进行身份验证,您必须在全局.gitconfig
中使用管道的访问令牌显式设置一个extraheader
。
尽管令牌仅在构建期间有效,但我不希望extraheader
配置污染(本地)构建代理用户的全局.gitconfig
,并且可能影响后续构建。为了使配置瞬态,我在.gitconfig
中创建了一个临时$env:AGENT_TEMPDIRECTORY
(在构建结束时由代理程序对其进行了清理),然后在全局变量中使用[include]
对其进行引用。 .gitconfig
。然后,include
会在Terraform操作完成后取消设置。
在Terraform操作之前,我在管道中具有以下PowerShell任务:
# Build a temp .gitconfig
$tempGitConfig = Join-Path $env:AGENT_TEMPDIRECTORY ".gitconfig.$($env:BUILD_BUILDID)"
# Set an extraheader for the module sources that uses the pipeline's access token
git config --file $tempGitConfig `
http.https://my.azd.com/project.extraheader `
"AUTHORIZATION: bearer $($env:SYSTEM_ACCESSTOKEN)"
# Include temp .gitconfig in global user .gitconfig
git config --global include.path $tempGitConfig
然后在Terraform操作之后,另一个PowerShell步骤取消设置include.path
:
# Cleanup
git config --global --unset include.path "\.gitconfig\.$($env:BUILD_BUILDID)"
如果您要反复执行此操作,则可以全部打包到自定义构建任务中。
答案 4 :(得分:0)
我做到了
_ado_token.ps1
# used in Azure DevOps to allow terrform to auth with Azure DevOps GIT repos
$tfmodules = Get-ChildItem $PSScriptRoot -Recurse -Filter "*.tf"
foreach ($tfmodule in $tfmodules) {
$content = [System.IO.File]::ReadAllText($tfmodule.FullName).Replace("git::https://myorg@","git::https://" + $env:SYSTEM_ACCESSTOKEN +"@")
[System.IO.File]::WriteAllText($tfmodule.FullName, $content)
}
azure-pipelines.yml
- task: PowerShell@2
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
inputs:
filePath: '_ado_token.ps1'
pwsh: true
displayName: '_ado_token.ps1'