【问题标题】:AD password update via Powershell通过 Powershell 更新 AD 密码
【发布时间】:2020-06-01 13:31:19
【问题描述】:

Too all 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  

我要完成的工作如下:

  1. 列表项
  2. 仅使用“samAccountName”导入一列 cvs
  3. 使用随机生成的 20 个字符长的密码重置 csv 中列出的帐户的密码
  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
            
    }

帐户密码正在更新,但无法发送电子邮件

【问题讨论】:

    标签: powershell active-directory powershell-3.0 change-password


    【解决方案1】:

    当您执行$Name = $users.Name 时,$Name 变量会在 CSV 中获取包含 ALL 个用户名的数组。

    删除该行并在 ForEach-Object 循环中设置变量:

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

    注意:

    • SmtpPort 采用整数,而不是字符串
    • From 不能为空字符串

    附注尝试做一些适当的代码缩进,这样更容易看到代码块(如 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
    }
    

    【讨论】:

    • 非常感谢 Theo 的清理工作。这是错过了“删除该行,而是在 ForEach-Object 循环中设置变量:”
    • @Steven 是的,我也是这么想的,但是在电子邮件中向所有收件人发送密码对于破解帐户来说太过分了。 (想想看……在电子邮件中发送密码是否安全?)
    • @Theo 我不小心删除了之前的评论。我完全同意。我想在入职等情况下风险很小,但如果我能帮上忙,我不会选择这种方法。
    • @Steven 和 Theo,我完全同意这不是最安全的方法;但是考虑到这些只是临时密码,并且还有其他安全机制来确保只有指定用户才能访问使用该密码的平台,这使得它现在更安全一些。 P/S 可以随意分享其他选项,以安全的方式传达此类信息,不确定嵌入式链接、使用令牌等如何加固?
    【解决方案2】:

    不要接受我的回答。我只是在建立@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
    
    • 使用哈希表存储 AD 用户对象,因此您不必在每次循环迭代时重新执行 Where{}。根据用户数量,这可能会快很多。在关联 2 个来源之间的数据时,我倾向于使用哈希表。
    • 将 $Body 变量移出循环。这里的字符串不喜欢缩进,通过将其移出我们不必干扰循环缩进;提高可读性。然后在循环内部,我们可以通过替换字符串来获得实际的主体。
    • 我还将 $MailParams 参数散列放置在循环之外。然后在循环内我重置了 2 个不同的键。吹毛求疵,但我也不想在每次循环迭代时都声明哈希。
    • $重用 $newPassword 变量,而不是随意放置额外的 $newpdw 变量。
    • 扩展了别名,只是因为 PSScriptAnalyzer 抱怨它...

    显然这是未经测试的!但是,我希望它会有所帮助......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-06
      • 2014-05-17
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多