One of the new features that came with vSphere 4.1 was the ability to use Active Directory Authentication on ESX(i) servers for permissions, console access and ssh access.This is a great feature that you will probably want to activate on all your ESX(i) servers.
Unfortunately this new feature is not available in PowerCLI 4.1. That means you can’t set this up in your configuration scripts through a PowerCLI cmdlet. In most such cases you can fall back on one of the SDK APIs to bypass this lack of a cmdlet. But unfortunately the new “managers”, of which HostActiveDirectoryAuthentication is one, are not available in the VMware.Vim assembly either.
Rob raised this in a recent PowerCLI Community thread. Yasen, one of the PowerCLI Dev Team members, provided a bypass. To make this bypass a bit more accessible, I decided to roll it up in a PowerShell function.
A (little) bit of background information
The Active Directory Authentication feature has been discussed at length in several vSphere 4.1 blog posts.
A great video, that explains what it is and how you can use it, was made by David Davis. See his VIDEO: New vSphere 4.1 Windows Active Directory Authentication post.
The script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
#requires -version 2 function Get-VMHostAuthentication{ <# .SYNOPSIS The function retrieves the authentication services from an ESX(i) host .DESCRIPTION This function retrieves the configured authentication services from one or more ESX(i) hosts. .NOTES Author: Luc Dekens .PARAMETER VMHost Specify the ESX(i) host .EXAMPLE PS> Get-VMHost | Get-VMHostAuthentication .EXAMPLE PS> Get-VMHostAuthentication -VMHost (Get-VMHost) #> param( [parameter(ValueFromPipeline = $true,Position=1,Mandatory = $true)] [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl[]]$VMHost) process{ if(!$VMHost){$VMHost = $_} foreach($esx in $VMHost){ $filter = New-Object VMware.Vim.PropertyFilterSpec -Property @{ ObjectSet = New-Object VMware.Vim.ObjectSpec -Property @{ Obj = $esx.ExtensionData.ConfigManager.AuthenticationManager } PropSet = New-Object VMware.Vim.PropertySpec -Property @{ Type = "HostAuthenticationManager" All = $true } } $collector = Get-View $esx.ExtensionData.Client.ServiceContent.PropertyCollector $content = $collector.RetrieveProperties($filter) $stores = $content | Select -First 1 | %{$_.PropSet} | where {$_.Name -eq "info"} foreach($authConfig in $stores.Val.AuthConfig){ $row = New-Object PSObject $row | Add-Member -MemberType NoteProperty -Name Name -Value $null $row | Add-Member -MemberType NoteProperty -Name Type -Value $null $row | Add-Member -MemberType NoteProperty -Name Enabled -Value $null $row | Add-Member -MemberType NoteProperty -Name Domain -Value $null $row | Add-Member -MemberType NoteProperty -Name Membership -Value $null $row | Add-Member -MemberType NoteProperty -Name Trust -Value $null $row.Name = $esx.Name $row.Enabled = $authConfig.Enabled switch($authConfig.GetType().Name){ 'HostLocalAuthenticationInfo'{ $row.Type = 'Local authentication' } 'HostActiveDirectoryInfo'{ $row.Type = 'Active Directory' $row.Domain = $authConfig.JoinedDomain $row.Membership = $authConfig.DomainMembershipStatus $row.Trust = $authConfig.TrustedDomain } } $row } } } } function Set-VMHostADDomain{ <# .SYNOPSIS The function adds or removes an ESX(i) 4.1 server to/from an Active Directory domain .DESCRIPTION By adding an ESX(i) 4.1 host to an AD domain, you can use AD authentication for console access, SSH and permissions on the host's child objects .NOTES Author: Luc Dekens .PARAMETER VMHost Specify the ESX(i) host .PARAMETER Domain The name of the Active Directory domain in FQDN notation .PARAMETER User An Active Directory account that administrative authority to add hosts to AD .PARAMETER Password The password for the AD account specified in -User .PARAMETER Credential The credentials for an AD account with administrative authority to add hosts to AD .PARAMETER ADJoin A switch indicating if the host shall be added ($true) or removed ($false) from AD .PARAMETER RemovePermission Will remove ($true) all AD permissions that still exist on the ESX(i) host and it's children .EXAMPLE PS> Get-VMHost | Set-VMHostADDomain -ADJoin:$true -Domain $domain -User $user -Password $pswd .EXAMPLE PS> Set-VMHostADDomain -VMHost (Get-VMHost) -ADJoin:$true -Credential $cred .EXAMPLE PS> Set-VMHostADDomain -VMHost (Get-VMHost) -ADJoin:$false -RemovePermission:$true #> param( [parameter(ValueFromPipeline = $true,Position=1,Mandatory = $true)] [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl[]]$VMHost, [string]$Domain, [string]$User, [string]$Password, [System.Management.Automation.PSCredential]$Credential, [switch]$ADJoin, [switch]$RemovePermission = $false ) process{ if(!$VMHost){$VMHost = $_} foreach($esx in $VMHost){ $filter = New-Object VMware.Vim.PropertyFilterSpec -Property @{ ObjectSet = New-Object VMware.Vim.ObjectSpec -Property @{ Obj = $esx.ExtensionData.ConfigManager.AuthenticationManager } PropSet = New-Object VMware.Vim.PropertySpec -Property @{ Type = "HostAuthenticationManager" All = $true } } $collector = Get-View $esx.ExtensionData.Client.ServiceContent.PropertyCollector $content = $collector.RetrieveProperties($filter) $stores = $content | Select -First 1 | %{$_.PropSet} | where {$_.Name -eq "supportedStore"} $result = $stores.Val | where {$_.Type -eq "HostActiveDirectoryAuthentication"} $hostADAuth = [VMware.Vim.VIConvert]::ToVim41($result) if($ADJoin){ if($Credential){ $User = $Credential.GetNetworkCredential().UserName $Password = $Credential.GetNetworkCredential().Password } $taskMoRef = $esx.ExtensionData.Client.VimService.JoinDomain_Task($hostADAuth,$Domain,$User,$Password) } else{ $taskMoRef = $esx.ExtensionData.Client.VimService.LeaveCurrentDomain_Task($hostADAuth,$RemovePermission) } $esx.ExtensionData.WaitForTask([VMware.Vim.VIConvert]::ToVim($taskMoRef)) } } } |
Annotations
Line 1: This function uses PowerShell v2 features and will not run with PowerShell v1
Line 3-63: The Get-VMHostAuthentication function
Line 38-60: Return information for each of the configured authentication methods.
Line 65-138: The Set-VMHostADDomain function
Line 24,108: Handles use of the function in a pipeline or with a -VMHost parameter
Line 26-34,110-118: Creates the PropertyFilterSpec object through the use of the hash table property list.
Line 119-123: The ‘bypass’ from Yasen. It uses the PropertyCollector to ultimately get at the MoRef of the HostActiveDirectoryAuthentication manager.
Line 123: The MoRef is converted to a VIM 4.1 MoRef with the ToVim41 method of the builtin VIConvert class.
Line 125: Depending on the state of the ADJoin switch, the host is ‘joined’ or ‘removed’ from the AD domain.
Line 126-129: If the AD account is passed through a PSCredential object, the clear text account and password are extracted.
Line 135: The script waits for the completion of the called method.
Examples
To display the authentication services for an ESX(i) server that has no AD authentication configured.
1 |
Get-VMHost $esxName | Get-VMHostAuthetication |
This returns the following information.
To add a specific ESX(i) server to an Active Directory domain you can do
1 |
Set-VMHostADDomain -VMhost (Get-VMHost $esxName) -ADJoin:$true -Domain 'test.local' -User 'Administrator' -Password 'MyPassword' |
or
1 |
Get-VMHost $esxName | Set-VMHostADDomain -ADJoin:$true -Domain 'test.local' -User 'Administrator' -Password 'MyPassword' |
The Get-VMHostAuthentication function now returns.
You can also enable AD authentication on a series of ESX(i) hosts.
1 |
Set-VMHostADDomain -VMhost (Get-VMHost) -ADJoin:$true -Domain 'test.local' -Credential (Get-Credential) |
or like this
1 |
Get-VMHost | Set-VMHostADDomain -ADJoin:$true -Domain 'test.local' -Credential (Get-Credential) |
To remove a host, you have to set the -ADJoin switch to $false.
Like this
1 |
Get-VMHost | Set-VMHostADDomain -ADJoin:$false |
The previous call assumes that there were no permissions with AD principals left on the ESX(i) server or any of it’s children.
If there were, you would get an error message.
You can let the ‘unjoin’ remove any remaining permissions for you.
For that you use the -RemovePermission parameter.
1 |
Get-VMHost | Set-VMHostADDomain -ADJoin:$false -RemovePermission:$true |
Loren Gordon
Luc, Not sure if there’s a better way of doing this now, but I merged your script with Alex’s. Hopefully this will be helpful to someone else.
function Set-VMHostADDomain{
Get-VMHost | Set-VMHostADDomain -ADJoin:$true -Domain $domain -User $user -Password $pswd
.EXAMPLE
PS> Set-VMHostADDomain -VMHost (Get-VMHost) -ADJoin:$true -Credential $cred
.EXAMPLE
PS> Set-VMHostADDomain -VMHost (Get-VMHost) -ADJoin:$false -RemovePermission:$true
#>
param(
[parameter(ValueFromPipeline = $true,Position=1,Mandatory = $true)]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl[]]$VMHost,
[string]$Domain,
[string]$User,
[string]$Password,
[System.Management.Automation.PSCredential]$Credential,
[switch]$ADJoin,
[switch]$RemovePermission = $false
)
process{
if(!$VMHost){$VMHost = $_}
foreach($esx in $VMHost){
$collector = Get-View -id $esx.ID
$authenticationManagerView = Get-View $vmhostView.ConfigManager.AuthenticationManager
$hostActiveDirectoryAuthenticationMoRef = $authenticationManagerView.SupportedStore | where { $_.Type -eq ‘HostActiveDirectoryAuthentication’ }
$hostActiveDirectoryAuthentication = Get-View $hostActiveDirectoryAuthenticationMoRef
if($ADJoin){
if($Credential){
$User = $Credential.GetNetworkCredential().UserName
$Password = $Credential.GetNetworkCredential().Password
}
$taskMoRef = $hostActiveDirectoryAuthentication.JoinDomain_Task($Domain,$User,$Password)
}
else{
$taskMoRef = $hostActiveDirectoryAuthentication.LeaveCurrentDomain_Task($RemovePermission)
}
$esx.ExtensionData.WaitForTask([VMware.Vim.VIConvert]::ToVim($taskMoRef))
}
}
}
@LucD
Alex Mittell
Hey Luc,
This code below worked for me and seems quite a lot simpler to use, obviously you probably want to use a securestring or Get-Credentials to get the password instead of plain text, the below is just an example, but it got my ESXi hosts joined to the Domain just fine without loading anything but the standard PowerCLI modules. What do you think?
Regards,
Alex
function JoinDomainWithAD ($vmhost, $addomain, $aduser, $adpass) {
$vmhostView = Get-View -id $vmhost.ID
$authenticationManagerView = Get-View $vmhostView.ConfigManager.AuthenticationManager
$hostActiveDirectoryAuthenticationMoRef = $authenticationManagerView.SupportedStore | where { $_.Type -eq ‘HostActiveDirectoryAuthentication’ }
$hostActiveDirectoryAuthentication = Get-View $hostActiveDirectoryAuthenticationMoRef
$hostActiveDirectoryAuthentication.JoinDomain($addomain, $aduser, $adpass)
}
Write-Host
Write-Host ” Joining ESXi server to Active Directory domain…”
$esxihost = Read-Host “Enter ESXi host FQDN to join to Domain”
$ADDOMAIN = Read-Host “Enter Domain to join ESXi host to”
$ADUSER = Read-Host “Enter Username with permission to join to Domain: $ADDOMAIN”
$ADPASS = Read-Host “Enter password for username”
JoinDomainWithAD -vmhost $esxihost -addomain $ADDOMAIN -aduser $ADUSER -adpass $ADPASS
LucD
@Alex, the reason why I used the PropertyCollector was because the PowerCLI version at that time was missing the AuthenticationManager in the assembly. See also Yasen’s entry in the Community thread the article points to.
But you are absolutely right, the later PowerCLI builds did have the AuthenticationManager in the assembly, and your function is using that and is indeed a lot simpler.
sandeep
it’s not detaling more concept
LucD
@Sandeep, can you include the code you are trying to run or the eventual error messages you are seeing ?
maldini
could you elaborate how to get the logs populating???
maldini
Hi jeff,
I am facing the excet same problems trying to join my ESXi host to domain. Could you eleborate how to get the logs populating?
Jeff Couch
@Jeff Couch
I jumped the gun. Found in the logs that my $domain was not populating. This fixed the issue.
Thanks for an awesome function set!
LucD
Thanks Jeff.
I kept the comment in, it can be a pointer when someone else encounters the same problem.
Jeff Couch
Luc,
I am having trouble with this function. I am getting:
Exception calling “WaitForTask” with “1” argument(s): “Errors in Active Directory operations.”
$esx.ExtensionData.WaitForTask <<<< ([VMware.Vim.VIConvert]::ToVim($taskMoRef))
It works fine from the VI client. Any thoughts?
Thanks,
Jeff
John Cousens
@John Cousens
Never mind. The problem was between the keyboard and my chair 🙂 I tried to add the host from vCenter and got the same error. My host profile hadn’t applied the host name which was still set to “localhost”.
John Cousens
hey Luc,
this is an awesome script and works for us 90% of the time. However, I occasionally get the following error at line 135 in your script and don’t know why. Any help would be greatly appreciated. This is happening with ESXi 4.1.
Exception calling “WaitForTask” with “1” argument(s): “The host does not have a suitable FQDN.”
$esx.ExtensionData.WaitForTask <<<<([VMware.Vim.VIConvert]::ToVim($taskMoRef))
LucD
@John, thanks.
Could it be that you are un-joining an AD domain while you have a Connect-VIServer with an AD account active ?
Yev Berman
Hey Luc,
I wonder, is there any PowerCLI script you know that can Join\Change domain to VM?
P.S. Without RemoteCLI.
Thank you for your attention.
LucD
Hi Yev, you can do that with the Set-OSCustomizationSpec cmdlet.
Use the -Domain parameter.