Azure Pipelines中传递证书作为变量失败问题排查
问题:Azure DevOps中跨Bash任务传递证书变量后验证失败
第一个Bash任务内用openssl验证证书正常,但第二个任务执行验证时失败,错误输出:
Could not read certificate from /dev/fd/63
Unable to load certificate##[error]Bash exited with code '1'.
对应的Pipeline代码如下:
- task: Bash@3 displayName: Bash - Convert Test Cert from Base 64 and save as variables name: TestCertConvert inputs: targetType: 'inline' script: | openssl genrsa -out "cert.key" 4096 openssl req -x509 -new -nodes -key "cert.key" -sha256 -days 365 -out "cert.crt" -subj "/CN=foo.com" manual_cert_decoded=$(cat cert.crt) echo "##vso[task.setvariable variable=MANUAL-DECODED;issecret=false]$manual_cert_decoded" # Verify the cert using openssl openssl x509 -text -noout -in <(echo "$manual_cert_decoded") - task: Bash@3 displayName: Verify test certs can be read inputs: targetType: 'inline' script: | openssl x509 -text -noout -in <(echo "$(MANUAL-DECODED)")
原因分析
核心问题是Azure DevOps的任务变量传递会自动替换换行符为空格。
第一个任务中,manual_cert_decoded是当前Shell会话内的变量,保留了证书PEM格式的原始换行符,传递给openssl时格式完全符合要求,因此验证通过。
但通过##vso[task.setvariable]设置的跨任务变量,其内容里的所有换行符都会被替换成空格。第二个任务中$(MANUAL-DECODED)实际传递的是没有换行的连续文本,openssl x509无法识别这种非标准格式的证书,导致验证失败。
解决方法
通过Base64编码/解码来保留证书的原始格式,这是跨任务传递多文本内容的可靠方案:
步骤1:修改第一个任务,对证书进行Base64编码后设置变量
- task: Bash@3 displayName: Bash - Encode Cert and save as variables name: TestCertConvert inputs: targetType: 'inline' script: | openssl genrsa -out "cert.key" 4096 openssl req -x509 -new -nodes -key "cert.key" -sha256 -days 365 -out "cert.crt" -subj "/CN=foo.com" # 用Base64编码证书内容,-w 0确保输出无换行 manual_cert_encoded=$(base64 -w 0 cert.crt) echo "##vso[task.setvariable variable=MANUAL-ENCODED;issecret=false]$manual_cert_encoded" # 可选:验证编码解码后的证书有效性 echo "$manual_cert_encoded" | base64 -d | openssl x509 -text -noout
步骤2:修改第二个任务,解码变量后验证证书
- task: Bash@3 displayName: Verify test certs can be read inputs: targetType: 'inline' script: | # 解码变量内容后直接传递给openssl echo "$(MANUAL-ENCODED)" | base64 -d | openssl x509 -text -noout
这种方法能确保证书的PEM格式完全保留,跨任务传递后依然可以被openssl正确识别。
内容的提问来源于stack exchange,提问作者Wyko ter Haar
相关产品推荐
相关产品推荐

