WSUS更新の承認:インポート、エクスポート、コピー

背景



最近まで、私は全国に多くのオフィスを持つロシアの大企業でエネキーシクとして働いていました。 私の管轄では、極東のさまざまな都市に11のサイトがありました(これは重要です)。 これらの各オフィスには、他とは接続されていない独自のネットワークインフラストラクチャ(独自のADドメイン、独自のサブネットなど)がありました。



かつて、管理者はMSからOSとプログラムを自動的に更新するプロセスを整理するタスクを設定し、レポートプラットフォームにWSUSを展開することを許可しました。



問題



WSUSが展開された後、コンピューターをWSUSグループに関連付けるためのポリシーが構成され、コンテンツカタログがMSサーバーと同期されるなど、疑問が生じました:誰が、そして最も重要な更新方法を承認しますか?



想像してみてください。ICMP応答の遅延がわずか 800ミリ秒である稀な数分は、前例のない運命であると認識されている11の都市との接続は非常に「高速」かつ「安定」です。 そして、それぞれが展開前にすべての更新をテストする必要があります。 同時に、サイトのサーバーへのアクセスはRDP経由のみでした。 各都市のサーバーに毎週接続し(そのような頻度で確立された順序)、テストグループでの新しい更新の使用を手動で承認し、それに応じて、テストした更新を商用運用に転送する必要がありました。

画像





車輪を再発明する理由



WSUSを使用した経験のある読者は、次の質問をするでしょう。実際、問題は何ですか? マイクロソフトはすべてを提供しています。「レプリカ」と呼ばれる「ダウンストリーム」(下位)サーバーが更新ファイル自体と特定のグループでの使用が承認された更新に関する情報の両方をダウンロードする複製メカニズムがあります。



確かにそうです。 ただし、検討中のケースでは、通常のメカニズムの使用は機能しませんでした。 ルートサーバーとそのレプリカの間に十分な幅のチャネルが必要です。 私はそのようなチャンネルを持っていませんでした。 しかし、指示が​​ありました-いかなる状況でもITコストを増やすことはありませんでした。



アイデア



「いやいや!」私は考えて、この状況から抜け出す方法を疑問に思い始めました。 まず、各WSUSサーバーは、何らかの形でMSのWindowsUpdateサーバー、WSUSプロバイダーのローカルサーバー、またはオフィスの近隣のWSUSサーバーなどにアクセスできました。 つまり 更新ファイルをダウンロードする場所があり、ダウンロードする必要がある更新プログラムを示すだけでした。 第二に、 Powershellの使用を許可されました。



アイデアは単純でした。どの更新が承認されたかに関するデータをインポート/エクスポートするメカニズムを実装する必要があります。 大学での研究中に形成された古い伝統によると、私は単純なXMLファイルにエクスポートすることにしました。 このファイルの構造は次のようなものです。

<Groups> <!--   ,       --> <gWSUS_wks_test> <!--   (Update) --> <Update> <!-- ,      --> <UpdateProduct>Windows XP</UpdateProduct> <!--  ,   ,    MS --> <UpdateKB>815021</UpdateKB> <!--    --> <UpdateDescription>An identified security vulnerability in Microsoft Windows NT 4.0, Windows 2000, and Windows XP could allow an attacker to take control of the computer. This issue is most likely to affect computers used as web servers. You can help protect your computer from this and other identified issues by installing this update from Microsoft. After you install this item, you may have to restart your computer.</UpdateDescription> <!--    --> <UpdateID>4aed463b-3a3b-4ad8-976e-17baf6434da2</UpdateID> <!--     --> <UpdateIsDeclined>False</UpdateIsDeclined> <!--        --> <UpdateApprovalIsOptional>False</UpdateApprovalIsOptional> <!--    (        ) --> <UpdateApprovalDeadLine>12/31/9999 23:59:59</UpdateApprovalDeadLine> <!-- ,    (   - ) --> <UpdateApprovalAction>Install</UpdateApprovalAction> </Update> </gWSUS_wks_test> </Groups>
      
      







示されたメカニズムを使用するシナリオは、次のように表すことができます。

  1. ネットワーク上の管理者(または信頼できるアシスタント)は、特定のグループで使用する更新を承認し、すべてが正常であることを確認し、特定のコンピューターグループ(たとえば、内部WEB)に適用する情報に関するファイルをアップロードしますウェブサイト;
  2. Enikeyschik in place(たとえば、私)は、ステップ1で管理者が生成したファイルをダウンロードし、そのコンテンツをローカルのWSUSデータベースにアップロードするスクリプトをセットアップします。
  3. enikeyschの責任のゾーンに接続されていないWSUSサーバーが複数ある場合-ステップ2が数回実行されます




これは最終的に何をもたらしますか? 第一に、enikeyschikはどの更新を承認するかを決定しません。この決定は、特定のグリッチに強く結びつく可能性が高い、作業で使用される元の開発曲線に対する各更新の効果を合理的に予測できる資格のあるシステム管理者によって行われます OS、SQLサーバー、およびMS Officeパッケージのドキュメント化されていない機能。



第二に、enikeyschikを間違えることはありません(必要な更新を承認することを忘れ、不要なものを誤って承認するなど)



第三に、管理者は、同じ更新プログラムがすべての企業ネットワークへのインストールに対して承認されているという保証を受け取ります(つまり、「Zamkadskで使用されているオフィスのバージョン」という質問は関係ありません)。



承認のエクスポートに加えて、テストグループでテストされたテストを「戦闘」テストに転送するメカニズムが必要でした。 1つのボタン/コマンドで、「テストグループでの使用が禁止および承認されていないすべてを承認する」ことをお勧めします。 これは、パフォーマーのミスの結果として保護されていないアップデートが本番に入るのを防ぐために必要です(「ああ、承認しました、間違ってクリックしました!」)。



実装



コード


既製のソリューションを探すのに時間を費やし、それを見つけられなかったので、私はWSUS APIPowershell 、および.NETのドキュメントをさらに深く研究しました。



最初に、WSUSサーバーを操作できるオブジェクトに一般的にアクセスする方法を理解する必要がありました。 これを行うには、適切なアセンブリをダウンロードします。

 [reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")|out-null
      
      







その後、ローカルにインストールされたWSUSサーバーを表すオブジェクトを返す関数を作成します。

 <# .SYNOPSIS    -  WSUS .DESCRIPTION      (,    )  WSUS .OUTPUTS   IUpdateServer,    WSUS #> Function Get-WsusServerInstance() { #  $Script:WSUS   "" . $WSUSServer = $Script:WSUS #      WSUS. if ($WSUSServer -eq $null) { $WSUSServer =[Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(); } Return $WSUSServer }
      
      







問題の記述にはWSUSグループとの連携が含まれるため、アイデアを得る方法を学ぶ必要があります。 私はこのコードのようなものを使用しました:

 <# .SYNOPSIS   -   WSUS   . .PARAMETER Name   WSUS,    . .OUTPUTS  IComputerTargetGroup,    WSUS,   . $null -   . #> Function Get-WsusGroupByName([STRING]$Name) { $wsus = $null $wsus = Get-WsusServerInstance $Groups = $wsus.GetComputerTargetGroups() Foreach ($Group in $Groups) { if ($Group.Name -eq $Name) { Return $Group } } Return $null }
      
      







WSUSグループビューにアクセスするメカニズムが用意されたので、特定のグループに承認された更新プログラムのリストを簡単に取得できます。

 <# .SYNOPSIS   ,    . .DESCRIPTION   ,  ,    .       (ID)   . .PARAMETER GroupName  ,       .OUTPUTS  .     : objUpdate ()  objApproval ( ) #> Function Get-UpdatesApprovedToGroup([STRING]$GroupName) { #   $ApprovedUpdates = @() # ,   WSUS $wsus = Get-WsusServerInstance #    $Group = Get-WsusGroupByName -Name $GroupName Write-Host "Querying updates info from WSUS server..." #    ,    $WsusUpdates = $wsus.GetUpdates() $TotalWsusUpdates = $WsusUpdates.Count $i = 0 #   ,           foreach ($Update in $WsusUpdates) { $i++ #KBID (    MS)  [STRING]$UpdateKB = $Update.KnowledgebaseArticles Write-Host "Gathering approvals for update. Last porcessed is KB$UpdateKB" #,             . $CurrentApprovals = $update.GetUpdateApprovals($group) #      (, ),   #      . if ($CurrentApprovals.Count -gt 0) { foreach ($Approval in $CurrentApprovals) { # ,      . $Record = New-Object Object Add-Member -InputObject $Record -MemberType NoteProperty -Value $Update -Name "objUpdate" | Out-Null Add-Member -InputObject $Record -MemberType NoteProperty -Value $Approval -Name "objApproval" | Out-Null $ApprovedUpdates = $ApprovedUpdates + $Record } } } Return $ApprovedUpdates }
      
      







この関数の結果として取得された情報は、ファイルに保存してから、たとえば次の関数を使用して別のWSUSサーバーにインポートできます。

 <# .SYNOPSIS      WSUS   .DESCRIPTION       (Approval),      (Decline) .PARAMETER FilePath XML-,        WSUS. .OUTPUTS $null (    ). #> Function Import-Approvals([STRING]$FilePath) { #    WSUS $WSUS = Get-WsusServerInstance #   WSUS,      . $XML = [xml](get-content $FilePath) $Groups = $XML.Groups $Groups = $Groups.ChildNodes #        Foreach ($Group in $Groups) { #  XML if ($Group.get_NodeType() -ne $XML_TYPE_COMMENT) { $GroupName = $Group.Name Write-Host "Importing updates for WSUS group: $GroupName" #   $objGroup = Get-WsusGroupByName -Name $GroupName #    ,       $Updates = $Group.ChildNodes $TotalUpdates = $Updates.Count $i = 0 Foreach ($Update in $Updates) { $i++ $UpdateGUID = $Update.UpdateID if ($UpdateGUID -ne "") { $UpdateKB = $Update.UpdateKB Write-Host "Importing updates for $GroupName. Last processed is KB$UpdateKB" # Update   ID  : $UpdateGUID = [System.Guid]$UpdateGUID $objUpdateID = [Microsoft.UpdateServices.Administration.UpdateRevisionId]$UpdateGUID $objUpdate = $WSUS.GetUpdate($objUpdateID) #       XML-,       [DateTime]$UpdateApprovalDeadline = Get-XmlValue -XML $Update.UpdateApprovalDeadLine [Microsoft.UpdateServices.Administration.UpdateApprovalAction]$UpdateApprovalAction = Get-XmlValue -XML $Update.UpdateApprovalAction if ($Update.UpdateIsDeclined -eq "true") { $UpdateIsDeclined = $true } else { $UpdateIsDeclined = $false } #  $objUpdate.Approve($UpdateApprovalAction,$objGroup,$UpdateApprovalDeadline) | Out-Null #  ""    ,     $objUpdate.IsDeclined = $UpdateIsDeclined } } } Write-host -Message "Import finished for group: $GroupName" } }
      
      







一般に、すべては非常に簡単です。 エクスポートはインポートと同様に実行されます(スクリプトの全文で対応する機能を見つけることができる人)。



ユーザーインターフェース




このスクリプトは私だけでなく、同僚(他の地域でも同じenikeyshchiki)が使用することになっていたため、グラフィカルユーザーインターフェイスを提供することにしました。





メインウィンドウの形でミニマリズムを観察しようとしましたが、インターフェイスにスクリプトパラメーターを含めることは避けました。 このスクリプトを使用するすべてのコンピューターにWPFがインストールされているわけではないため、グラフィカルインターフェイスはSystem.Windows.Formsを使用して実装され、そのようなXAMLタスクには適していません。



もちろん、ルーチン操作を自動化するように設計されたPowershellソリューションにはコマンドラインインターフェイスが必要です。そうしないと、ユーザーはスクリプトでコマンドラインインターフェイスを使用できません(または、少なくともスケジュールどおりに実行できません)。



説明されているシナリオは、以下のパラメーターを受け入れます。

  1. DoImportFromFile-承認情報をインポートするファイルへのパス。 このパラメーターが空の場合、インポートは行われません。
  2. DoExportToFile-承認情報をアップロードするファイルへのパス。 同様に、このパラメーターの値がない場合、エクスポートは実行されません。
  3. ServersCopyTestApprovals- 「戦闘」サーバーで使用するために、サーバーのテストグループでの使用が許可されているすべての更新を承認します(以下を参照)。
  4. WorkstationsCopyTestApprovals-前のものと似ていますが、ワークステーション用です。
  5. PathToLog-ログファイルへのパス(既定では一時フォルダー "%Temp%"に作成されます)




実施活動



説明されたシナリオを正常に使用するために、いくつかの準備措置を実行する必要がありました。



最初に、少なくとも1つのテストワークステーションと少なくとも1つのテストサーバーが各ネットワークに割り当てられました。 可能な限り、主要なビジネスにとって重要ではないノードをテストグループに含めようとしました。 更新プログラムがネットワーク全体での使用が承認される前に、テストコンピューターで数日間(システム管理者の裁量で)チェックされます。 問題の原因となる更新は除外(拒否)され、残りはテストの終了時にバトルグループでの使用が承認されます。 説明されているスクリプトは、承認のコピーに使用されます。



次のコンピューターグループは、シナリオを使用することになっているすべてのWSUSサーバーで作成されました。

  1. gWSUS_srv_test-テストサーバー。
  2. gWSUS_wks_test-テストワークステーション。
  3. gWSUS_srv_prod- 「バトル」サーバー。
  4. gWSUS_wks_prod-ビジネスに不可欠なワークステーション


グループ名はスクリプトにハードコーディングされており、編集せずに変更することはできません。 各WSUSサーバーで、スクリプトをテストグループから「戦闘」承認に隔月のスケジュールでコピーするモードで実行するように構成しました(このような期間により、一方で、「問題」の更新をリストaから除外することができますもう1つは、コンピューターへの更新の配信を遅らせないことです。



数日ごとに(システム管理者の裁量で)、テストネットワークで特別に任命されたenikeyschikが新しい(まだ承認されておらず、キャンセルされていない)更新を承認します。 システム管理者から許可を得た後、承認リストをXMLファイルの形式でネットワーク内の特別なサイトにアップロードします。



1日1回、各WSUSサーバーで単純なバッチファイルが実行され、このサイトから更新リストの現在のバージョンをダウンロードし、承認をインポートします。



 REM      cd /dd:\WSUS_script\ REM     del /f .\WSUS_updates_approvals.waf REM     wget --tries=100 --retry-connrefused --continue http://server.network.lan/wsus_approvals/WSUS_updates_approvals.waf REM     powershell -command -ExecutionPolicy Bypass ".\wsus_admin_tool.ps1 -DoImportFromFile 'c:\WSUS_updates_approvals.waf'"
      
      







おわりに



もちろん、説明されているソリューションには特定の欠点がないわけではありません:スクリプトはダウンロード可能な承認の関連性をチェックしません(このDBMSがない場合、ネットワーク上のSQLのサービスパックを承認する必要がありますか?)、スクリプトはアップストリームWSUSサーバー(またはWindowsUpdateサーバー)へのアクセスを必要とします、はいそして、コード自体はおそらく理想からはほど遠いでしょう。



ただし、タスクは正常に解決されました。ご存知のとおり、実践は真実の基準です。 説明したソリューションが他の誰かに役立つことを願っています。



Ps完全なスクリプトコードはPasteBin入手できます




All Articles