VMware Cloud Community
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

Add ESXi in Doamin & chnage password of root

Hi ,

I am looking for a script for below task in powercli

1- Script to add all ESXi Hosts in a vCenter to Domain for authentication (script should have an option to re-add a host to domain if it was already part of domain, but authentication is failing)

2- Retrieve last date of root password change from all ESXi hosts in a vCenter

3- Change the root password (with a randomly generated password meeting password complexity policy) of all ESXi hosts if the last password change date is more than 80 days and generate the output with the new passwords to update in password repository.

Tags (2)
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try like this

Function MakeUp-String([Int]$Size = 8, [Char[]]$CharSets = "ULNS", [Char[]]$Exclude) {

    $Chars = @(); $TokenSet = @()

    If (!$TokenSets) {$Global:TokenSets = @{

        U = [Char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ'                                #Upper case

        L = [Char[]]'abcdefghijklmnopqrstuvwxyz'                                #Lower case

        N = [Char[]]'0123456789'                                                #Numerals

        S = [Char[]]'!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'                         #Symbols

    }}

    $CharSets | ForEach {

        $Tokens = $TokenSets."$_" | ForEach {If ($Exclude -cNotContains $_) {$_}}

        If ($Tokens) {

            $TokensSet += $Tokens

            If ($_ -cle [Char]"Z") {$Chars += $Tokens | Get-Random}             #Character sets defined in upper case are mandatory

        }

    }

    While ($Chars.Count -lt $Size) {$Chars += $TokensSet | Get-Random}

    ($Chars | Sort-Object {Get-Random}) -Join ""                                #Mix the (mandatory) characters and output string

}

# Input file CSV, layout

#

# Name,User,Password

# esx1,root,password123

$report = @()

foreach($line in Import-Csv -Path .\esxNames.csv -UseCulture){

    Get-VMHost -Name $line.Name |

    ForEach-Object -Process {

        $esx = $_

        $pswd = $line.Password

      

        # Leave domain when joined  

        $leave = Get-VMHostAuthentication -VMHost $esx | where{$_.Domain -eq $domainName} |

         Set-VMHostAuthentication -LeaveDomain -Confirm:$false

        Write-Output "$($esx.Name) left domain"

  

        # Join domain

        $adCred = Get-Credential -Message "Please provide crdentials for the AD domain join"

          

        $join = Get-VMHostAuthentication -VMHost $esx |

         Set-VMHostAuthentication -Domain $domainName -JoinDomain -Credential $adCred -Confirm:$false

        Write-Output "$($esx.Name) joined domain"

  

        # Find (if any) root password change in last 80 days

        $pswdChange = Get-Vievent -Start (Get-Date).AddDays(-80) -MaxSamples ([int]::MaxValue) |

        Where{$_ -is [VMware.Vim.UserPasswordChanged] -and

              $_.UserName -eq $line.User -and

              $_.Host.Name -eq $esx.Name}

        if(-not $pswdChange){

            $pswd = MakeUp-String -Size 7  

            $srv = Connect-VIServer -Server $line.Name -User $line.User -Password $line.Password 4> $null

            if($srv){

                try{

                    Set-VMHostAccount -UserAccount $line.User -Password $pswd -Server $srv -Confirm:$false | Out-Null

                    Write-Output "ESXi: $($esx.Name)  Password: $pswd"

                }

                Catch{

                    Write-Output "Password change failed on $($esx.Name)"

                    $pswd = $line.Password

                }

                Disconnect-VIServer -Server $esx.Name -Confirm:$false

            }

        }

        else{

            $lastPswdChange = $pswdChange | Sort-Object -Property CreatedTime -Descending | Select -First 1

            Write-Output "Password on $($esx.Name) not changed. Last password change on $($lastPswdChange.CreatedTime)"

        }

  

        # Add AD group

        $groupName = Read-Host -Prompt "Provide AD group to be added as Admin (domain\group)"

        $srv = Connect-VIServer -Server $esx.Name -User $line.User -Password $pswd 4> $null

        $localEsx = Get-VMHost -Server $srv

        $role = Get-VIRole -Server $srv -Name Admin

        New-VIPermission -Principal $groupName -Role $role -Entity $localEsx -Confirm:$false

        Disconnect-VIServer -Server $esx.Name -Confirm:$false

        # Output

        $report += [pscustomobject]@{

            Name = $line.Name

            User = $line.User

            Password = $pswd

        }

    }

}

$report | Export-Csv -Path .\new-esxNames.csv -NoTypeInformation -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
31 Replies
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

LucD​  I believe you can help me here to get it done .  i i would appreciate your help

Thanks

Dharm

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this.
You will need to provide the root password, the domainname, a domain admin and a domain admin password.
The Create-Password function to generate the password comes from Create-Password

$rootPswd = 'VMware1!'

$domainName = 'my.domain'

$domainAdmin = 'Administrator'

$domainAdminPswd = 'Microsoft1!'

Function Create-Password { # https://powersnippets.com/create-password/

[CmdletBinding()]Param ( # Version 01.01.00, by iRon

[Int]$Size = 8, [Char[]]$Complexity = "ULNS", [Char[]]$Exclude

)

$AllTokens = @(); $Chars = @(); $TokenSets = @{

UpperCase = [Char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

LowerCase = [Char[]]'abcdefghijklmnopqrstuvwxyz'

Numbers   = [Char[]]'0123456789'

Symbols   = [Char[]]'!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'

}

$TokenSets.Keys | Where {$Complexity -Contains $_[0]} | ForEach {

$TokenSet = $TokenSets.$_ | Where {$Exclude -cNotContains $_} | ForEach {$_}

If ($_[0] -cle "Z") {$Chars += $TokenSet | Get-Random} #Character sets defined in uppercase are mandatory

$AllTokens += $TokenSet

}

While ($Chars.Count -lt $Size) {$Chars += $AllTokens | Get-Random}

($Chars | Sort-Object {Get-Random}) -Join "" #Mix the (mandatory) characters and output string

}

Get-VMHost -Name esx* |

ForEach-Object -Process {

    $esx = $_

   

    # Place ESXi node in maintenance mode

    Set-VMHost -VMHost $esx -State Maintenance -Confirm:$false | Out-Null

    while($esx.State -ne 'maintenance'){

        sleep 5

        $esx = Get-VMHost -Name $esx.Name

    }

    Write-Output "$($esx.Name) in maintenance mode"

    # Leave domain when joined   

    $leave = Get-VMHostAuthentication -VMHost $esx | where{$_.Domain -eq $domainName} |

     Set-VMHostAuthentication -LeaveDomain -Confirm:$false

    Write-Output "$($esx.Name) left domain"

    # Join domain

    $join = Get-VMHostAuthentication -VMHost $esx |

     Set-VMHostAuthentication -Domain $domainName -JoinDomain -Username $domainAdmin -Password $domainAdminPswd -Confirm:$false

    Write-Output "$($esx.Name) joined domain"

    # Take ESXi node out of maintenance mode

    Set-VMHost -VMHost $esx.Name -State Connected -Confirm:$false | Out-Null

    while($esx.State -ne 'connected'){

        sleep 5

        $esx = Get-VMHost -Name $esx.Name

    }

    Write-Output "$($esx.Name) is connected"

    # Find (if any) root password change in last 80 days

    $pswdChange = Get-Vievent -Start (Get-Date).AddDays(-80) |

    Where{$_ -is [VMware.Vim.UserPasswordChanged] -and

          $_.UserName -eq 'root' -and

          $_.Host.Name -eq $esx.Name}

    if(-not $pswdChange){

        $newPswd = Create-Password -Size 7   

        $srv = Connect-VIServer -Server $esx.Name -User root -Password $pswd 4> $null

        if($srv){

            try{

                Set-VMHostAccount -UserAccount root -Password $newPswd -Server $srv -Confirm:$false | Out-Null

                Write-Output "ESXi: $($esx.Name)  Password: $newPswd"

            }

            Catch{

                Write-Output "Password change failed on $($esx.Name)"

            }

            Disconnect-VIServer -Server $esx.Name -Confirm:$false

        }

    }

    else{

        Write-Output "Password on $($esx.Name) not changed"

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

Thanks for quick help . I will check and update you the result .

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

Hey ,

Thanks again for script , I would request you if you can make below little change in the script . Thanks in advance

1- Input of ESX and ESX username ESX Password should come from one file as we have different password of all esxi server  file  format - esx1,root,password123

2- AD Domain join user & password ask for user input

3- add as ESX in to security AD group that name will be again user input

4- some ESX are already in domain but when we try to login with AD domain access it got failed so that esxi also rejoin the AD

4- Want all these change without maintenance mode

5- in the last give me the output file with esxi hostname , username and new password which i can use for next time password change : file  format - esx1,root,password123

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Most of these additional requests, except 3, are quite trivial.
Is there none of these that you can do yourself?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

yea , i can try but so good to do that .

1- We just need to take esxi input from file , Domain and Group , Vcenter input from user

2- add in AD Group i got from one of your old post , like below

  

# Give group Admin permission

$role = Get-VIRole -Server $esxSrv -Name $roleName

$account = Get-VIAccount -Domain $domainName -Id $groupName -Group

New-VIPermission -Principal $account -Role $role -Entity $esx -Confirm:$false

 

3- Domain authentication check , unable to find the way

4 output file copy the same file just update  the new password .

I can try but i m very slow in that if you can do , that would be very helpful for me

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, so 3) meant that you wanted to use an AD group to assign a permission on the ESXi.
From the text understood the reverse, add the ESXi entry in AD to an AD group.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

I am looking for "  AD security group which should be added to administrators group of ESXi  "

that AD security group will be entered as a user input

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try like this

Function MakeUp-String([Int]$Size = 8, [Char[]]$CharSets = "ULNS", [Char[]]$Exclude) {

    $Chars = @(); $TokenSet = @()

    If (!$TokenSets) {$Global:TokenSets = @{

        U = [Char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ'                                #Upper case

        L = [Char[]]'abcdefghijklmnopqrstuvwxyz'                                #Lower case

        N = [Char[]]'0123456789'                                                #Numerals

        S = [Char[]]'!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'                         #Symbols

    }}

    $CharSets | ForEach {

        $Tokens = $TokenSets."$_" | ForEach {If ($Exclude -cNotContains $_) {$_}}

        If ($Tokens) {

            $TokensSet += $Tokens

            If ($_ -cle [Char]"Z") {$Chars += $Tokens | Get-Random}             #Character sets defined in upper case are mandatory

        }

    }

    While ($Chars.Count -lt $Size) {$Chars += $TokensSet | Get-Random}

    ($Chars | Sort-Object {Get-Random}) -Join ""                                #Mix the (mandatory) characters and output string

}

# Input file CSV, layout

#

# Name,User,Password

# esx1,root,password123

$report = @()

foreach($line in Import-Csv -Path .\esxNames.csv -UseCulture){

    Get-VMHost -Name $line.Name |

    ForEach-Object -Process {

        $esx = $_

        $pswd = $line.Password

      

        # Leave domain when joined  

        $leave = Get-VMHostAuthentication -VMHost $esx | where{$_.Domain -eq $domainName} |

         Set-VMHostAuthentication -LeaveDomain -Confirm:$false

        Write-Output "$($esx.Name) left domain"

  

        # Join domain

        $adCred = Get-Credential -Message "Please provide crdentials for the AD domain join"

          

        $join = Get-VMHostAuthentication -VMHost $esx |

         Set-VMHostAuthentication -Domain $domainName -JoinDomain -Credential $adCred -Confirm:$false

        Write-Output "$($esx.Name) joined domain"

  

        # Find (if any) root password change in last 80 days

        $pswdChange = Get-Vievent -Start (Get-Date).AddDays(-80) -MaxSamples ([int]::MaxValue) |

        Where{$_ -is [VMware.Vim.UserPasswordChanged] -and

              $_.UserName -eq $line.User -and

              $_.Host.Name -eq $esx.Name}

        if(-not $pswdChange){

            $pswd = MakeUp-String -Size 7  

            $srv = Connect-VIServer -Server $line.Name -User $line.User -Password $line.Password 4> $null

            if($srv){

                try{

                    Set-VMHostAccount -UserAccount $line.User -Password $pswd -Server $srv -Confirm:$false | Out-Null

                    Write-Output "ESXi: $($esx.Name)  Password: $pswd"

                }

                Catch{

                    Write-Output "Password change failed on $($esx.Name)"

                    $pswd = $line.Password

                }

                Disconnect-VIServer -Server $esx.Name -Confirm:$false

            }

        }

        else{

            $lastPswdChange = $pswdChange | Sort-Object -Property CreatedTime -Descending | Select -First 1

            Write-Output "Password on $($esx.Name) not changed. Last password change on $($lastPswdChange.CreatedTime)"

        }

  

        # Add AD group

        $groupName = Read-Host -Prompt "Provide AD group to be added as Admin (domain\group)"

        $srv = Connect-VIServer -Server $esx.Name -User $line.User -Password $pswd 4> $null

        $localEsx = Get-VMHost -Server $srv

        $role = Get-VIRole -Server $srv -Name Admin

        New-VIPermission -Principal $groupName -Role $role -Entity $localEsx -Confirm:$false

        Disconnect-VIServer -Server $esx.Name -Confirm:$false

        # Output

        $report += [pscustomobject]@{

            Name = $line.Name

            User = $line.User

            Password = $pswd

        }

    }

}

$report | Export-Csv -Path .\new-esxNames.csv -NoTypeInformation -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

Hi ,

Thank for help , I will test and update you .Just for my understanding , are we testing below point in the script  and yes which command

4- some ESX are already in domain but when we try to login with AD domain access it got failed so that esxi also rejoin the AD

is this for above point ?

Set-VMHostAuthentication -LeaveDomain -Confirm:$false

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

If the ESXi node is already joined to the domain, the ESXi node will indeed first leave the domain.

Before re-joining.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

Yes but only in that case where Domain authentication getting failed. Can we make a check for that as well before leaving the esxi which is in domain . 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

And how would you identify a domain authentication failure?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

For that i am not sure ,

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

In that case, what is wrong in leaving/joining the domain, when the ESXi node was already joined?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

We are using ESX 5.5 , I tested the script . It is working fine for Domain join and AD group but it is changing the password for all esx host even there password is one day old and also not saving that password record in the report file .

could you pls check

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Which version of the script are you testing?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dharmendrarhce
Enthusiast
Enthusiast
Jump to solution

I am using below script , i did little bit change in that . Domain join is working fine ,

1- Script changing password for each host even we changed the password today

2- as password got changed so AD group is not adding in   ESX , throwing error , authentication failed

3- out put report file is getting created blank even it is changing the password

======================================

Function MakeUp-String([Int]$Size = 8, [Char[]]$CharSets = "ULNS", [Char[]]$Exclude) {

    $Chars = @(); $TokenSet = @()

    If (!$TokenSets) {$Global:TokenSets = @{

        U = [Char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ'                                #Upper case

        L = [Char[]]'abcdefghijklmnopqrstuvwxyz'                                #Lower case

        N = [Char[]]'0123456789'                                                #Numerals

        S = [Char[]]'!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'                         #Symbols

    }}

    $CharSets | ForEach {

        $Tokens = $TokenSets."$_" | ForEach {If ($Exclude -cNotContains $_) {$_}}

        If ($Tokens) {

            $TokensSet += $Tokens

            If ($_ -cle [Char]"Z") {$Chars += $Tokens | Get-Random}             #Character sets defined in upper case are mandatory

        }

    }

    While ($Chars.Count -lt $Size) {$Chars += $TokensSet | Get-Random}

    ($Chars | Sort-Object {Get-Random}) -Join ""                                #Mix the (mandatory) characters and output string

}

$vcenter = Read-Host - Prompt "Provide Vcenter Name "

$vcenterCred = Get-Credential -Message "Please provide crdentials for the Vcenter "

#connect the Vcenter

Connect-VIServer -Server $vcenter -Credential $vcenterCred -Confirm:$false

# Input file CSV, layout

#

# Name,User,Password

# esx1,root,password123

$report = @()

   $domainName = Read-Host - Prompt "Provide Domain Name "

   $groupName = Read-Host -Prompt "Provide AD group to be added as Admin (domain\group)"

   $adCred = Get-Credential -Message "Please provide crdentials for the AD domain join"

foreach($line in Import-Csv -Path .\esxNames.csv -UseCulture){

    Get-VMHost -Name $line.Name |

    ForEach-Object -Process {

        $esx = $_

        $pswd = $line.Password

      

        # Leave domain when joined  

        $leave = Get-VMHostAuthentication -VMHost $esx | where{$_.Domain -eq $domainName} |

         Set-VMHostAuthentication -LeaveDomain -Confirm:$false

        Write-Output "$($esx.Name) left domain"

 

        # Join domain       

         

        $join = Get-VMHostAuthentication -VMHost $esx |

         Set-VMHostAuthentication -Domain $domainName -JoinDomain -Credential $adCred -Confirm:$false

        Write-Output "$($esx.Name) joined domain"

  

        # Find (if any) root password change in last 80 days

        $pswdChange = Get-Vievent -Start (Get-Date).AddDays(-80) |

        Where{$_ -is [VMware.Vim.UserPasswordChanged] -and

              $_.UserName -eq $line.User -and

              $_.Host.Name -eq $esx.Name}

        if(-not $pswdChange){

            $pswd = MakeUp-String -Size 8  

            $srv = Connect-VIServer -Server $line.Name -User $line.User -Password $line.Password 4> $null

            if($srv){

                try{

                    Set-VMHostAccount -UserAccount $line.User -Password $pswd -Server $srv -Confirm:$false | Out-Null

                    Write-Output "ESXi: $($esx.Name)  Password: $pswd"

                }

                Catch{

                    Write-Output "Password change failed on $($esx.Name)"

                    $pswd = $line.Password

                }

                Disconnect-VIServer -Server $esx.Name -Confirm:$false

            }

        }

        else{

            Write-Output "Password on $($esx.Name) not changed"

        }

  

        # Add AD group

      

        $srv = Connect-VIServer -Server $esx.Name -User $line.User -Password $pswd 4> $null

        $localEsx = Get-VMHost -Server $srv

        $role = Get-VIRole -Server $srv -Name Admin

        New-VIPermission -Principal $groupName -Role $role -Entity $localEsx -Confirm:$false

        Disconnect-VIServer -Server $esx.Name -Confirm:$false

        # Output

        $report += [pscustomobject]@{

            Name = $line.Name

            User = $line.User

            Password = $pswd

        }

    }

}

Export-Csv -Path .\new-esxNames.csv -NoTypeInformation -UseCulture

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The report is empty because the $report variable was not piped to Export-Csv.

I corrected that code above.

The $report variable should contains the changed passwords.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos