适用于:✔️ Linux VM
总结
本文可帮助你排查 Linux VM 上Azure实例元数据服务(IMDS)证明终结点的证书链问题。 这些问题可能会影响依赖于 IMDS 证明数据的应用程序,以便进行 VM 身份验证、许可验证或安全令牌获取。
注释
有关Windows VM,请参阅Windows上的 IMDS 证书链问题。
证书链体系结构
IMDS 证明使用四级证书链,该链在 Windows 和 Linux 中相同:
DigiCert Global Root G2 (Root CA)
+-- Microsoft TLS RSA Root G2 (cross-signed intermediate)
+-- Microsoft TLS G2 RSA CA OCSP xx (OCSP responder intermediate)
+-- CN=metadata.azure.com (leaf certificate)
Important
尽管名为“Microsoft TLS RSA Root G2”,它并不是根证书颁发机构。 它是由 DigiCert Global Root G2 颁发的交叉签名的中间证书。
注释
IMDS 轮换 OCSP 中间证书。 Azure 使用多个编号为 02 至 16 的 OCSP 响应程序中间证书。 VM 可以使用其中任意一个。
与Windows的主要区别
与Windows不同,大多数 Linux 分发版不会通过 AIA(颁发机构信息访问)自动下载缺少的中间证书。 如果信任存储中缺少中间证书,则链生成会立即失败。 此限制使问题在 Linux 上更加明显,但也意味着修复非常简单:安装缺少的证书。
症状
查询 IMDS 已证明终结点的应用程序会失败,并出现证书或 SSL 错误。 常见症状包括:
- 访问
curlIMDS 认证端点时返回证书验证错误 - Python 应用程序引发
ssl.SSLCertVerificationError - Java应用程序报告
sun.security.validator.ValidatorException - 自定义许可或身份验证以无提示方式失败
如何诊断
步骤 1:验证 IMDS 是否可访问
curl -s -H "Metadata:true" \
"http://169.254.169.254/metadata/instance?api-version=2021-02-01" | head -c 200
如果此命令返回 JSON 元数据,则 IMDS 连接正常工作。 此问题特定于已证明的终结点和证书。
步骤 2:提取已证明的文档并检查证书链
# Get the attested document
ATTESTED=$(curl -s -H "Metadata:true" \
"http://169.254.169.254/metadata/attested/document?api-version=2018-10-01")
# Extract the signing certificate from the PKCS#7 signature
echo "$ATTESTED" | python3 -c "
import json, sys, base64
doc = json.load(sys.stdin)
sig = base64.b64decode(doc['signature'])
with open('/tmp/imds_sig.der', 'wb') as f:
f.write(sig)
print('Signature saved to /tmp/imds_sig.der')
"
# Extract the certificate from the PKCS#7 envelope
openssl pkcs7 -in /tmp/imds_sig.der -inform DER -print_certs -out /tmp/imds_cert.pem 2>/dev/null
# View the certificate details
openssl x509 -in /tmp/imds_cert.pem -noout -subject -issuer -dates
步骤 3:验证证书链
# Check if the chain validates against the system trust store
openssl verify -verbose /tmp/imds_cert.pem 2>&1
如果看到 error 20 at 0 depth lookup: unable to get local issuer certificate,信任存储中缺少中间证书或根证书。
步骤 4:确定 VM 使用的 OCSP 中间层
IMDS 轮换 OCSP 中间证书。 在安装证书之前,请确定 VM 使用哪个证书:
# Extract the OCSP number from the leaf certificate's issuer
OCSP_ISSUER=$(openssl x509 -in /tmp/imds_cert.pem -noout -issuer)
echo "Leaf issuer: $OCSP_ISSUER"
OCSP_NUM=$(echo "$OCSP_ISSUER" | grep -oP 'OCSP \K[0-9]+')
echo "Your VM uses OCSP: $OCSP_NUM"
在以下部分中的安装命令中使用此 OCSP 编号。 这些示例使用 04 ,但 VM 可能使用不同的数字(02、06、08、10、12、14 或 16)。
步骤 5:检查信任存储中有哪些证书
# Check for DigiCert Global Root G2
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' \
/etc/ssl/certs/ca-certificates.crt 2>/dev/null | grep -i "DigiCert Global Root G2"
# Check for Microsoft TLS RSA Root G2
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' \
/etc/ssl/certs/ca-certificates.crt 2>/dev/null | grep -i "Microsoft TLS"
步骤 6:测试证书下载终结点的连接
# Test AIA endpoints (port 80)
for host in cacerts.digicert.com caissuers.microsoft.com www.microsoft.com; do
if curl -s --connect-timeout 5 -o /dev/null "http://$host"; then
echo "[OK] $host"
else
echo "[BLOCKED] $host"
fi
done
解决方案
安装缺少的证书
下载并安装信任存储中缺少的中间证书。 可能需要同时安装交叉签名中间证书和 OCSP 响应程序中间证书。
Important
证书下载 URL 提供 DER 格式的文件。 Linux 信任存储需要 PEM 格式。 安装前,务必使用 openssl x509 -inform DER 进行转换。
注释
IMDS 将轮换 OCSP 中间体(编号为 02 到 16)。 检查叶证书的签发者(步骤 4),以确定您的 VM 使用的是哪个 OCSP 中间证书。 将下方下载 URL 中的 04 替换为您的 VM 的实际 OCSP 编号。 例如,如果 VM 使用 OCSP 10,请更改为 OCSP%2004``OCSP%2010。
Ubuntu/Debian
# Install the cross-signed intermediate (Microsoft TLS RSA Root G2)
sudo curl -s -o /tmp/microsoft-tls-rsa-root-g2.der \
"http://caissuers.microsoft.com/pkiops/certs/Microsoft%20TLS%20RSA%20Root%20G2%20-%20xsign.crt"
sudo openssl x509 -in /tmp/microsoft-tls-rsa-root-g2.der -inform DER \
-out /usr/local/share/ca-certificates/microsoft-tls-rsa-root-g2.crt
# Install the OCSP intermediate (replace 04 with your VM's OCSP number)
sudo curl -s -o /tmp/microsoft-tls-g2-rsa-ca-ocsp.der \
"https://www.microsoft.com/pkiops/certs/Microsoft%20TLS%20G2%20RSA%20CA%20OCSP%2004.crt"
sudo openssl x509 -in /tmp/microsoft-tls-g2-rsa-ca-ocsp.der -inform DER \
-out /usr/local/share/ca-certificates/microsoft-tls-g2-rsa-ca-ocsp.crt
# Update the certificate store
sudo update-ca-certificates
RHEL / CentOS / Oracle Linux / Azure Linux
# Install the cross-signed intermediate
sudo curl -s -o /tmp/microsoft-tls-rsa-root-g2.der \
"http://caissuers.microsoft.com/pkiops/certs/Microsoft%20TLS%20RSA%20Root%20G2%20-%20xsign.crt"
sudo openssl x509 -in /tmp/microsoft-tls-rsa-root-g2.der -inform DER \
-out /etc/pki/ca-trust/source/anchors/microsoft-tls-rsa-root-g2.crt
# Install the OCSP intermediate (replace 04 with your VM's OCSP number)
sudo curl -s -o /tmp/microsoft-tls-g2-rsa-ca-ocsp.der \
"https://www.microsoft.com/pkiops/certs/Microsoft%20TLS%20G2%20RSA%20CA%20OCSP%2004.crt"
sudo openssl x509 -in /tmp/microsoft-tls-g2-rsa-ca-ocsp.der -inform DER \
-out /etc/pki/ca-trust/source/anchors/microsoft-tls-g2-rsa-ca-ocsp.crt
# Update the certificate store
sudo update-ca-trust
SUSE /openSUSE
# Install the cross-signed intermediate
sudo curl -s -o /tmp/microsoft-tls-rsa-root-g2.der \
"http://caissuers.microsoft.com/pkiops/certs/Microsoft%20TLS%20RSA%20Root%20G2%20-%20xsign.crt"
sudo openssl x509 -in /tmp/microsoft-tls-rsa-root-g2.der -inform DER \
-out /usr/share/pki/trust/anchors/microsoft-tls-rsa-root-g2.crt
# Install the OCSP intermediate (replace 04 with your VM's OCSP number)
sudo curl -s -o /tmp/microsoft-tls-g2-rsa-ca-ocsp.der \
"https://www.microsoft.com/pkiops/certs/Microsoft%20TLS%20G2%20RSA%20CA%20OCSP%2004.crt"
sudo openssl x509 -in /tmp/microsoft-tls-g2-rsa-ca-ocsp.der -inform DER \
-out /usr/share/pki/trust/anchors/microsoft-tls-g2-rsa-ca-ocsp.crt
# Update the certificate store
sudo update-ca-certificates
验证修复
安装证书后,验证证书链是否有效:
# Re-fetch and verify
curl -s -H "Metadata:true" \
"http://169.254.169.254/metadata/attested/document?api-version=2018-10-01" \
| python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('/tmp/imds_sig.der','wb').write(base64.b64decode(d['signature']))"
openssl pkcs7 -in /tmp/imds_sig.der -inform DER -print_certs -out /tmp/imds_cert.pem 2>/dev/null
openssl verify -verbose /tmp/imds_cert.pem
成功的输出显示:
/tmp/imds_cert.pem: OK
Tip
还可以将 --autofix 标志与 验证工具 配合使用,在一个步骤中自动执行下载、转换、安装、信任存储更新和重新验证。
更多情景
时钟倾斜导致验证失败
症状:openssl verify 即使证书应仍在有效期内,也会因 certificate is not yet valid 或 certificate has expired 而失败。
原因: 虚拟机的系统时钟存在严重偏差。 证书验证会根据本地时钟检查 notBefore 和 notAfter。
如何检测:
# Check current time vs NTP
date -u
chronyc tracking 2>/dev/null || ntpq -p 2>/dev/null
解决方法:
# Force time sync (chrony)
sudo chronyc makestep
# Or force time sync (ntpd)
sudo ntpdate time.windows.com
同步时钟后,重新运行 openssl verify /tmp/imds_cert.pem。
已过期的中间证书
症状: 中间证书已存在于信任存储中,但 openssl verify 仍然失败。 证书的 notAfter 日期已过。
如何检测:
# Check expiry of the OCSP intermediate
openssl x509 -in /tmp/imds_cert.pem -noout -issuer -dates
解决方法: 下载新的证书,并使用上一“解决方案”部分中特定于发行版的命令重新安装它。 验证工具的 --autofix 标志会自动处理此步骤。
代理会拦截 AIA,但不会拦截 IMDS
症状: IMDS 可访问(步骤 1 通过),但证书下载终结点被阻止(步骤 6 失败)。
原因: IMDS 使用会绕过代理设置的链路本地地址(169.254.169.254)。 证书下载 URL 通过已配置的代理。 如果代理阻止 AIA 终结点,证书下载会失败。
如何检测:
# Check proxy settings
echo "http_proxy=$http_proxy"
echo "https_proxy=$https_proxy"
env | grep -i proxy
分辨率: 将 AIA 和 CRL 终结点添加到 no_proxy 环境变量:
export no_proxy="$no_proxy,caissuers.microsoft.com,www.microsoft.com,cacerts.digicert.com,crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,oneocsp.microsoft.com"
若要使此更改永久化,请将 export 行添加到 /etc/environment 或 /etc/profile.d/proxy.sh.
预安装的证书即将过期
症状: IMDS 已正常运行数月,然后突然开始失效。 所有 AIA 终结点都被阻止(防火墙策略)。 VM 依赖于预安装的证书。
原因: 如果阻止 AIA,请预安装所有中间证书。 这些证书具有到期日期。 过期后,链会失败,VM 无法自动加载替换。
如何检测:
# Check expiry of installed Microsoft TLS certs
for cert in /usr/local/share/ca-certificates/microsoft-*.crt \
/etc/pki/ca-trust/source/anchors/microsoft-*.crt \
/usr/share/pki/trust/anchors/microsoft-*.crt; do
[ -f "$cert" ] && echo "$(openssl x509 -in "$cert" -noout -enddate 2>/dev/null) $cert"
done
解决方法:
-
从“Azure证书颁发机构详细信息”页下载新证书。
-
若要防止 AIA 被阻止时将来出现过期问题,请预安装 所有 OCSP 中间变体(02 到 16)。 这样,VM 就可以在 OCSP 轮换中幸存下来,而无需下载任何内容:
for NUM in 02 04 06 08 10 12 14 16; do curl -s -o "/tmp/ocsp-${NUM}.der" \ "https://www.microsoft.com/pkiops/certs/Microsoft%20TLS%20G2%20RSA%20CA%20OCSP%20${NUM}.crt" openssl x509 -in "/tmp/ocsp-${NUM}.der" -inform DER \ -out "/usr/local/share/ca-certificates/microsoft-tls-g2-rsa-ca-ocsp-${NUM}.crt" done sudo update-ca-certificates注释
显示的证书安装路径适用于 Ubuntu/Debian。 对于 RHEL,请使用
/etc/pki/ca-trust/source/anchors/和update-ca-trust。 对于 SUSE,请使用/usr/share/pki/trust/anchors/和update-ca-certificates。
防火墙注意事项
如果 VM 的防火墙阻止出站 HTTP(端口 80),则无法从 AIA 终结点下载证书。 确保可访问以下终结点:
| Purpose | Endpoints |
|---|---|
| AIA (证书下载) | cacerts.digicert.com、caissuers.microsoft.com、www.microsoft.com |
| CRL(证书吊销列表) | crl3.digicert.com、crl4.digicert.com |
| OCSP (在线验证) | ocsp.digicert.com、oneocsp.microsoft.com |
有关详细信息,请参阅 证书下载和吊销列表。