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.
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
LucD I believe you can help me here to get it done . i i would appreciate your help
Thanks
Dharm
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
Thanks for quick help . I will check and update you the result .
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
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
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
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
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
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
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
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
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 .
And how would you identify a domain authentication failure?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
For that i am not sure ,
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
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
Which version of the script are you testing?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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
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