Merge pull request #414 from dmilov/topic/dmilov/ssoadmin-externaldomain

New features and bug fixes
This commit is contained in:
dmilov
2021-02-11 11:44:14 +02:00
committed by GitHub
11 changed files with 364 additions and 249 deletions

View File

@@ -11,7 +11,7 @@
RootModule = 'VMware.vSphere.SsoAdmin.psm1' RootModule = 'VMware.vSphere.SsoAdmin.psm1'
# Version number of this module. # Version number of this module.
ModuleVersion = '1.0.0' ModuleVersion = '1.1.0'
# ID used to uniquely identify this module # ID used to uniquely identify this module
GUID = 'b3e25326-e809-4d68-a252-ca5fcaf1eb8b' GUID = 'b3e25326-e809-4d68-a252-ca5fcaf1eb8b'
@@ -34,7 +34,7 @@ RequiredModules = @(
) )
# Functions to export from this module # Functions to export from this module
FunctionsToExport = @('Connect-SsoAdminServer', 'Disconnect-SsoAdminServer', 'New-SsoPersonUser', 'Get-SsoPersonUser', 'Set-SsoPersonUser', 'Remove-SsoPersonUser', 'Get-SsoGroup', 'Get-SsoPasswordPolicy', 'Set-SsoPasswordPolicy', 'Get-SsoLockoutPolicy', 'Set-SsoLockoutPolicy', 'Get-SsoTokenLifetime', 'Set-SsoTokenLifetime', 'Add-ActiveDirectoryIdentitySource', 'Get-IdentitySource') FunctionsToExport = @('Connect-SsoAdminServer', 'Disconnect-SsoAdminServer', 'New-SsoPersonUser', 'Get-SsoPersonUser', 'Set-SsoPersonUser', 'Remove-SsoPersonUser', 'Get-SsoGroup', 'Get-SsoPasswordPolicy', 'Set-SsoPasswordPolicy', 'Get-SsoLockoutPolicy', 'Set-SsoLockoutPolicy', 'Get-SsoTokenLifetime', 'Set-SsoTokenLifetime', 'Add-ExternalDomainIdentitySource', 'Get-IdentitySource')
# Cmdlets to export from this module # Cmdlets to export from this module
CmdletsToExport = @() CmdletsToExport = @()
@@ -43,5 +43,5 @@ CmdletsToExport = @()
VariablesToExport = '' VariablesToExport = ''
# Aliases to export from this module # Aliases to export from this module
AliasesToExport = '*' AliasesToExport = @('Add-ActiveDirectoryIdentitySource')
} }

View File

@@ -54,6 +54,22 @@ param(
} }
} }
function FormatError {
param(
[System.Exception]
$exception
)
if ($exception -ne $null) {
if ($exception.InnerException -ne $null) {
$exception = $exception.InnerException
}
# result
$exception.Message
}
}
# Global variables # Global variables
$global:DefaultSsoAdminServers = New-Object System.Collections.Generic.List[VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer] $global:DefaultSsoAdminServers = New-Object System.Collections.Generic.List[VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer]
@@ -128,6 +144,8 @@ function Connect-SsoAdminServer {
$certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator'
} }
$ssoAdminServer = $null
try {
$ssoAdminServer = New-Object ` $ssoAdminServer = New-Object `
'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' `
-ArgumentList @( -ArgumentList @(
@@ -135,10 +153,19 @@ function Connect-SsoAdminServer {
$User, $User,
$Password, $Password,
$certificateValidator) $certificateValidator)
} catch {
Write-Error (FormatError $_.Exception)
}
if ($ssoAdminServer -ne $null) { if ($ssoAdminServer -ne $null) {
$existingConnectionIndex = $global:DefaultSsoAdminServers.IndexOf($ssoAdminServer)
if ($existingConnectionIndex -ge 0) {
$global:DefaultSsoAdminServers[$existingConnectionIndex].RefCount++
$ssoAdminServer = $global:DefaultSsoAdminServers[$existingConnectionIndex]
} else {
# Update $global:DefaultSsoAdminServers varaible # Update $global:DefaultSsoAdminServers varaible
$global:DefaultSsoAdminServers.Add($ssoAdminServer) | Out-Null $global:DefaultSsoAdminServers.Add($ssoAdminServer) | Out-Null
}
# Function Output # Function Output
Write-Output $ssoAdminServer Write-Output $ssoAdminServer
@@ -194,13 +221,13 @@ function Disconnect-SsoAdminServer {
} }
foreach ($requestedServer in $Server) { foreach ($requestedServer in $Server) {
if ($global:DefaultSsoAdminServers.Contains($requestedServer)) {
$global:DefaultSsoAdminServers.Remove($requestedServer) | Out-Null
}
if ($requestedServer.IsConnected) { if ($requestedServer.IsConnected) {
$requestedServer.Disconnect() $requestedServer.Disconnect()
} }
if ($global:DefaultSsoAdminServers.Contains($requestedServer) -and $requestedServer.RefCount -eq 0) {
$global:DefaultSsoAdminServers.Remove($requestedServer) | Out-Null
}
} }
} }
} }
@@ -324,6 +351,7 @@ function New-SsoPersonUser {
} }
# Output is the result of 'CreateLocalUser' # Output is the result of 'CreateLocalUser'
try {
$connection.Client.CreateLocalUser( $connection.Client.CreateLocalUser(
$UserName, $UserName,
$Password, $Password,
@@ -332,6 +360,9 @@ function New-SsoPersonUser {
$FirstName, $FirstName,
$LastName $LastName
) )
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
} }
@@ -401,6 +432,7 @@ function Get-SsoPersonUser {
$Name = [string]::Empty $Name = [string]::Empty
} }
try {
foreach ($connection in $serversToProcess) { foreach ($connection in $serversToProcess) {
if (-not $connection.IsConnected) { if (-not $connection.IsConnected) {
Write-Error "Server $connection is disconnected" Write-Error "Server $connection is disconnected"
@@ -426,6 +458,9 @@ function Get-SsoPersonUser {
} }
} }
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
@@ -533,6 +568,7 @@ function Set-SsoPersonUser {
$Unlock) $Unlock)
Process { Process {
try {
foreach ($u in $User) { foreach ($u in $User) {
$ssoAdminClient = $u.GetClient() $ssoAdminClient = $u.GetClient()
if ((-not $ssoAdminClient)) { if ((-not $ssoAdminClient)) {
@@ -566,6 +602,9 @@ function Set-SsoPersonUser {
Write-Output $u Write-Output $u
} }
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
@@ -602,6 +641,7 @@ function Remove-SsoPersonUser {
$User) $User)
Process { Process {
try {
foreach ($u in $User) { foreach ($u in $User) {
$ssoAdminClient = $u.GetClient() $ssoAdminClient = $u.GetClient()
if ((-not $ssoAdminClient)) { if ((-not $ssoAdminClient)) {
@@ -611,6 +651,9 @@ function Remove-SsoPersonUser {
$ssoAdminClient.DeleteLocalUser($u) $ssoAdminClient.DeleteLocalUser($u)
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
#endregion #endregion
@@ -681,6 +724,7 @@ function Get-SsoGroup {
$Name = [string]::Empty $Name = [string]::Empty
} }
try {
foreach ($connection in $serversToProcess) { foreach ($connection in $serversToProcess) {
if (-not $connection.IsConnected) { if (-not $connection.IsConnected) {
Write-Error "Server $connection is disconnected" Write-Error "Server $connection is disconnected"
@@ -706,6 +750,9 @@ function Get-SsoGroup {
} }
} }
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
#endregion #endregion
@@ -748,6 +795,7 @@ function Get-SsoPasswordPolicy {
if ($Server -ne $null) { if ($Server -ne $null) {
$serversToProcess = $Server $serversToProcess = $Server
} }
try {
foreach ($connection in $serversToProcess) { foreach ($connection in $serversToProcess) {
if (-not $connection.IsConnected) { if (-not $connection.IsConnected) {
Write-Error "Server $connection is disconnected" Write-Error "Server $connection is disconnected"
@@ -756,6 +804,9 @@ function Get-SsoPasswordPolicy {
$connection.Client.GetPasswordPolicy(); $connection.Client.GetPasswordPolicy();
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
@@ -891,6 +942,7 @@ function Set-SsoPasswordPolicy {
Process { Process {
try {
foreach ($pp in $PasswordPolicy) { foreach ($pp in $PasswordPolicy) {
$ssoAdminClient = $pp.GetClient() $ssoAdminClient = $pp.GetClient()
@@ -956,6 +1008,9 @@ function Set-SsoPasswordPolicy {
$MinLowercaseCount, $MinLowercaseCount,
$PasswordLifetimeDays); $PasswordLifetimeDays);
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
#endregion #endregion
@@ -998,6 +1053,8 @@ function Get-SsoLockoutPolicy {
if ($Server -ne $null) { if ($Server -ne $null) {
$serversToProcess = $Server $serversToProcess = $Server
} }
try {
foreach ($connection in $serversToProcess) { foreach ($connection in $serversToProcess) {
if (-not $connection.IsConnected) { if (-not $connection.IsConnected) {
Write-Error "Server $connection is disconnected" Write-Error "Server $connection is disconnected"
@@ -1006,6 +1063,9 @@ function Get-SsoLockoutPolicy {
$connection.Client.GetLockoutPolicy(); $connection.Client.GetLockoutPolicy();
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
@@ -1077,7 +1137,7 @@ function Set-SsoLockoutPolicy {
$MaxFailedAttempts) $MaxFailedAttempts)
Process { Process {
try {
foreach ($lp in $LockoutPolicy) { foreach ($lp in $LockoutPolicy) {
$ssoAdminClient = $lp.GetClient() $ssoAdminClient = $lp.GetClient()
@@ -1108,6 +1168,9 @@ function Set-SsoLockoutPolicy {
$FailedAttemptIntervalSec, $FailedAttemptIntervalSec,
$MaxFailedAttempts); $MaxFailedAttempts);
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
#endregion #endregion
@@ -1150,6 +1213,8 @@ function Get-SsoTokenLifetime {
if ($Server -ne $null) { if ($Server -ne $null) {
$serversToProcess = $Server $serversToProcess = $Server
} }
try {
foreach ($connection in $serversToProcess) { foreach ($connection in $serversToProcess) {
if (-not $connection.IsConnected) { if (-not $connection.IsConnected) {
Write-Error "Server $connection is disconnected" Write-Error "Server $connection is disconnected"
@@ -1158,6 +1223,9 @@ function Get-SsoTokenLifetime {
$connection.Client.GetTokenLifetime(); $connection.Client.GetTokenLifetime();
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
@@ -1211,6 +1279,7 @@ function Set-SsoTokenLifetime {
Process { Process {
try {
foreach ($tl in $TokenLifetime) { foreach ($tl in $TokenLifetime) {
$ssoAdminClient = $tl.GetClient() $ssoAdminClient = $tl.GetClient()
@@ -1224,22 +1293,25 @@ function Set-SsoTokenLifetime {
$MaxBearerTokenLifetime $MaxBearerTokenLifetime
); );
} }
} catch {
Write-Error (FormatError $_.Exception)
}
} }
} }
#endregion #endregion
#region IdentitySource #region IdentitySource
function Add-ActiveDirectoryIdentitySource { function Add-ExternalDomainIdentitySource {
<# <#
.NOTES .NOTES
=========================================================================== ===========================================================================
Created on: 9/30/2020 Created on: 2/11/2021
Created by: Dimitar Milov Created by: Dimitar Milov
Twitter: @dimitar_milov Twitter: @dimitar_milov
Github: https://github.com/dmilov Github: https://github.com/dmilov
=========================================================================== ===========================================================================
.DESCRIPTION .DESCRIPTION
This function adds Identity Source of ActiveDirectory type. This function adds Identity Source of ActiveDirectory, OpenLDAP or NIS type.
.PARAMETER Name .PARAMETER Name
Name of the identity source Name of the identity source
@@ -1269,8 +1341,12 @@ function Add-ActiveDirectoryIdentitySource {
Specifies the vSphere Sso Admin Server on which you want to run the cmdlet. Specifies the vSphere Sso Admin Server on which you want to run the cmdlet.
If not specified the servers available in $global:DefaultSsoAdminServers variable will be used. If not specified the servers available in $global:DefaultSsoAdminServers variable will be used.
.PARAMETER Server
Specifies the vSphere Sso Admin Server on which you want to run the cmdlet.
If not specified the servers available in $global:DefaultSsoAdminServers variable will be used.
.EXAMPLE .EXAMPLE
Add-ActiveDirectoryIdentitySource ` Add-ExternalDomainIdentitySource `
-Name 'sof-powercli' ` -Name 'sof-powercli' `
-DomainName 'sof-powercli.vmware.com' ` -DomainName 'sof-powercli.vmware.com' `
-DomainAlias 'sof-powercli' ` -DomainAlias 'sof-powercli' `
@@ -1280,9 +1356,22 @@ function Add-ActiveDirectoryIdentitySource {
-Username 'sofPowercliAdmin' ` -Username 'sofPowercliAdmin' `
-Password '$up3R$Tr0Pa$$w0rD' -Password '$up3R$Tr0Pa$$w0rD'
Adds ActiveDirectory identity source .EXAMPLE
Add-ExternalDomainIdentitySource `
-Name 'sof-powercli' `
-DomainName 'sof-powercli.vmware.com' `
-DomainAlias 'sof-powercli' `
-PrimaryUrl 'ldap://sof-powercli.vmware.com:389' `
-BaseDNUsers 'CN=Users,DC=sof-powercli,DC=vmware,DC=com' `
-BaseDNGroups 'CN=Users,DC=sof-powercli,DC=vmware,DC=com' `
-Username 'sofPowercliAdmin' `
-Password '$up3R$Tr0Pa$$w0rD' `
-ServerType 'OpenLDAP'
Adds External Identity Source
#> #>
[CmdletBinding()] [CmdletBinding()]
[Alias("Add-ActiveDirectoryIdentitySource")]
param( param(
[Parameter( [Parameter(
Mandatory=$true, Mandatory=$true,
@@ -1352,6 +1441,15 @@ function Add-ActiveDirectoryIdentitySource {
[string] [string]
$Password, $Password,
[Parameter(
Mandatory=$false,
ValueFromPipeline=$false,
ValueFromPipelineByPropertyName=$false,
HelpMessage='External domain server type')]
[ValidateSet('ActiveDirectory','OpenLdap','NIS')]
[string]
$DomainServerType = 'ActiveDirectory',
[Parameter( [Parameter(
Mandatory=$false, Mandatory=$false,
ValueFromPipeline=$false, ValueFromPipeline=$false,
@@ -1365,6 +1463,8 @@ function Add-ActiveDirectoryIdentitySource {
if ($Server -ne $null) { if ($Server -ne $null) {
$serversToProcess = $Server $serversToProcess = $Server
} }
try {
foreach ($connection in $serversToProcess) { foreach ($connection in $serversToProcess) {
if (-not $connection.IsConnected) { if (-not $connection.IsConnected) {
Write-Error "Server $connection is disconnected" Write-Error "Server $connection is disconnected"
@@ -1379,7 +1479,11 @@ function Add-ActiveDirectoryIdentitySource {
$BaseDNUsers, $BaseDNUsers,
$BaseDNGroups, $BaseDNGroups,
$Username, $Username,
$Password); $Password,
$DomainServerType);
}
} catch {
Write-Error (FormatError $_.Exception)
} }
} }

View File

@@ -30,6 +30,7 @@ namespace VMware.vSphere.SsoAdminClient.DataTypes
password, password,
serverCertificateValidator); serverCertificateValidator);
RefCount = 1;
Id = $"/SsoAdminServer={NormalizeUserName()}@{Name}"; Id = $"/SsoAdminServer={NormalizeUserName()}@{Name}";
} }
@@ -50,10 +51,13 @@ namespace VMware.vSphere.SsoAdminClient.DataTypes
public string Id { get; set; } public string Id { get; set; }
public bool IsConnected => _client != null; public bool IsConnected => _client != null;
public SsoAdminClient Client => _client; public SsoAdminClient Client => _client;
public int RefCount { get; set; }
public void Disconnect() { public void Disconnect() {
if (--RefCount == 0) {
_client = null; _client = null;
} }
}
public override string ToString() { public override string ToString() {
return Name; return Name;

View File

@@ -627,9 +627,9 @@ namespace VMware.vSphere.SsoAdminClient
string baseDNUsers, string baseDNUsers,
string baseDNGroups, string baseDNGroups,
string authenticationUserName, string authenticationUserName,
string authenticationPassword) { string authenticationPassword,
string serverType) {
string serverType = "ActiveDirectory";
string authenticationType = "password"; string authenticationType = "password";
var authorizedInvocationContext = var authorizedInvocationContext =
CreateAuthorizedInvocationContext(); CreateAuthorizedInvocationContext();

View File

@@ -52,7 +52,8 @@ Describe "Connect-SsoAdminServer and Disconnect-SsoAdminServer Tests" {
-Server $VcAddress ` -Server $VcAddress `
-User $User ` -User $User `
-Password ($Password + "invalid") ` -Password ($Password + "invalid") `
-SkipCertificateCheck } | ` -SkipCertificateCheck `
-ErrorAction Stop } | `
Should Throw "Invalid credentials" Should Throw "Invalid credentials"
} }
@@ -62,7 +63,8 @@ Describe "Connect-SsoAdminServer and Disconnect-SsoAdminServer Tests" {
{ Connect-SsoAdminServer ` { Connect-SsoAdminServer `
-Server $VcAddress ` -Server $VcAddress `
-User $User ` -User $User `
-Password $Password} | ` -Password $Password `
-ErrorAction Stop } | `
Should Throw "The SSL connection could not be established, see inner exception." Should Throw "The SSL connection could not be established, see inner exception."
} }
} }
@@ -102,43 +104,48 @@ Describe "Connect-SsoAdminServer and Disconnect-SsoAdminServer Tests" {
It 'Diconnect-SsoAdminServer does not disconnect if connected to more than 1 SSO server' { It 'Diconnect-SsoAdminServer does not disconnect if connected to more than 1 SSO server' {
# Arrange # Arrange
$expected += @(Connect-SsoAdminServer ` $connection1 = Connect-SsoAdminServer `
-Server $VcAddress ` -Server $VcAddress `
-User $User ` -User $User `
-Password $Password ` -Password $Password `
-SkipCertificateCheck) -SkipCertificateCheck
$expected += @(Connect-SsoAdminServer ` $connection2 = Connect-SsoAdminServer `
-Server $VcAddress ` -Server $VcAddress `
-User $User ` -User $User `
-Password $Password ` -Password $Password `
-SkipCertificateCheck) -SkipCertificateCheck
# Act # Act
# Assert # Assert
{Disconnect-SsoAdminServer} | should -Throw 'Connected to more than 1 SSO server, please specify a SSO server via -Server parameter' $connection2 | Should Be $connection1
(Compare-Object $global:DefaultSsoAdminServers $expected -IncludeEqual).Count | Should Be 2 $connection2.RefCount | Should Be 2
$expected.IsConnected | Should -Contain $true
Disconnect-SsoAdminServer
$connection2.IsConnected | Should -Contain $true
$connection2.RefCount | Should Be 1
} }
It 'Diconnect-SsoAdminServer does disconnect via pipeline if connected to more than 1 SSO server' { It 'Diconnect-SsoAdminServer does disconnect via pipeline if connected to more than 1 SSO server' {
# Arrange # Arrange
$expected += @(Connect-SsoAdminServer ` $connection1 = Connect-SsoAdminServer `
-Server $VcAddress ` -Server $VcAddress `
-User $User ` -User $User `
-Password $Password ` -Password $Password `
-SkipCertificateCheck) -SkipCertificateCheck
$expected += @(Connect-SsoAdminServer ` $connection2 = Connect-SsoAdminServer `
-Server $VcAddress ` -Server $VcAddress `
-User $User ` -User $User `
-Password $Password ` -Password $Password `
-SkipCertificateCheck) -SkipCertificateCheck
# Act # Act
$expected | Disconnect-SsoAdminServer $connection1, $connection2 | Disconnect-SsoAdminServer
# Assert # Assert
$global:DefaultSsoAdminServers.count | Should Be 0 $global:DefaultSsoAdminServers.Count | Should Be 0
$expected.IsConnected | Should -not -Contain $true $connection1.IsConnected | Should Be $false
$connection2.IsConnected | Should Be $false
} }
It 'Disconnects disconnected object' { It 'Disconnects disconnected object' {