WSUS-Berichtsgenehmigungen für eine Gruppe

9

Ich versuche, einen Weg zu finden, um einen WSUS-Bericht mit Updates zu erstellen, die für Computergruppe A genehmigt wurden und für eine oder mehrere andere Gruppen nicht genehmigt wurden. Alternativ ein tabellarischer Bericht, in dem der Genehmigungsstatus für jedes Update und jede Gruppe aufgeführt ist, damit er verarbeitet werden kann, um das zu extrahieren, was ich benötige. Es scheint keinen solchen Bericht in WSUS selbst zu geben, oder zumindest keinen, den ich finden kann. Daher wäre ein Skript zur Erstellung eines solchen Berichts sehr willkommen.

John Gardeniers
quelle
Auf welcher Windows-Version läuft Ihr WSUS?
Nate
@Nate, es ist WSUS 3.2.7600.226, das auf einem Server 2008 R2 Standard 64-Bit-Computer ausgeführt wird.
John Gardeniers
Ich denke, ich habe eine Lösung für Sie, geben Sie mir ein paar und ich werde bestätigen
Nate

Antworten:

8

Dieses Powershell-Skript macht genau das, was Ihre ursprüngliche Anfrage war. Untersuchen Sie eine Computergruppe und suchen Sie nach Updates, die für eine oder mehrere andere Computergruppen nicht genehmigt wurden.

Hinweis Sie müssen dies entweder auf einem WSUS-Server oder auf einem Computer ausführen, auf dem die WSUS-Verwaltungstools installiert sind.

Aufbau

Stellen Sie $targetComputerGroupdie Computergruppe ein, die Sie als Basis verwenden möchten. Stellen Sie $CheckForMissingdie Namen der Gruppe oder Gruppen ein, für die Sie sehen möchten, ob sie genehmigt wurden. Hinweis: Um Vielfache zu machen, müssen Sie nur das Koma trennen ("Gruppe1, Gruppe2").

$serverName="localhost"
$targetComputerGroup="BaselineGroup"
$checkForMissing="MissingGroup1,MissingGroup2"

[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus=[Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($serverName,$false)
$computerGroup=$wsus.GetComputerTargetGroups()|ForEach-Object -Process {if ($_.Name -eq $targetComputerGroup) {$_}}
$UpdateScope=New-Object Microsoft.UpdateServices.Administration.UpdateScope
$UpdateScope.ApprovedStates="Any"
$updateScope.ApprovedComputerTargetGroups.Add($computerGroup)
$Approvals = $wsus.GetUpdateApprovals($UpdateScope)

#At this point we have all of the updates assigned to the $targetComputerGroup

$report= @()
write-host "Querying for all Updates approved for $targetComputerGroup"

foreach ($Approval in $approvals) {
   $record=""|Select-Object ComputerGroup,UpdateName, UpdateID
   $record.ComputerGroup=$wsus.GetComputerTargetGroup($Approval.ComputerTargetGroupID).Name
   $record.UpdateName=$wsus.GetUpdate($Approval.UpdateID).Title
   $record.UpdateID=$wsus.GetUpdate($Approval.UpdateID).ID.UpdateID
   $report +=$record
   }

#Now group the results by UpdateName
$GR=$report|group -Property UpdateName

$CheckForMissing=$CheckForMissing.Split(",")

 foreach ($entry in $gr) {
    $groups=@()
    foreach ($g in $entry.Group) {
        $groups += $g.ComputerGroup
        }
    foreach ($missing in $checkForMissing) {
        if ($groups -Contains $missing) {}
        else{
            New-Object PSObject -Property @{
            Name = $entry.Name
            UpdateID = $entry.Group[0].UpdateID
            GroupMissing = $missing
            }
        }
    }
}

Wenn Sie fertig sind, haben Sie eine Ausgabe wie folgt ausgegeben: Geben Sie hier die Bildbeschreibung ein

Wenn Sie die Liste nicht auf dem Bildschirm ausgeben, sondern in eine CSV exportieren möchten, ersetzen Sie den unteren Teil durch den folgenden Code:

   $CheckForMissing=$CheckForMissing.Split(",")
   $CSVdata=@()
     foreach ($entry in $gr) {
        $groups=@()
        foreach ($g in $entry.Group) {
            $groups += $g.ComputerGroup
            }
        foreach ($missing in $checkForMissing) {
            if ($groups -Contains $missing) {}
            else{
                $CSVdata += New-Object PSObject -Property @{
                Name = $entry.Name
                UpdateID = $entry.Group[0].UpdateID
                GroupMissing = $missing
                }
            }
        }
    }
 $CSVdata|Export-Csv "FILENAME.CSV"
Nate
quelle
Es klappt! Wissen Sie, wie Sie verhindern können, dass die Ausgabe abgeschnitten wird? Übrigens kann ich das Kopfgeld für weitere 9 Stunden nicht vergeben.
John Gardeniers
1
Das Abschneiden hängt davon ab, wie Powershell-Formate für den Bildschirm angezeigt werden. Ich habe die Antwort mit einem Beispiel für die Ausgabe in eine CSV-Datei aktualisiert, damit Sie die vollständigen Werte erhalten.
Nate
Hervorragend, da CSV sehr gut für meine Bedürfnisse geeignet ist. Von hier aus kann ich es Perl geben, wo ich zumindest weiß, was ich tue. Sehr geschätzt.
John Gardeniers
7

Man kann "einfach" eine Verbindung zur WSUS-Datenbank herstellen und Abfragen dagegen ausführen:

  1. Starten Sie SQL Management Studio mit erhöhten Berechtigungen.
  2. Eine Verbindung mit \\.\pipe\MSSQL$MICROSOFT##SSEE\sql\queryVerwendung von Windows - Authentifizierung .

Diese Tabellen scheinen in Bezug auf Ihre Frage von Interesse zu sein:

  • tbUpdate
    Enthält Informationen zu einzelnen Updates

  • tbTargetGroup
    Enthält Informationen zu allen Computergruppen

  • tbDeployment
    Enthält Informationen darüber, welche Updates für welche Computergruppen genehmigt wurden

Es erscheint jedoch vorteilhaft, die bereits vorhandene Ansicht vUpdateApprovalzu verwenden, um die meisten Informationen abzurufen, nach denen Sie suchen, da diese Ansicht die ActionIDSpalte tbDeploymentunter anderem bereits übersetzt .

Die vUpdateApprovalAnsicht enthält jedoch keine leicht lesbaren Titel für Aktualisierungen. Die Titel werden normalerweise aus gelesen tbLocalizedProperty. Um es uns einfacher zu machen, gibt es noch eine andere Sichtweise : vUpdate.

Ich habe nicht wirklich die richtigen Daten in unserer WSUS-Datenbank, um die richtige Abfrage zu erstellen, die zu Ihrer ersten Anfrage passt (und ich bin nicht sicher genug, um sie blind zu erstellen). Hier ist ein Ansatz für Ihre sekundäre Anfrage. Wenn ich es nicht vermasselt habe, wird eine Liste aller Aktualisierungen und der Genehmigungsstatus für alle Gruppen erstellt.

SELECT
    aUpdate.UpdateId,
    aUpdate.DefaultTitle,
    aGroup.Name as GroupName,
    aApproval.Action as Action
FROM
    PUBLIC_VIEWS.vUpdate AS aUpdate INNER JOIN
    PUBLIC_VIEWS.vUpdateApproval AS aApproval ON aUpdate.UpdateId = aApproval.UpdateId LEFT JOIN
    dbo.tbTargetGroup as aGroup ON aGroup.TargetGroupID = aApproval.ComputerTargetGroupId
;

Welches erzeugt diese Ausgabe auf unserem deutschen SBS:

Geben Sie hier die Bildbeschreibung ein

Für unseren SBS mit seinen 5 Standardgruppen werden 121558 Ergebniszeilen in ~ 26 Sekunden erzeugt. Wenn Sie also mit der Abfrage herumspielen möchten, kann es ratsam sein, SELECT TOP 1000beim Testen die erste Zeile in zu ändern .

Ich habe mir auch die Zeit genommen, alles in ein PowerShell-Skript zu packen:

# Where to connect to
$dataSource        = "\\.\pipe\MSSQL`$MICROSOFT##SSEE\sql\query"
$connectionTimeout = 30

# The query we want to perform against the WSUS database
$query = @"
    SELECT TOP 10
        aUpdate.UpdateId,
        aUpdate.DefaultTitle,
        aGroup.Name as GroupName,
        aApproval.Action as Action
    FROM
        PUBLIC_VIEWS.vUpdate AS aUpdate INNER JOIN
        PUBLIC_VIEWS.vUpdateApproval AS aApproval ON aUpdate.UpdateId = aApproval.UpdateId LEFT JOIN
        dbo.tbTargetGroup as aGroup ON aGroup.TargetGroupID = aApproval.ComputerTargetGroupId
"@
$queryTimeout = 120

# Construct the connection string
$connectionString = "Data Source={0};Integrated Security=True;Connect Timeout={1};Database=SUSDB" -f $dataSource,$connectionTimeout

# Open the connection to the SQL server
$connection = New-Object System.Data.SqlClient.SQLConnection
$connection.ConnectionString = $connectionString
$connection.Open()

# Construct our SQL command
$sqlCommand = New-Object system.Data.SqlClient.SqlCommand( $query, $connection )
$sqlCommand.CommandTimeout = $queryTimeout

# Retrieve the data from the server
$dataSet     = New-Object system.Data.DataSet
$dataAdapter = New-Object system.Data.SqlClient.SqlDataAdapter( $sqlCommand )
[void]$dataAdapter.fill( $dataSet )

# Clean up
$connection.Close()

# Output result
$dataSet.Tables

Bitte beachten Sie, dass dieses Skript die SELECT TOP 10Einschränkung enthält, um ein Überfluten Ihrer Shell während des Testens zu vermeiden.

Der Hochstapler
quelle
Es ist sicherlich etwas zu untersuchen. Möglicherweise gibt es ein Perl-Modul für die Interaktion mit MS SQL Server.
John Gardeniers
@ JohnGardeniers: Ich habe ein PowerShell-Skript hinzugefügt, das die Abfrage ausführt. Leider ist mein Perl-Wissen noch schlechter :)
Der Hochstapler
Das ist ein guter Ausgangspunkt, aber ich muss herausfinden, wie ich verhindern kann, dass die Ausgabe abgeschnitten wird.
John Gardeniers
@ JohnGardeniers: So zeigt PowerShell standardmäßig die zurückgegebenen Objekte an. Sie können das Skript ausführen myscript.ps1 | fl, um eine andere (nicht abgeschnittene) Ausgabe zu erhalten.
Der Hochstapler
Ich habe beschlossen, Sie für Ihre Mühe zu belohnen, aber Sie müssen 24 Stunden warten. Das System erlaubt mir nicht, sofort ein Kopfgeld zu vergeben.
John Gardeniers