【问题标题】:Simplify PowerShell runbook to send e-mail简化 PowerShell Runbook 以发送电子邮件
【发布时间】:2021-05-09 06:36:04
【问题描述】:

我能否简化我的 PowerShell Azure Runbook,以便从订阅中的所有 KV 中收集即将到期的机密和证书(相对于重复代码)并在电子邮件中发送格式化的表格?

当前运行手册在订阅中配置到自动化帐户的关联模块上运行良好,但我确信有一种更简洁的方式来运行它并定期向利益相关者发送格式化的电子邮件。

Param(
        [string]$SubscriptionID = "",
        [int]$DaysNearExpiration = "30",
        [string]$VaultName
)
 
Get-AzureRmSubscription -SubscriptionId $SubscriptionID | Select-AzureRmSubscription | Format-Table -Autosize
 
$ExpiredSecrets = @()
$NearExpirationSecrets = @()

#gather all key vaults from subscription
if ($VaultName) {
    $KeyVaults = Get-AzureRmKeyVault -VaultName $VaultName
}
else {
    $KeyVaults = Get-AzureRmKeyVault
}
#check date which will notify about expiration
$ExpirationDate = (Get-Date (Get-Date).AddDays($DaysNearExpiration) -Format yyyyMMdd)
$CurrentDate = (Get-Date -Format yyyyMMdd)
 
# iterate across all key vaults in subscription
foreach ($KeyVault in $KeyVaults) {
    # gather all secrets in each key vault
    $SecretsArray = Get-AzureKeyVaultSecret -VaultName $KeyVault.VaultName
    foreach ($secret in $SecretsArray) {
        # check if expiration date is set
        if ($secret.Expires) {
            $secretExpiration = Get-date $secret.Expires -Format yyyyMMdd
            # check if expiration date set on secret is before notify expiration date
            if ($ExpirationDate -gt $secretExpiration) {
                # check if secret did not expire yet but will expire soon
                if ($CurrentDate -lt $secretExpiration) {
                    $NearExpirationSecrets += New-Object PSObject -Property @{
                        Name           = $secret.Name;
                        Category       = 'SecretNearExpiration';
                        KeyVaultName   = $KeyVault.VaultName;
                        ExpirationDate = $secret.Expires;
                    }
                }
                # secret is already expired
                else {
                    $ExpiredSecrets += New-Object PSObject -Property @{
                        Name           = $secret.Name;
                        Category       = 'SecretNearExpiration';
                        KeyVaultName   = $KeyVault.VaultName;
                        ExpirationDate = $secret.Expires;
                    }
                }
 
            }
        }
    }
         
}
 
Write-Output "Total number of expired secrets: $($ExpiredSecrets.Count)"
$ExpiredSecrets
  
Write-Output "Total number of secrets near expiration: $($NearExpirationSecrets.Count)"
$NearExpirationSecrets

$ExpiredCertificates = @()
$NearExpirationCertificates = @()

#gather all key vaults from subscription
if ($VaultName) {
    $KeyVaults = Get-AzureRmKeyVault -VaultName $VaultName
}
else {
    $KeyVaults = Get-AzureRmKeyVault
}
#check date which will notify about expiration
$ExpirationDate = (Get-Date (Get-Date).AddDays($DaysNearExpiration) -Format yyyyMMdd)
$CurrentDate = (Get-Date -Format yyyyMMdd)
 
# iterate across all key vaults in subscription
foreach ($KeyVault in $KeyVaults) {
    # gather all certificates in each key vault
    $CertificatesArray = Get-AzureKeyVaultCertificate -VaultName $KeyVault.VaultName
    foreach ($Certificate in $CertificatesArray) {
        # check if expiration date is set
        if ($certificate.Expires) {
            $certificateExpiration = Get-date $certificate.Expires -Format yyyyMMdd
            # check if expiration date set on certificate is before notify expiration date
            if ($ExpirationDate -gt $certificateExpiration) {
                # check if secret did not expire yet but will expire soon
                if ($CurrentDate -lt $certificateExpiration) {
                    $NearExpirationCertificates += New-Object PSObject -Property @{
                        Name           = $certificate.Name;
                        Category       = 'CertificateNearExpiration';
                        KeyVaultName   = $KeyVault.VaultName;
                        ExpirationDate = $certificate.Expires;
                    }
                }
                # secret is already expired
                else {
                    $ExpiredCertificates += New-Object PSObject -Property @{
                        Name           = $certificate.Name;
                        Category       = 'CertificateNearExpiration';
                        KeyVaultName   = $KeyVault.VaultName;
                        ExpirationDate = $certificate.Expires;
                    }
                }
 
            }
        }
    }
         
}
 
Write-Output "Total number of expired certificates: $($ExpiredCertificates.Count)"
$ExpiredCertificates
  
Write-Output "Total number of certificates near expiration: $($NearExpirationCertificates.Count)"
$NearExpirationCertificates

【问题讨论】:

    标签: azure powershell certificate azure-keyvault runbook


    【解决方案1】:

    这是一个可能的重构(未经测试):

    Param(
            [string]$SubscriptionID = "",
            [int]$DaysNearExpiration = "30",
            [string]$VaultName
    )
     
    Get-AzureRmSubscription -SubscriptionId $SubscriptionID | Select-AzureRmSubscription | Format-Table -Autosize
    
    $ExpiredSecrets = [System.Collections.Generic.List[PSCustomObject]] @()
    $NearExpirationSecrets = [System.Collections.Generic.List[PSCustomObject]] @()
    
    #gather all key vaults from subscription
    $KeyVaultArgs = if( $VaultName ) { @{ VaultName = $VaultName } } else { @{} } 
    # In PS 7+ you could write:
    # $KeyVaultArgs = $VaultName ? @{ VaultName = $VaultName } : @{} 
    $KeyVaults = Get-AzureRmKeyVault @KeyVaultArgs
    
    #check date which will notify about expiration
    $ExpirationDate = (Get-Date (Get-Date).AddDays($DaysNearExpiration) -Format yyyyMMdd)
    $CurrentDate = (Get-Date -Format yyyyMMdd)
     
    # iterate across all key vaults in subscription
    foreach ($KeyVault in $KeyVaults) {
        # gather all secrets in each key vault
        $SecretsArray = Get-AzureKeyVaultSecret -VaultName $KeyVault.VaultName | Where-Object Expires
    
        foreach ($secret in $SecretsArray) {
            # check if expiration date is set
            $secretExpiration = Get-date $secret.Expires -Format yyyyMMdd
            # check if expiration date set on secret is before notify expiration date
            if ($ExpirationDate -gt $secretExpiration) {
                $secret = [PSCustomObject]@{
                    Name           = $secret.Name
                    Category       = 'SecretNearExpiration'
                    KeyVaultName   = $KeyVault.VaultName
                    ExpirationDate = $secret.Expires
                }
    
                # check if secret did not expire yet but will expire soon
                if ($CurrentDate -lt $secretExpiration) {
                    $NearExpirationSecrets.Add( $secret )
                }
                # secret is already expired
                else {
                    $ExpiredSecrets.Add( $secret )
                }
            }
        }       
    }
    
    # omitted unmodified code ...
    

    变化:

    • 使用[System.Collections.Generic.List[PSCustomObject]] 而不是普通数组。当阵列可以变大时,这会更有效。每当使用运算符 += 时,Powershell 都会重新创建一个大小为 +1 的普通数组。 list 的内部数组将仅以 2 的倍数调整大小。
    • $KeyVaultArgs = if ... 使用条件赋值将参数创建为哈希表,然后使用 splatting 只需一次调用 Get-AzureRmKeyVault
    • $SecretsArray = Get-AzureKeyVaultSecret -VaultName $KeyVault.VaultName | Where-Object Expires 让我们摆脱了foreach 中的if ($secret.Expires),从而降低了嵌套级别。
    • $secret = [PSCustomObject]@{ 从下面的 if/else 构造中删除重复代码。语法也比New-Object PSObject 更简洁。
    • $NearExpirationSecrets.Add( $secret )$ExpiredSecrets.Add( $secret ) 是必需的,因为 list 不支持 += 运算符。

    【讨论】:

    • 感谢@zett42 ....您重构的代码按预期工作!您是否碰巧知道我如何从 KV 以及您的脚本中提取证书信息(或者如果我可以将所有内容都提取到即将过期则更好)?我的脚本基本上重复了两次相同的逻辑,上层请求机密,下层请求证书。
    • @Grant 不知怎的,我错过了下半部分;-)。让我看看今天晚些时候我是否有时间......
    • 不用担心@zett42。谢谢!
    猜你喜欢
    • 2015-12-24
    • 2019-01-15
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    相关资源
    最近更新 更多