Обновление пароля AD через Powershell - PullRequest
0 голосов
/ 17 февраля 2020

Слишком все Эксперты Powershell : Мне нужна помощь, чтобы выяснить, почему это работает неправильно. Что я имею в виду неправильно, учетные записи в пароле CSV обновляются случайным паролем, и пользователям отправляется электронное письмо, но я не понимаю, почему они получают один и тот же пароль, и каждая учетная запись в AD адресована. См. Вывод электронной почты:

Электронная почта первого пользователя:

Hello Guest DefaultAccount user1, user2, user3, user4 test John Doe, 
Your AD Account user1, password has been updated to e,wQlsGfBE;J'4  

Повторное использование почты

 Hello Guest DefaultAccount user1, user2, user3, user4 test John Doe, 
Your AD Account jdoe, password has been updated to e,wQlsGfBE;J'4  

что я пытаюсь для выполнения sh:

  1. Элемент списка
  2. Импорт одного столбца cvs только с "samAccountName"
  3. сброс пароля для учетные записи, перечисленные в csv со случайным сгенерированным длинным паролем из 20 символов
  4. Отправьте на адрес электронной почты, связанный с учетной записью AD, новый пароль. (Я делаю это, потому что их адрес электронной почты отличается от их учетной записи AD), чтобы они могли получать свою электронную почту.

Import-Module ActiveDirectory
# Import AD user objects and store in users variables 
$users = Get-ADUser -Filter *  -Properties Name, EmailAddress,SamAccountName | Select SamAccountName,Name,EmailAddress
    
$Name = $users.Name
$SamAccountName = $users.SamAccountName
$EmailAddress = $users.EmailAddress

#Date
$date = (Get-Date -Format F) 

#Generate a random password and store in newpwd 
$newpwd = -join (33..126|%{[char]$_}|Get-Random -Count 20)
$newPassword = ConvertTo-SecureString -AsPlainText "$newpwd" -Force

# Import users from CSV
Import-Csv "C:\Userlist.csv" | ForEach-Object {
$samAccountName= $_."samAccountName"

        #Proceed with password reset
            Set-ADAccountPassword -Identity $samAccountName -NewPassword $newPassword -Reset
            Set-AdUser -Identity $samAccountName -ChangePasswordAtLogon $true

#Server configuration 
$smtpServer =""
$SmtpPort = ""
# sending option
$from = "it-operation@example.com"
$to = $EmailAddress 
$subject  ="AD Password updated - " + $date
$priority = "Normal"
$from = ""

$body = @"
Hello $name, <br> 
Your AD Account $samAccountName, password has been updated to $newpwd
"@
try {
# Send the report email
Send-MailMessage -To $to -Subject $subject -BodyAsHtml -body $body -SmtpServer $smtpServer -Port $SmtpPort -From $From -Priority $priority  
}
catch{
    write-warning "error in sending. $_"
}  # End User Processing
            
    }

Пароль учетной записи обновляется, но просто не может отправить emai

Ответы [ 2 ]

2 голосов
/ 17 февраля 2020

Когда вы делаете $Name = $users.Name, переменная $Name получает массив, содержащий ALL имена пользователей в CSV.

Удалите эту строку и вместо этого установите переменную внутри вашего ForEach-Object l oop:

# Import users from CSV
$UserList = Import-Csv "C:\Userlist.csv" | ForEach-Object {
    $samAccountName= $_.samAccountName
    $name = $_.Name
    # then the rest of your code
}

Примечание:

  • SmtpPort принимает целое число, а не строку
  • From не может быть пустой строкой

PS Попробуйте сделать правильный отступ кода, чтобы было гораздо легче увидеть, где начинается и заканчивается блок кода (например, ForEach-Object))


Ваш исправленный код:

Import-Module ActiveDirectory
# Import AD user objects and store in users variables 
$users = Get-ADUser -Filter *  -Properties Name, EmailAddress,SamAccountName | Select SamAccountName,Name,EmailAddress

#Date
$date = (Get-Date -Format F) 

# Import users from CSV
Import-Csv "C:\Userlist.csv" | ForEach-Object {
    # read this from the CSV
    $samAccountName= $_.samAccountName
    # get the user object from the $users array
    $user = $users | Where-Object { $_.SamAccountName -eq $samAccountName }
    $name = $user.Name
    $emailAddress = $user.EmailAddress

    #Generate a random password and store in newpwd 
    $newpwd = -join (33..126|%{[char]$_}|Get-Random -Count 14)
    $newPassword = ConvertTo-SecureString -AsPlainText "$newpwd" -Force

    $body = @"
Hello $name, <br> 
Your AD Account $samAccountName, password has been updated to $newpwd
"@

    #Proceed with password reset
    Set-ADAccountPassword -Identity $samAccountName -NewPassword $newPassword -Reset
    Set-AdUser -Identity $samAccountName -ChangePasswordAtLogon $true

    #Server configuration 
    $mailParams = @{
        SmtpServer = "YourSMTPServer"
        Port = 25  # <-- an integer value
        # sending option
        From = "it-operation@example.com"
        To = $user.EmailAddress 
        Subject  ="AD Password updated - " + $date
        Priority = "Normal"
        Body = $body
        BodyAsHtml = $true
    }
    try {
    # Send the report email
    Send-MailMessage @mailParams -ErrorAction Stop
    }
    catch{
        write-warning "error in sending. $_"
    }  # End User Processing
}
1 голос
/ 17 февраля 2020

Не принимай мой ответ. Я просто строю то, что сделал @Theo. (Хотелось бы, чтобы я проголосовал "за")

Import-Module ActiveDirectory

# Import AD user objects and store in users variables 
$Users = @{} 
Get-ADUser -Filter *  -Properties Name,EmailAddress,SamAccountName | Select-Object SamAccountName,Name,EmailAddress |
ForEach-Object{ $Users.Add( $_.samAccountName, $_ ) }

#Date
$Date = (Get-Date -Format F) 

# Generate a random password and store in newPassword 
$newPassword = -join ( 33..126 | ForEach-Object{ [char]$_ }| Get-Random -Count 20 )
$newPassword = ConvertTo-SecureString -AsPlainText "$newPassword" -Force
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Move to the loop if you want each user's pwd to be different!!!

# Put this here so you can indent the loop easier...
$BaseBody = 
@"
Hello %NAME%, <br> 
Your AD Account %SAMACCOUNTNAME%, password has been updated to %NEWPASSWORD%
"@

# Server configuration & recipien configurations...:
$MailParams = @{
    $smtpServer = "YorServer.example.com" #MAKE SURE YOU CHANGE THIS
    $SmtpPort   = 25
    $from       = "it-operation@example.com"
    $To         = ""
    $subject    ="AD Password updated - " + $date
    $Body       = ""
}
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Removed -Priority if it's alwasy going to be normal you don't need it.

# Import users from CSV
Import-Csv "C:\Userlist.csv" | 
ForEach-Object {
    $samAccountName = $_."samAccountName"

    # Proceed with password reset
    Set-ADAccountPassword -Identity $samAccountName -NewPassword $newPassword -Reset
    Set-ADUser -Identity $samAccountName -ChangePasswordAtLogon $true

    # Get the Name & Email address from the $Users Hash...:
    $EmailAddress = $Users[$samAccountName].EmailAddress
    $Name         = $Users[$samAccountName].Name

    # Reset the To & Body values
    $MailParams['To']   = $EmailAddress
    $MailParams['Body'] = $BaseBody.Replace('%NAME%', $Name).Replace('%SAMACCOUNTNAME%', $samAccountName).Replace('%NEWPASSWORD%', $newPassword)    

    try { # Send the report email
        Send-MailMessage @MailParams -ErrorAction Stop
    }
    catch{
        write-warning "Error in sending : $_"
    }
} # End User Processing
  • Использовал таблицу ha sh для хранения пользовательских объектов AD, чтобы вам не приходилось повторно выполнять Where {} на каждой итерации l oop. В зависимости от количества пользователей это может быть немного быстрее. При сопоставлении данных между 2 источниками я тяготею к таблицам ha sh.
  • Переместил переменную $ Body из l oop. Здесь строки не любят иметь отступы, перемещая их, мы не должны вмешиваться в отступ l oop; улучшение читаемости. Затем внутри l oop мы можем получить фактическое тело, выполнив некоторую замену строки.
  • Я также поместил параметр $ MailParams ha sh вне l oop. Затем внутри l oop я сбрасываю 2 клавиши, которые меняются. Плохо, но я бы лучше не объявлял ha sh на каждой итерации l oop.
  • $ Повторно использовал переменную $ newPassword вместо того, чтобы лишняя переменная $ newpdw просто лежала вокруг.
  • Расширен псевдонимы только потому, что PSScriptAnalyzer жалуется на это ...

Очевидно, что это не проверено! Но я надеюсь, что это полезно ...

...