wsusの最近のブログ記事

同期される更新全部に対し、受け入れるか否かを検証・判断するのは専属の要員をアサイン出来ないなら無理だな、と思う。
そういうわけで、一定の更新クラス(セキュリティ問題の修正プログラム、修正プログラム集、重要な更新)に対して自動承認を行っている。

これらの自動承認とは別に「ルート証明書の更新プログラム」を自動承認したい。

WSUS APIを参照すると、IUpdateのApproveメソッドで承認できるらしい。
http://msdn.microsoft.com/en-us/library/aa354567(VS.85).aspx

ということで↓のスクリプトをPowerShellで書いてみた。
  • 「すべてのコンピュータ」に対して
  • 更新の名前に「ルート証明書の更新プログラム」を含む
  • インストール承認する
すべてのコンピュータ、を指すIComputerTargetGroupを得る
$all_computers_group = $update_server.GetComputerTargetGroup([Microsoft.UpdateServices.Administration.ComputerTargetGroupId]::AllComputers)
$target_computer_group = new-object Microsoft.UpdateServices.Administration.ComputerTargetGroupCollection
$target_computer_group.Add($all_computers_group) | out-null

更新に対する検索条件。Title以外にも適用されるらしいので、これだと余計なhitがあるかも。。
$update_scope = new-object Microsoft.UpdateServices.Administration.UpdateScope
$update_scope.TextIncludes = "ルート証明書の更新プログラム"

IUpdateを列挙。拒否済み、最新リビジョンでないものはスキップ
foreach($update in $update_server.GetUpdates($update_scope) | sort ArrivalDate)
{
if($update.IsDeclined -or -not $update.IsLatestRevision)
{
# 既に拒否済みのもの
# 最新リビジョンでないもの
# は相手にしない
continue
}

適用したいコンピュータグループの数だけ承認メソッド呼び出し
  foreach($target_group in $target_computer_group)
{
$update.Approve(
[Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install,
$target_group) | out-null
}



いつもどおり無保証。どのような結果についても責任を負いかねます。利用は自己責任で。

trap [Exception] {
$t = $error[0].ToString().Trim() + "`n" + $error[0].InvocationInfo.PositionMessage.Trim()
[Diagnostics.EventLog]::WriteEntry("approve_update", $t, "Error", 1)
}

[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
$update_server = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
$update_server.PreferredCulture ="ja"

$all_computers_group = $update_server.GetComputerTargetGroup([Microsoft.UpdateServices.Administration.ComputerTargetGroupId]::AllComputers)
$unassigned_computers_group = $update_server.GetComputerTargetGroup([Microsoft.UpdateServices.Administration.ComputerTargetGroupId]::UnassignedComputers)

$target_computer_group = new-object Microsoft.UpdateServices.Administration.ComputerTargetGroupCollection
$target_computer_group.Add($all_computers_group) | out-null

# 更新に対する条件
$update_scope = new-object Microsoft.UpdateServices.Administration.UpdateScope
$update_scope.TextIncludes = "ルート証明書の更新プログラム"


foreach($update in $update_server.GetUpdates($update_scope) | sort ArrivalDate)
{
if($update.IsDeclined -or -not $update.IsLatestRevision)
{
# 既に拒否済みのもの
# 最新リビジョンでないもの
# は相手にしない
continue
}
$rev_id = $update.Id
write-host ($update.ArrivalDate.ToLocalTime(), $rev_id.UpdateId, $rev_id.RevisionNumber, $update.Title)
foreach($app in $update.GetUpdateApprovals() | sort CreationDate)
{
$target_group = $app.GetComputerTargetGroup()
write-host ("`t", $app.CreationDate.ToLocalTime(), $app.Action.ToString(), $target_group.Name)
}

foreach($target_group in $target_computer_group)
{
$update.Approve(
[Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install,
$target_group) | out-null
}
}

Windows Server 2008
WSUS 3.0 SP1
PowerShell 1.0

PowerShellから WSUS APIを使う 

|
前提条件とやりたいこと
  • WSUSでWindows PCの更新管理をしている。
  • ここの運用では、ほとんどのコンピュータはADドメインに参加しており、コンピュータアカウントの管理者が設定してある。
  • 一定の間隔で更新未適用コンピュータの一覧を作成し自動的にメール通知するようにしたい。
    • 更新クラスが「SP、セキュリティ問題の修正プログラム、修正プログラム集、重要な更新」のいずれかで、これらの更新をインストール完了していないコンピュータの一覧。
    • メールの内容を自由にカスタマイズしたい。
  • また、当該コンピュータの管理者の氏名を一覧に含めることで連絡リストを兼ねたい。
    • WSUSで得たコンピュータ名をキーにActive Directoryに問い合わせ、管理者名を付記する。
    • ここの環境ではWSUSサーバとDCは同じサーバで運用。
  • メールの送付に関する設定および送付先はWSUSの通知設定と同じ設定を用いる
    • 「状態レポート」の通知先に送る。(更新レポートの通知先でなく)

WSUSの機能は.NET Frameworkから利用することが出来る。
http://msdn.microsoft.com/en-us/library/aa354567(VS.85).aspx

PowerShellは.NETのクラスライブラリを使うことが出来るから、WSUSの操作をスクリプトから行うことが出来る。

ということで、レポートスクリプト
無保証です。使用は自己責任で。
タスクスケジューラで定期的に実行している。ここの環境はw2k8のため管理者としての実行が必要だった。

.NETのクラスライブラリ(に限らずCOMでもActiveXでも)がスクリプトからさくさく使えるのはなんとも強力。unixのtarやgzipやsha1sumのようなレベルのコマンドがないので手間がかかるな、と感じることはあるけど、書き下ろせなくはない強力さがある。

アセンブリのロードと各種情報(更新クラスのTitleとか)の日本語化指定
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
$update_server = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
$update_server.PreferredCulture ="ja"

IComputerTarget.FullDomainNameからコンピュータアカウントを検索
$searcher = New-Object DirectoryServices.DirectorySearcher
    $manage_cn = ""
    $computer_account = $computer.FullDomainName.Split(".")[0] + '$'
    $searcher.Filter = "(sAMAccountName=$computer_account)"
    $result = $searcher.FindOne()
    if($result -ne $null)
    {
        $managed_by = $result.Properties["managedby"]

        if($managed_by -match "CN=(?<cn>[^,]+)")
        {
            $manage_cn = $matches.cn
        }
    }
※$computerはIComputerTarget

メール作成と送信
$email_conf = $update_server.GetEmailNotificationConfiguration()
$mail = New-Object System.Net.Mail.SmtpClient($email_conf.SmtpHostName)
$mail.Timeout = 30 * 1000

$msg = New-Object System.Net.Mail.MailMessage
$msg.Subject = "[WSUS]更新未適用コンピュータ"
$msg.From = New-Object System.Net.Mail.MailAddress($email_conf.SenderEmailAddress, $email_conf.SenderDisplayName)
foreach($rcpt in $email_conf.StatusNotificationRecipients)
{
$msg.To.Add($rcpt)
}
$msg.Body = $body

$mail.Send($msg)
※デフォルトで本文charsetおよびsubjectのMIMEエンコードのcharsetはutf8。
※WSUS側で通知設定がされていない場合は想定せず。
※ここの環境ではSMTP認証が不要のため無視している。


環境:
  Windows Server 2008(DC)
  WSUS 3.0 SP1
  PowerShell 1.0