Jump to content

Powershell Skript für Kennwortalter


Recommended Posts

Hallo,

 

ich bin neu im Administratorenbereich und erst recht was Skripten mit Powershell betrifft. Nach Einsteigernbüchern und einen Onlinegrundkurd habe ich folgende Aufgabe bekommen: 

Eine Info-E-Mail an die Benutzer senden , wenn ihr Kennwort ein Jahr alt geworden ist (ohne es zu ändern). Die E-Mail soll über das alter Informieren und die Benutzer darauf hinweisen, dass das Kennwort bitte zu ändern ist wenn es öffentlich bekannt wurde. Der Kennwortwechsel soll nicht erzwungen werden!

Die Info soll immer zum Geburtstag des Kennwortes kommen, also auch bei zwei Jahre, drei Jahre, ...

 

Das Auslesen und Berechnen des Kennwortalters klappt ganz gut mit folgendem Skript:

 

Import-Module -Name ActiveDirectory

#Variablen
$TodayTime = Get-Date
$null = Get-Date -UFormat '%d.%m.%Y' 
$WarningLevel = 365
$UsersWithOldPasswordFromAD = New-Object  -TypeName System.Collections.ArrayList
$UsersWithOldPasswordFromFile = New-Object -TypeName System.Collections.ArrayList
$FileArray = New-Object -TypeName System.Collections.ArrayList

# PW Versandliste
[String]$StatusFile = '//abc.own/NETLOGON/Passwort.csv'
If (!(Test-Path -Path ('{0}' -f $StatusFile))) {
    New-Item -Path '//abc.own/NETLOGON' -Name 'Passwort.csv' -ItemType 'file'
}

#alle aktiven AD-User mit E-Mail-Adresse (außer Systembenutzer)
$AllADUsers = Get-ADUser -Filter { Enabled -eq $True -and PasswordNeverExpires -eq $False -and Mail -like '*@abc.*' } -Properties PasswordLastSet,Mail 

#Berechnung des Kennwortalters
ForEach ($ADUser in  $AllADUsers)
{
    $NutzerName = $ADUser.SamAccountName
    $null = $ADUser.Mail
    $PasswordLastSet = $ADUser.PasswordLastSet

    # Wenn Benutzer von Admins in der AD erstellt wurden, und das Initial-Passwort vom Benutzer noch nicht geändert wurde, dann ist PasswordLastSet nicht gesetzt (NULL)
    # In diesem Fall, setzten wir PasswordLastSet auf Heute, damit die Berechnung "0" ergibt
    If(! $PasswordLastSet) {
    $PasswordLastSet = $TodayTime
    }
    $PasswordAge = ($TodayTime-$PasswordLastSet).Days

    if  ($PasswordAge -ge $WarningLevel) 
    {
    $UsersWithOldPasswordFromAD += $ADUser.SamAccountName 
    }
     

}

Wo ich jetzt aber scheitere ist diese User in Datei schreiben, wenn diese noch nicht drin stehen, und wenn sie drin stehen mit dem Datum zu vergleichen, wann sie die letzte Mail bekommen haben. Da diese Skript jeden Tag laufen soll und wir die User nicht zu bombadieren wollen. Mein Ansatz dafür ist

# Datei mit historischen Daten einlesen
foreach($line in (Get-Content $StatusFile2)) {
    $FileArray += $line
  
}
  
foreach ($ADUser in $UsersWithOldPasswordFromAD)
{
    foreach ($line in $FileArray) {
        #$FileUser = Import-Csv "$Statusfile2" -Header name
        #$FileDate = Import-Csv "$Statusfile2" -Header datum
        
        if($ADUser -ne $FileArray.name) 
        {
          Write-Host "$ADUser steht drin"
        }

Wenn jemand mir auf die Sprünge helfen kann?  

Link to post

Zum Prüfen, ob ein Element in einer Sammlung enthalten ist, gibt es die Operatoren -in /-notin bzw. -contains/-notcontains .

 

Wenn es Dir nur darum geht, ein Array mit Elementen zu ergänzen, die noch nicht drin sind, hier sind einige Techniken zusammengefasst: https://it-pro-berlin.de/2017/08/powershell-wie-schnell-sind-arrays/

 

EDIT: OK, habe jetzt gesehen, dass Du das Datum mitführen willst. Das kannst Du mit einem Custom Object machen, der die Properties sAMAccountName und LastDate hat.  Also praktisch statt 

 if  ($PasswordAge -ge $WarningLevel) 
    {
    $UsersWithOldPasswordFromAD += $ADUser.SamAccountName 
    }

so etwas wie

if  ($PasswordAge -ge $WarningLevel) {
    $UsersWithOldPasswordFromAD += [PSCustomObject]@{
      	'sAMAccountName' = $ADUser.SamAccountName
        'LastDate' = Get-Date
      }
}

Dann packst Du das alles in eine CSV mit Export-CSV. Beim nächsten Durchlauf importierst Du die CSV mit Import-CSV und machst in der Schleife dann so etwas wie

$existingEntry = $UsersFromCSV.Where({$_.sAMAccoutnName -eq  $ADUser.SamAccountName})
if ($existingEntry.Count -gt 0) {
	$LastReminderDays = ((Get-Date) - $existingEntry[0].LastDate).Days
    # je nachdem,  wie lange her, nochmal erinnern und Datum aktualisieren
} else {
	# anfügen
}

 

Edited by cj_berlin
Link to post

Es geht mir nicht nur um das Ergänzen, sondern das die Datei, welche gespeichert wird mit den ausgelesenen Usern verglichen wird und wenn sie noch nicht drauf stehen mit einem E-Mailversanddatum versehen werden. Und somit bei einem erneuten durchlauf nicht überschrieben werden. Sondern erst nach einem weiteren Jahr.

Link to post

Hi,

 

ein wenig OT: Ich würde den Bezug zum Kennwortalter einfach weglassen und die User (un)regelmäßig informieren / schulen / sensibilisieren, dass beim Verdacht der Kennwort Kompromittierung das Passwort ASAP zu ändern (und IT / GL / Manager zu informieren) ist.

 

Gruß

Jan

Link to post
vor 3 Minuten schrieb testperson:

Hi,

 

ein wenig OT: Ich würde den Bezug zum Kennwortalter einfach weglassen und die User (un)regelmäßig informieren / schulen / sensibilisieren, dass beim Verdacht der Kennwort Kompromittierung das Passwort ASAP zu ändern (und IT / GL / Manager zu informieren) ist.

 

Gruß

Jan

Hallo Jan,

 

grundsätzlich gebe ich dir Recht und die Mitarbeiter sind bei Kompromittierung angehalten sofort ihr Passwort zu ändern. Aber meine GL möchte, das trotz neuen BSI-IT-Grundschutz Kompendium, wo keine Passwörter mehr ablaufen sollten, die Kollegen jedes Jahr es doch ändern sollten. Und daran soll ich sie per Mail erinnern

vor 29 Minuten schrieb cj_berlin:

Zum Prüfen, ob ein Element in einer Sammlung enthalten ist, gibt es die Operatoren -in /-notin bzw. -contains/-notcontains .

 

Wenn es Dir nur darum geht, ein Array mit Elementen zu ergänzen, die noch nicht drin sind, hier sind einige Techniken zusammengefasst: https://it-pro-berlin.de/2017/08/powershell-wie-schnell-sind-arrays/

 

EDIT: OK, habe jetzt gesehen, dass Du das Datum mitführen willst. Das kannst Du mit einem Custom Object machen, der die Properties sAMAccountName und LastDate hat.  Also praktisch statt 


 if  ($PasswordAge -ge $WarningLevel) 
    {
    $UsersWithOldPasswordFromAD += $ADUser.SamAccountName 
    }

so etwas wie


if  ($PasswordAge -ge $WarningLevel) {
    $UsersWithOldPasswordFromAD += [PSCustomObject]@{
      	'sAMAccountName' = $ADUser.SamAccountName
        'LastDate' = Get-Date
      }
}

Dann packst Du das alles in eine CSV mit Export-CSV. Beim nächsten Durchlauf importierst Du die CSV mit Import-CSV und machst in der Schleife dann so etwas wie


$existingEntry = $UsersFromCSV.Where({$_.sAMAccoutnName -eq  $ADUser.SamAccountName})
if ($existingEntry.Count -gt 0) {
	$LastReminderDays = ((Get-Date) - $existingEntry[0].LastDate).Days
    # je nachdem,  wie lange her, nochmal erinnern und Datum aktualisieren
} else {
	# anfügen
}

 

Vielen Dank für den Ansatz nur bekomme ich in der CSV diese Einträge:

Count          : 208
Length         : 208
LongLength     : 208
Rank           : 1
SyncRoot       : System.Object[]
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Mit folgender Skriptzeile habe die CSV exportiert:

 

export-csv -Path $StatusFile -InputObject $UsersWithOldPasswordFromAD

 

 

  • Confused 1
Link to post
vor 2 Minuten schrieb Mildred:

Aber meine GL möchte, das trotz neuen BSI-IT-Grundschutz Kompendium, wo keine Passwörter mehr ablaufen sollten, die Kollegen jedes Jahr es doch ändern sollten. Und daran soll ich sie per Mail erinnern

Dann würde ich den Ablauf einfach aktiviert lassen (und den Chef auf "Bl*dsinn" hinweisen)?! Meiner Erfahrung nach ändert niemand sein Passwort nur weil eine E-Mail ihn dazu bewegen möchte. ;)

  • Like 1
Link to post
vor 7 Minuten schrieb Dukel:

Dann verschickt einmal im Jahr (automatisch) eine eMail an alle. Da ist es doch egal, wann die Mitarbeiter das Kenntwort geändert haben.

Auch eine Möglichkeit. Nur soll die Aufgabe auch dazu da sein, meine mühseelig erlernten PowerShell Grundkenntnisse praktisch anzuwenden. Nur stehe ich komplett auf dem Schlauch.

 

Link to post
vor einer Stunde schrieb Mildred:

Vielen Dank für den Ansatz nur bekomme ich in der CSV diese Einträge:

Count          : 208
Length         : 208
LongLength     : 208
Rank           : 1
SyncRoot       : System.Object[]
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Mit folgender Skriptzeile habe die CSV exportiert:

 


export-csv -Path $StatusFile -InputObject $UsersWithOldPasswordFromAD

 

 

Was bekommst Du denn ausgegeben, wenn Du $UsersWithOldPasswordFromAD einfach an die Konsole ausgibst?

 

EDIT: Ach, ich sehe: ArrayList... Mach mal für einen schnellen Test einfach ein Array daraus:

 $UsersWithOldPasswordFromAD = @()

 

Edited by cj_berlin
Link to post
Gerade eben schrieb cj_berlin:

Zeig mal wieder das komplette Skript mit allen Änderungen.

Den Fehler habe ich gefunden, das es zumindest in der Anzeige passt. Und nun klappt es auch mit der CSV

#!/usr/bin/env powershell
Import-Module -Name ActiveDirectory

#Variablen
$TodayTime = Get-Date
$Today = Get-Date -UFormat '%d.%m.%Y' 
$WarningLevel = 365
$UsersWithOldPasswordFromAD = New-Object  -TypeName System.Collections.ArrayList
$UsersWithOldPasswordFromFile = New-Object -TypeName System.Collections.ArrayList
$FileArray = New-Object -TypeName System.Collections.ArrayList

# PW Versandliste
[String]$StatusFile = '//aa.own/NETLOGON/Passwort.csv'
If (!(Test-Path -Path ('{0}' -f $StatusFile))) {
    New-Item -Path '//aa.own/NETLOGON' -Name 'Passwort.csv' -ItemType 'file'
}

#alle aktiven AD-User mit E-Mail-Adresse (außer Systembenutzer)
$AllADUsers = Get-ADUser -Filter { Enabled -eq $True -and PasswordNeverExpires -eq $False -and Mail -like '*@aa.*' } -Properties PasswordLastSet,Mail 

#Berechnung des Kennwortalters
ForEach ($ADUser in  $AllADUsers)
{
    $NutzerName = $ADUser.SamAccountName
    $null = $ADUser.Mail
    $PasswordLastSet = $ADUser.PasswordLastSet

    # Wenn Benutzer von Admins in der AD erstellt wurden, und das Initial-Passwort vom Benutzer noch nicht geändert wurde, dann ist PasswordLastSet nicht gesetzt (NULL)
    # In diesem Fall, setzten wir PasswordLastSet auf Heute, damit die Berechnung "0" ergibt
    If(! $PasswordLastSet) {
    $PasswordLastSet = $TodayTime
    }
    $PasswordAge = ($TodayTime-$PasswordLastSet).Days

    if  ($PasswordAge -ge $WarningLevel) 
    {
    $UsersWithOldPasswordFromAD += [PSCustomObject]@{
      	'sAMAccountName' = $NutzerName
        'E-MailVersand' = $Today
    }
     

}
}

Write-Host 
$UsersWithOldPasswordFromAD | Export-Csv -Path $StatusFile -NoTypeInformation 

Aber jetzt fehlt mir folgendes. Wenn ich danach wieder die CSV einlese und mit deinen Tipps weiterbearbeite , habe ich nun folgenden Gedanken. Wenn ich das Skript ein 2. Mal durchlaufen lasse, überschreibt es mir doch das "alte" Datum oder?

Link to post
vor 3 Minuten schrieb Mildred:

Aber jetzt fehlt mir folgendes. Wenn ich danach wieder die CSV einlese und mit deinen Tipps weiterbearbeite , habe ich nun folgenden Gedanken. Wenn ich das Skript ein 2. Mal durchlaufen lasse, überschreibt es mir doch das "alte" Datum oder?

Du musst die CSV vorher importieren und beim Durchlauf der Schleife abgleichen:

  • Ist der User nicht drin, hinzufügen,
  • ist der User drin und die letzte Erinnerung ist noch frisch, nix machen,
  • ist der User drin und die letzte Erinnerung zu alt, aktualisieren und Mail schicken
  • Like 1
Link to post

Hallo cj_berlin,

 

ich hab die CSV Importiert, habe aber das Problem, das das Datum generell umgeschrieben wird. Mein Skript dazu sieht wie folgt aus:

Import-Csv $StatusFile
$existingEntry = $UserFromCSV.Where({$_.sAMAccountName -eq $ADUser.SamAccountName})
if ($existingEntry.count -gt 0)
    {
       $LastReminderDays = ((Get-Date) - $existingEntry[0].EMailversand).Days 
       if ($LastReminderDays -gt 365)
       { $UsersWithOldPasswordFromAD += [PSCustomObject]@{
         'EMailVersand' = Get-Date -UFormat '%d.%m.%Y'
        }
        }
        }
else {$UsersWithOldPasswordFromAD += [PSCustomObject]@{
      	'sAMAccountName' = $NutzerName
        
    }
    }
            
$UsersWithOldPasswordFromAD | Export-Csv -Path $StatusFile -NoTypeInformation

 

Link to post

Moin,

 

$existingEntry[0].EMailversand enthält kein Datum. Daher wird vermutlich $LastReminderDays nicht richtig berechnet. Ansonsten aktualisierst Du ja nicht den Eintrag in den importierten Daten, sondern fügst immer einen neuen an.

 

Hier musst Du noch an der Logik arbeiten, ich habe sie in Worten ja beschrieben.

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...