WSUSで高度な自動承認/拒否を組む

# はじめに
WSUS4.0以降はでは若干良くなっているが、WSUSの管理より構成する自動承認ではアーキテクチャによる絞り込みや細かな期間指定等が不可能なため、PowerShellを用いた高度な条件による自動承認/拒否を構成するための備忘録

# 参考サイト
[WSUS メンテナンス ガイド](https://blogs.technet.microsoft.com/jpwsus/2018/03/08/maintenance-guide/)
[不要な更新プログラムは「拒否済み」に設定しよう！](https://blogs.technet.microsoft.com/jpwsus/2017/12/11/decline-is-yrfrnd/)

# PowerShellでWSUSに接続する
WSUSサーバー上で実行する場合。

```powershell
Import-Module UpdateServices
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();
```

リモートのWSUSサーバーに接続する場合。

```powershell
Import-Module UpdateServices
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer([サーバーアドレス], [SSLの有無($true/$false)], [ポート番号(デフォルトは8530)]);
```

# 更新プログラムの取得

```powershell
$allUpdates = $wsus.GetUpdates()
```

# 取得した更新プログラムの要素一覧（抜粋）
|要素|説明|
|:--|:--|
|Title|更新プログラム名|
|LegacyName|更新プログラムのレガシー名|
|Description|更新プログラムの説明|
|KnowledgebaseArticles|文書番号|
|UpdateClassificationTitle|分類|
|ProductTitles|対象プロダクト|
|ProductFamilyTitles|対象プロダクトファミリー|
|CreationDate|リリース日|
|ArrivalDate|着信日|
|IsApproved|承認状態(True/False)|
|IsDeclined|拒否状態(True/False)|
|HasSupersededUpdates|他の更新プログラムに優先した更新プログラム(True/False)|
|IsSuperseded|他の更新プログラムに優先された更新プログラム(True/False)|

# 優先した、優先された更新プログラムの状態一覧及び抽出条件
|優先アイコン|HasSupersededUpdates|IsSuperseded|
|:-:|:--|:--|
|![優先した.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420540/99482716-9f01-36ac-f391-b4bec03a2438.png)|True|False|
|![優先したされた.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420540/1006ca65-d5c9-9844-1ac2-38326c542d99.png)|True|True|
|![優先された.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420540/d3d74168-081c-cef1-caee-c345fbca5fba.png)|False|True|

# 承認状態

|状態|IsApproved|IsDeclined
|:--|:--|:--|
|未承認|False|False|
|承認済み|True|False|
|拒否済み|False|True|

# LegacyName要素を利用したアーキテクチャによる抽出条件
32bit

```powershell
$x86update = $allUpdates | where { $_.LegacyName -imatch "-x86-" }
```

64bit

```powershell
$x64update = $allUpdates | where { $_.LegacyName -imatch "-x64-" }
```

ARM64

```powershell
$arm64update = $allUpdates | where { $_.LegacyName -imatch "-arm64-" }
```

# サンプルスクリプト
## 拒否済みを除く置き換えられた最も古い更新プログラムを拒否※
※置き換えた更新プログラムの承認状態は不問のため少し乱暴
　実際の運用環境に組み込む場合は参考サイトを参考にエラーハンドリングや置き換えた更新プログラムの承認状態の判定等を組み込む必要あり。

```powershell
Import-Module UpdateServices
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();
$allUpdates = $wsus.GetUpdates()
$supersededUpdates = $allUpdates | where { $_.IsDeclined -eq $false -And $_.IsSuperseded -eq $true -And $_.HasSupersededUpdates -eq $true }
if (! $supersededUpdates.count -eq 0 ) {
    # 更新プログラムを拒否
    $supersededUpdates.Decline()
}
```

## リリースから3週間経過した未承認のWindows 10 Version 1809 64bit 向け更新プログラムを承認

```powershell
Import-Module UpdateServices
# 3週間前の日時を取得
$searchDate = (Get-Date).AddDays(-21)
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();
$allUpdates = $wsus.GetUpdates()
$approveUpdates = $allUpdates | where { $_.IsDeclined -eq $false -And $_.IsApproved -eq $false -And $_.LegacyName -imatch "-Windows10Rs5Client-" -And $_.LegacyName -imatch "-x64-" -And $_.CreationDate -le $searchDate }
if (! $approveUpdates.count -eq 0 ) {
    # 更新プログラムを承認
    $approveUpdates.Approve()
}
```

# おまけ
WSUSの自動運用で定期的に実行するべき処理
1.SUSDBのインデックス再構築
　参考サイト
　[WSUS DB インデックスの再構成の手順について](https://blogs.technet.microsoft.com/jpwsus/2014/03/05/wsus-db/)
2.再構築後に更新プログラムの承認、不要更新プログラムの拒否
3.拒否後に不要コンテンツファイルの削除
　参考サイト
　[Invoke-WsusServerCleanup](https://docs.microsoft.com/ja-jp/powershell/module/wsus/invoke-wsusservercleanup?view=win10-ps)

# 最後に
WSUSの自動運用に少しでもこの記事が役に立てばと思います。