Azure DevOps管道Docker容器Libcrypto密钥加载错误求助
Terragrunt + Azure DevOps 管道模块下载权限问题排查与解决
问题背景
使用Azure DevOps管道实现Terragrunt持续集成,Terraform模块存储在独立代码仓库,执行terragrunt plan需要通过SSH密钥访问该仓库。所有Terragrunt命令在Docker容器中运行,构建容器时已注入SSH密钥,但执行terragrunt plan时出现模块下载失败,核心错误如下:
Load key "/root/.ssh/id_rsa": error in libcrypto
git@ssh.dev.azure.com: Permission denied (password,publickey).
现有配置
Dockerfile
FROM devopsinfra/docker-terragrunt:azure-tf-1.5.5-tg-0.50.1 RUN apt-get update RUN apt-get install -y git ARG SSH_PRIVATE_KEY RUN mkdir /root/.ssh/ RUN echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa RUN touch /root/.ssh/known_hosts RUN touch /root/.ssh/config RUN ssh-keyscan -t rsa ssh.dev.azure.com >> /root/.ssh/known_hosts RUN echo $'Host ssh.dev.azure.com vs-ssh.visualstudio.com \n\ HostkeyAlgorithms +ssh-rsa \n\ IdentityFile ~/.ssh/id_rsa \n\ IdentitiesOnly yes' >> /root/.ssh/config RUN chmod -R 600 ~/.ssh
Azure DevOps 管道配置
- task: Docker@1 displayName: 'Building image' inputs: command: 'Build an image' imageName: 'tg-azure-img' arguments: '--build-arg SSH_PRIVATE_KEY="$(ado-privatekey)"' - task: Docker@1 displayName: 'Terragrunt Plan' inputs: command: 'Run an image' imageName: 'tg-azure-img' qualifyImageName: false volumes: '$(Pipeline.Workspace)/drop:/code' envVars: | ARM_CLIENT_SECRET=$(edsp-terraform-ci-credential) ARM_CLIENT_ID=$(arm-client-id) ARM_TENANT_ID=$(arm-tenant-id) ARM_SUBSCRIPTION_ID=$(arm-subscription-id) workingDirectory: '/code/subscriptions/${{ parameters.workingDirectory }}' containerCommand: '/bin/bash run-plan.sh' runInBackground: false
解决思路
1. 修复SSH密钥写入时的格式损坏问题
使用echo命令写入SSH密钥会丢失换行符,导致密钥文件损坏。替换为printf命令保留完整格式:
# 替换原echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa RUN printf "%s" "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
2. 规范SSH目录与文件权限
chmod -R 600 ~/.ssh会将known_hosts和config也设为600权限(应为644),调整为:
RUN chmod 700 ~/.ssh # 目录仅所有者可读写执行 RUN chmod 600 ~/.ssh/id_rsa # 密钥文件仅所有者可读 RUN chmod 644 ~/.ssh/known_hosts ~/.ssh/config # 配置文件可读
3. 容器运行时注入密钥(更安全)
避免在镜像中硬编码敏感密钥,改为管道运行时挂载临时密钥文件:
- 步骤1:添加管道准备SSH密钥任务
- task: Bash@3 displayName: 'Prepare SSH Key' inputs: targetType: 'inline' script: | mkdir -p $(Pipeline.Workspace)/ssh echo "$(ado-privatekey)" > $(Pipeline.Workspace)/ssh/id_rsa echo $'Host ssh.dev.azure.com vs-ssh.visualstudio.com \n\ HostkeyAlgorithms +ssh-rsa \n\ IdentityFile ~/.ssh/id_rsa \n\ IdentitiesOnly yes' > $(Pipeline.Workspace)/ssh/config ssh-keyscan -t rsa ssh.dev.azure.com >> $(Pipeline.Workspace)/ssh/known_hosts chmod 700 $(Pipeline.Workspace)/ssh chmod 600 $(Pipeline.Workspace)/ssh/id_rsa chmod 644 $(Pipeline.Workspace)/ssh/config $(Pipeline.Workspace)/ssh/known_hosts
- 步骤2:修改Dockerfile移除密钥相关构建步骤
删除Dockerfile中所有ARG SSH_PRIVATE_KEY及后续密钥写入、权限配置的代码。 - 步骤3:更新容器运行任务
- task: Docker@1 displayName: 'Terragrunt Plan' inputs: command: 'Run an image' imageName: 'tg-azure-img' qualifyImageName: false volumes: | $(Pipeline.Workspace)/drop:/code $(Pipeline.Workspace)/ssh:/root/.ssh envVars: | ARM_CLIENT_SECRET=$(edsp-terraform-ci-credential) ARM_CLIENT_ID=$(arm-client-id) ARM_TENANT_ID=$(arm-tenant-id) ARM_SUBSCRIPTION_ID=$(arm-subscription-id) workingDirectory: '/code/subscriptions/${{ parameters.workingDirectory }}' containerCommand: '/bin/bash run-plan.sh' runInBackground: false
4. 验证SSH连接有效性
在容器运行命令前添加调试步骤,测试SSH连通性:
containerCommand: '/bin/bash -c "ssh -T git@ssh.dev.azure.com && run-plan.sh"'
若仍失败,需确认:
- 公钥已正确添加到Azure DevOps服务账号的SSH密钥列表中
- 密钥为无密码的PEM格式(Azure DevOps不支持带密码的SSH密钥)
ssh.config中的Host配置覆盖了所有需要的域名
5. 改用HTTPS + PAT认证替代SSH
放弃SSH密钥,改用Azure DevOps个人访问令牌(PAT)通过HTTPS访问模块仓库:
- 将Terraform模块源改为HTTPS格式:
git::https://dev.azure.com/myorg/modules.git//path/to/module - 在管道中添加环境变量:
envVars: | # ... 其他ARM变量 GIT_USERNAME=any_username GIT_PASSWORD=$(ado-pat)
- 在Terragrunt配置中添加Git凭证配置:
generate "git_credentials" { path = "git_credentials.tf" if_exists = "overwrite_terragrunt" contents = <<EOF terraform { git_credentials { username = "${get_env("GIT_USERNAME")}" password = "${get_env("GIT_PASSWORD")}" } } EOF }
内容的提问来源于stack exchange,提问作者Gabriel Kelly
相关产品推荐
相关产品推荐

