如何使用Azure Powershell Runbooks查询Azure虚拟机SSL证书有效期
最优实现方案
整体逻辑为通过Azure Runbook内置托管身份自动完成订阅鉴权,枚举当前订阅下所有虚拟机后,针对Windows、Linux操作系统分别调用Azure原生运行命令接口拉取证书存储中的SSL证书信息,计算有效期后可直接输出或持久化存储,无需在虚拟机内提前预装任何代理。
前置准备
- 给Runbook配置系统分配托管身份,为该身份分配包含
虚拟机读取、虚拟机运行命令权限的自定义角色,权限按最小原则配置即可,无需分配订阅级别的高权限 - 确保Runbook运行环境已导入Az.Compute、Az.Accounts官方PowerShell模块
- 所有目标虚拟机需允许来自Azure平台的运行命令调用,无需开放公网端口
核心实现步骤
1. 完成Azure订阅鉴权
在Runbook开头执行以下代码完成自动登录,无需明文存储账号密钥:
# 使用系统托管身份登录Azure Connect-AzAccount -Identity | Out-Null # 切换到目标订阅,替换为你的订阅ID Set-AzContext -SubscriptionId "xxxx-xxxx-xxxx-xxxx" | Out-Null
2. 枚举订阅下所有虚拟机
$allVms = Get-AzVM $certResult = @()
3. 按系统类型拉取SSL证书有效期
Windows VM查询逻辑
调用PowerShell命令拉取本地计算机证书存储中用于服务器身份验证的SSL证书:
foreach ($vm in $allVms) { if ($vm.StorageProfile.OsDisk.OsType -eq "Windows") { $winCertCmd = @" Get-ChildItem Cert:\LocalMachine\My | Where-Object { `$_.EnhancedKeyUsageList.FriendlyName -contains 'Server Authentication' } | Select-Object @{Name='VmName';Expression={'$($vm.Name)'}},Subject, Thumbprint, NotBefore, NotAfter, @{Name='DaysRemaining';Expression={( `$_.NotAfter - (Get-Date)).Days}} | ConvertTo-Json "@ try { $runResult = Invoke-AzVMRunCommand -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -CommandId 'RunPowerShellScript' -ScriptString $winCertCmd -ErrorAction Stop $certResult += $runResult.Value[0].Message | ConvertFrom-Json } catch { Write-Warning "虚拟机 $($vm.Name) 无法访问,跳过查询" continue } }
Linux VM查询逻辑
调用Shell命令扫描常用证书存储路径,通过openssl工具解析证书有效期:
else { $linuxCertCmd = @" find /etc/ssl /etc/nginx /etc/httpd /usr/local/share/ca-certificates -name "*.crt" -o -name "*.pem" | xargs -I {} openssl x509 -in {} -noout -subject -enddate 2>/dev/null | awk ' /^subject=/ {sub(/^subject=.*CN=/, "", \$0); sub(/[\/,].*/, "", \$0); sub(/^ */, "", \$0); s=\$0} /^notAfter=/ {dt=substr(\$0,10); cmd="date -d \""dt"\" +%s"; cmd | getline ts; close(cmd); now=systime(); days=int((ts-now)/86400); print "{\'VmName\':\'$($vm.Name)\',\'Subject\':\'"s"\',\'NotAfter\':\'"dt"\',\'DaysRemaining\':"days"}"}' "@ try { $runResult = Invoke-AzVMRunCommand -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -CommandId 'RunShellScript' -ScriptString $linuxCertCmd -ErrorAction Stop $certResult += $runResult.Value[0].Message | ConvertFrom-Json } catch { Write-Warning "虚拟机 $($vm.Name) 无法访问,跳过查询" continue } } }
4. 结果处理
# 直接输出结果到Runbook日志 $certResult | Format-Table # 可选:将结果导出为CSV存入Azure存储账号Blob,方便后续查看或对接告警
优化建议
- 为Runbook配置定时触发计划,比如每周执行一次自动巡检
- 新增有效期阈值判断,当
DaysRemaining小于30时自动触发告警通知 - Linux侧如果证书存放在自定义路径,只需修改
find命令后的扫描路径即可适配
内容的提问来源于stack exchange,提问作者itye1970
相关产品推荐
相关产品推荐

