tak na prawdę to kolejna lekcja zabawy hashtablami i ciągami. scenariusz w moim przypadq był taki, żeby zweryfikować jakie konta należą do grupy lokalnych adminów na stacjach roboczych. skrypt logowania wrzucił zawartość grupy do bazy danych, potem pobrałem sobie dane do zmiennej $DataSet.Tables[0] . teraz trzeba wygenerować raport “wypisz wszystkie komputery, na których ktoś należy do adminów a nie powinien, z informacją jakie to konto”. rozwiązanie jest takie:

#connection objects
$sqlconnection=New-Object system.data.sqlclient.sqlconnection
$sqlcmd= New-Object System.Data.SqlClient.SqlCommand
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$DataSet = New-Object System.Data.DataSet

#connect MYDATABASE on MYSQLSERVER
$sqlconnection.ConnectionString="Server=MYSQLSERVER;database=MYDATABASE;Integrated Security=True"
$sqlcmd.CommandText="select * from TABLENAME"
$sqlcmd.Connection=$sqlconnection
$SqlAdapter.SelectCommand = $SqlCmd
#that is strange way of getting results - they are popullated into $dataset array. 
$SqlAdapter.Fill($DataSet)|out-null


#now when we have everything in an array so we can manipulate on data
#first define hashtable for computers with admin accounts
$unsecure=@{};
foreach ($row in $DataSet.Tables[0]) {
    #how to remove correct group/user names from check? one can try to 
    #operate on strings but it's so... bueee
    #it's easier and nicer to have an object for comparison. hashtable is perfect
    $splitrow=@{};

    #column 1 in my database contains memberof information separated with semicolon
    #f.ex. 'domain admins;administrator;non-admin-user;'
    #so change this string into a hashtable:
    $row[1].split(";")|%{$splitrow.add($_,0)}
    #the second parameter is obligatory to fill but tottaly unimportant in this situation. 
    #so i put '0' but could be anything.
    #now it's easy to remove correct entries which are not interesting for this task
    $splitrow.Remove("administrator");
    $splitrow.Remove("Domain Admins");
    $splitrow.Remove("grupa_operatorow");
    $splitrow.Remove("specjalna_grupa");
    #as there is ';' on the end it will always produce one additional, empty record. 
    $splitrow.Remove("");

    #if there are any unwanted logins, the number will be greater then 0
    if ($splitrow.count -gt 0) {
        #add entry to final table. i want to have it back as a string so -join is going to be helpful
        $unsecure.add($row[0],$splitrow.keys -join ";")
    } else {
        #out of interest - just informational
        echo "KOMPUTER: $($row[0]) jest ok";
    }

}

#now print information to a file
$unsecure.count|out-file c:tempadmins.txt
$unsecure.getEnumerator()|Sort-Object name|out-file c:tempadmins.txt -append

czego można się nauczyć z tego skryptu?

  • jak połączyć się z bazą
  • jak pobrać i operować na wynikach
  • jak radzić sobie z hashtablami
  • szczególnie ciekawy jest sposób sortowania – gdzie użyty jest getEnumerator. zwykłe $unsecure|Sort-Object nie zahula

sposób być może nie jest optymalny więc będę wdzięczny za sugestie i alternatywne rozwiązania (:

eN.

-o((:: sprEad the l0ve ::))o-

Comments (2)

  1. Odpowiedz

    Ja jakoś osobiscie nie lubie datasetów – wole datareadery, które wiem jak się zachowują i jak allokuja pamięć, i jak sprawdzają sie w przeszukiwaniu dużych zbiorów danych.
    Ogólnie moje rozwiązanie wyglądałoby tak:

    $cn = new-object System.Data.SqlClient.SqlConnection(“Server=QUESTKPSQLEXPRESS;database=test;Integrated Security=True“);
    $cn.Open()
    $cmd = new-object „System.Data.SqlClient.SqlCommand” (“select * from Table_2“, $cn)
    $dr = $cmd.ExecuteReader()
    $unsecure=@{};
    while ($dr.Read()) {
    $groups = $dr.GetValue(1).toLower()
    $groups = $groups.Replace(„administrator”,””).Replace(„domain admins”,””).Replace(„grupa_operatorow”,””)
    $groups = $groups.Replace(„grupa_operatorow“,””).Replace(„specjalna_grupa”,””).Replace(„;;”,””)
    if ($groups.Length -gt 1){ $unsecure.add($dr.GetValue(0),$groups.Remove($groups.Length-1))}
    else {echo “KOMPUTER: $($dr.GetValue(0)) jest ok“;}
    }
    $dr.Close()
    $cn.Close()
    $unsecure

  2. nExoR

    Odpowiedz

    @peki: jesli chodzi o polaczenie do bazy do sie zgodze. co do pracy na stringach… strasznie sie boje takich rzeczy robic bo sa totalnie nieodporne na najmniejsze nawet roznice – zapomnisz to lower, gdzies zapodzieje sie spacja wiec trzeba trim(), zmieni sie kodowanie czy inne cos… operacje na obiekcie daja mi wiekszosc elastycznosc ale przede wszystkim determinizuje zachowanie i daje lepsza obsluge.

    niemniej dzieki za alternatywne rozwiazanie (: to rzuca nowe światło

Skomentuj nExoR Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Time limit is exhausted. Please reload CAPTCHA.