Zatwierdzenia raportu WSUS dla grupy

9

Próbuję znaleźć sposób na utworzenie raportu WSUS o aktualizacjach, które zostały zatwierdzone dla grupy komputerów A, które nie zostały zatwierdzone dla jednej lub więcej grup. Alternatywnie, raport tabelaryczny, który zawiera stan zatwierdzenia każdej aktualizacji i każdej grupy, dzięki czemu można go przetworzyć w celu wyodrębnienia tego, czego potrzebuję. Wydaje się, że nie ma takiego raportu w samym WSUS, a przynajmniej nie mogę go znaleźć, więc skrypt do sporządzenia takiego raportu byłby bardzo mile widziany.

John Gardeniers
źródło
Na której wersji systemu Windows działa Twój WSUS?
Nate,
@Nate, to WSUS 3.2.7600.226 działa na 64-bitowej maszynie Server 2008 R2 Standard.
John Gardeniers
Myślę, że mam dla ciebie rozwiązanie, daj mi kilka, a potwierdzę
Nate

Odpowiedzi:

8

Ten skrypt PowerShell robi dokładnie to, co było początkowe żądanie. Zbadaj jeden komputer Grupa i znajdź aktualizacje niezatwierdzone dla jednej lub wielu innych grup komputerów.

Uwaga: Musisz uruchomić to na serwerze WSUS lub na komputerze, na którym są zainstalowane narzędzia administracyjne WSUS.

Konfiguracja

Ustaw $targetComputerGroupna grupę komputerów, której chcesz użyć jako linię bazową. Ustaw $CheckForMissingnazwy grup lub grup, które chcesz sprawdzić, czy zostały zatwierdzone. Uwaga: Aby wykonać wielokrotność, wystarczy oddzielić przecinek („Grupa 1, Grupa 2”)

$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
            }
        }
    }
}

Po zakończeniu będziesz mieć wyjście takie jak: wprowadź opis zdjęcia tutaj

Jeśli zamiast wyświetlać dane na ekranie, chcesz wyeksportować listę do pliku CSV, zastąp dolną część następującym kodem:

   $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
źródło
To działa! Czy wiesz, jak zatrzymać obcinanie wyjścia? BTW, nie mogę przyznać nagrody za kolejne 9 godzin.
John Gardeniers,
1
Obcinanie jest funkcją tego, jak formaty PowerShell dla ekranu. Zaktualizowałem odpowiedź za pomocą przykładu wyjścia do pliku CSV, abyś mógł mieć pełne wartości.
Nate,
Doskonale, ponieważ CSV jest bardzo odpowiedni dla moich potrzeb. Stąd mogę go nakarmić Perlowi, gdzie przynajmniej wiem, co robię. Bardzo mile widziane.
John Gardeniers,
7

Można „po prostu” połączyć się z bazą danych WSUS i uruchomić na niej zapytania:

  1. Uruchom SQL Management Studio z podwyższonymi uprawnieniami.
  2. Połącz się \\.\pipe\MSSQL$MICROSOFT##SSEE\sql\queryprzy użyciu uwierzytelniania systemu Windows .

Te tabele wydają się być interesujące w odniesieniu do twojego pytania:

  • tbUpdate
    Przechowuje informacje o pojedynczych aktualizacjach

  • tbTargetGroup
    Przechowuje informacje o wszystkich grupach komputerów

  • tbDeployment
    Przechowuje informacje o tym, jakie aktualizacje zostały zatwierdzone dla których grup komputerów

Wydaje się jednak, że korzystne jest wykorzystanie już istniejącego widoku vUpdateApprovaldo odzyskania większości poszukiwanych informacji, ponieważ widok ten tłumaczy między innymi ActionIDkolumnę tbDeployment.

vUpdateApprovalWidok, jednak nie zawiera żadnych czytelnych tytułów aktualizacji. Tytuły są zwykle odczytywane z tbLocalizedProperty. Aby ułatwić nam, że jest inny widok: vUpdate.

Naprawdę nie mam odpowiednich danych w naszej bazie danych WSUS, aby zbudować odpowiednie zapytanie, które pasowałoby do twojego pierwszego żądania (i nie jestem wystarczająco pewny, aby je skonstruować na ślepo). Oto podejście do drugiego żądania. Jeśli się nie zepsułem, wyświetla listę wszystkich aktualizacji i stan zatwierdzenia dla wszystkich grup.

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
;

Który produkuje ten wynik w naszym niemieckim SBS:

wprowadź opis zdjęcia tutaj

W przypadku naszego SBS z 5 domyślnymi grupami daje to 121558 wierszy wyników w ~ 26 sekund. Tak więc, jeśli chcesz pobawić się zapytaniem, może być wskazana zmiana pierwszej linii na SELECT TOP 1000podczas testowania.

Poświęciłem też czas na podsumowanie tego wszystkiego w skrypcie PowerShell:

# 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

Pamiętaj, że ten skrypt zawiera SELECT TOP 10ograniczenie, aby uniknąć zalania powłoki podczas testowania.

Der Hochstapler
źródło
Z pewnością jest to coś do zbadania. Być może istnieje moduł Perla do interakcji z MS SQL Server.
John Gardeniers,
@JohnGardeniers: Dodałem skrypt PowerShell, który wykonuje zapytanie. Niestety moja znajomość języka Perl jest jeszcze gorsza :)
Der Hochstapler,
To dobry punkt wyjścia, ale będę musiał dowiedzieć się, jak zatrzymać obcinanie danych wyjściowych.
John Gardeniers
@JohnGardeniers: Tak właśnie domyślnie PowerShell wyświetla zwrócone obiekty. Możesz uruchomić skrypt tak, myscript.ps1 | flaby uzyskać inne (nie obcięte) wyjście.
Der Hochstapler,
Postanowiłem wynagrodzić cię za twój wysiłek, ale będziesz musiał poczekać 24 godziny. System nie pozwoli mi od razu przyznać nagrody.
John Gardeniers,