Skip to content

Commit

Permalink
xADUser: Adding ServicePrincipalNames property (#274)
Browse files Browse the repository at this point in the history
- Changes to xADUser
  - Added ServicePrincipalNames Property (issue #153).
  • Loading branch information
SSvilen authored and johlju committed May 25, 2019
1 parent 43f4be9 commit 58d8dfa
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 50 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

- Changes to xADUser
- Added ServicePrincipalNames Property

- Changes to xActiveDirectory
- Added new helper functions in xADCommon, see each functions comment-based
help for more information.
Expand Down
101 changes: 72 additions & 29 deletions DSCResources/MSFT_xADUser/MSFT_xADUser.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ $adPropertyMap = @(
@{ Parameter = 'PasswordNeverExpires'; UseCmdletParameter = $true; }
@{ Parameter = 'CannotChangePassword'; UseCmdletParameter = $true; }
@{ Parameter = 'TrustedForDelegation'; UseCmdletParameter = $true; }
@{ Parameter = 'ServicePrincipalNames'; }
)

function Get-TargetResource
Expand Down Expand Up @@ -301,7 +302,7 @@ function Get-TargetResource
[System.String]
$HomePhone,

# Specifies the user's pager number (ldapDisplayName 'pager')
# Specifies the user's pager number (ldapDisplayName 'pager')
[Parameter()]
[ValidateNotNull()]
[System.String]
Expand Down Expand Up @@ -358,7 +359,7 @@ function Get-TargetResource

# Specifies the authentication context type when testing user passwords #61
[Parameter()]
[ValidateSet('Default','Negotiate')]
[ValidateSet('Default', 'Negotiate')]
[System.String]
$PasswordAuthentication = 'Default',

Expand All @@ -372,7 +373,13 @@ function Get-TargetResource
[Parameter()]
[ValidateNotNull()]
[System.Boolean]
$RestoreFromRecycleBin
$RestoreFromRecycleBin,

# Specifies the service principal names registered on the user account
[Parameter()]
[ValidateNotNull()]
[System.String[]]
$ServicePrincipalNames
)

Assert-Module -ModuleName 'ActiveDirectory';
Expand Down Expand Up @@ -431,6 +438,9 @@ function Get-TargetResource
$targetResource['Path'] = Get-ADObjectParentDN -DN $adUser.DistinguishedName;
}
}
elseif (($property.Parameter) -eq 'ServicePrincipalNames') {
$targetResource['ServicePrincipalNames'] = [System.String[]]$adUser.ServicePrincipalNames
}
elseif ($property.ADProperty)
{
# The AD property name is different to the function parameter to use this
Expand Down Expand Up @@ -667,7 +677,7 @@ function Test-TargetResource
[System.String]
$HomePhone,

# Specifies the user's pager number (ldapDisplayName 'pager')
# Specifies the user's pager number (ldapDisplayName 'pager')
[Parameter()]
[ValidateNotNull()]
[System.String]
Expand Down Expand Up @@ -724,7 +734,7 @@ function Test-TargetResource

# Specifies the authentication context type when testing user passwords #61
[Parameter()]
[ValidateSet('Default','Negotiate')]
[ValidateSet('Default', 'Negotiate')]
[System.String]
$PasswordAuthentication = 'Default',

Expand All @@ -738,7 +748,13 @@ function Test-TargetResource
[Parameter()]
[ValidateNotNull()]
[System.Boolean]
$RestoreFromRecycleBin
$RestoreFromRecycleBin,

# Specifies the service principal names registered on the user account
[Parameter()]
[ValidateNotNull()]
[System.String[]]
$ServicePrincipalNames
)

Assert-Parameters @PSBoundParameters;
Expand All @@ -764,9 +780,9 @@ function Test-TargetResource
if ($parameter -eq 'Password' -and $PasswordNeverResets -eq $false)
{
$testPasswordParams = @{
Username = $UserName;
Password = $Password;
DomainName = $DomainName;
Username = $UserName;
Password = $Password;
DomainName = $DomainName;
PasswordAuthentication = $PasswordAuthentication;
}
if ($DomainAdministratorCredential)
Expand All @@ -787,6 +803,21 @@ function Test-TargetResource
{
# Both values are null/empty and therefore we are compliant
}
elseif ($parameter -eq 'ServicePrincipalNames')
{
$testMembersParams = @{
ExistingMembers = $targetResource.ServicePrincipalNames -as [System.String[]];
Members = $ServicePrincipalNames;
}
if (-not (Test-Members @testMembersParams))
{
$existingSPNs = $testMembersParams['ExistingMembers'] -join ',';
$desiredSPNs = $ServicePrincipalNames -join ',';
Write-Verbose -Message ($LocalizedData.ADUserNotDesiredPropertyState -f `
'ServicePrincipalNames', $desiredSPNs, $existingSPNs);
$isCompliant = $false;
}
}
elseif ($PSBoundParameters.$parameter -ne $targetResource.$parameter)
{
Write-Verbose -Message ($LocalizedData.ADUserNotDesiredPropertyState -f $parameter, $PSBoundParameters.$parameter, $targetResource.$parameter);
Expand Down Expand Up @@ -1020,7 +1051,7 @@ function Set-TargetResource
[System.String]
$HomePhone,

# Specifies the user's pager number (ldapDisplayName 'pager')
# Specifies the user's pager number (ldapDisplayName 'pager')
[Parameter()]
[ValidateNotNull()]
[System.String]
Expand Down Expand Up @@ -1077,7 +1108,7 @@ function Set-TargetResource

# Specifies the authentication context type when testing user passwords #61
[Parameter()]
[ValidateSet('Default','Negotiate')]
[ValidateSet('Default', 'Negotiate')]
[System.String]
$PasswordAuthentication = 'Default',

Expand All @@ -1091,7 +1122,13 @@ function Set-TargetResource
[Parameter()]
[ValidateNotNull()]
[System.Boolean]
$RestoreFromRecycleBin
$RestoreFromRecycleBin,

# Specifies the service principal names registered on the user account
[Parameter()]
[ValidateNotNull()]
[System.String[]]
$ServicePrincipalNames
)

Assert-Parameters @PSBoundParameters;
Expand All @@ -1106,7 +1143,7 @@ function Set-TargetResource
if ($targetResource.Ensure -eq 'Absent')
{
# Try to restore account if it exists
if($RestoreFromRecycleBin)
if ($RestoreFromRecycleBin)
{
Write-Verbose -Message ($LocalizedData.RestoringUser -f $UserName)
$restoreParams = Get-ADCommonParameters @PSBoundParameters
Expand Down Expand Up @@ -1134,8 +1171,8 @@ function Set-TargetResource
}

$setADUserParams = Get-ADCommonParameters @PSBoundParameters;
$replaceUserProperties = @{};
$removeUserProperties = @{};
$replaceUserProperties = @{ };
$removeUserProperties = @{ };
foreach ($parameter in $PSBoundParameters.Keys)
{
# Only check/action properties specified/declared parameters that match one of the function's
Expand Down Expand Up @@ -1172,6 +1209,12 @@ function Set-TargetResource
# we will change this as it is out of compliance (it always gets set anyway)
Write-Verbose -Message ($LocalizedData.UpdatingADUserProperty -f $parameter, $PSBoundParameters.$parameter);
}
elseif ($parameter -eq 'ServicePrincipalNames')
{
Write-Verbose -Message ($LocalizedData.UpdatingADUserProperty -f `
'ServicePrincipalNames', ($ServicePrincipalNames -join ','));
$replaceUserProperties['ServicePrincipalName'] = $ServicePrincipalNames;
}
elseif ($PSBoundParameters.$parameter -ne $targetResource.$parameter)
{
# Find the associated AD property
Expand Down Expand Up @@ -1273,7 +1316,7 @@ function Assert-Parameters
if (($PSBoundParameters.ContainsKey('Password')) -and ($Enabled -eq $false))
{
$throwInvalidArgumentErrorParams = @{
ErrorId = 'xADUser_DisabledAccountPasswordConflict';
ErrorId = 'xADUser_DisabledAccountPasswordConflict';
ErrorMessage = $LocalizedData.PasswordParameterConflictError -f 'Enabled', $false, 'Password';
}
ThrowInvalidArgumentError @throwInvalidArgumentErrorParams;
Expand Down Expand Up @@ -1308,7 +1351,7 @@ function Test-Password

# Specifies the authentication context type when testing user passwords #61
[Parameter(Mandatory = $true)]
[ValidateSet('Default','Negotiate')]
[ValidateSet('Default', 'Negotiate')]
[System.String]
$PasswordAuthentication
)
Expand All @@ -1319,20 +1362,20 @@ function Test-Password
if ($DomainAdministratorCredential)
{
$principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
[System.DirectoryServices.AccountManagement.ContextType]::Domain,
$DomainName,
$DomainAdministratorCredential.UserName,
$DomainAdministratorCredential.GetNetworkCredential().Password
);
[System.DirectoryServices.AccountManagement.ContextType]::Domain,
$DomainName,
$DomainAdministratorCredential.UserName,
$DomainAdministratorCredential.GetNetworkCredential().Password
);
}
else
{
$principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
[System.DirectoryServices.AccountManagement.ContextType]::Domain,
$DomainName,
$null,
$null
);
[System.DirectoryServices.AccountManagement.ContextType]::Domain,
$DomainName,
$null,
$null
);
}
Write-Verbose -Message ($LocalizedData.CheckingADUserPassword -f $UserName);

Expand All @@ -1342,8 +1385,8 @@ function Test-Password
$UserName,
$Password.GetNetworkCredential().Password,
[System.DirectoryServices.AccountManagement.ContextOptions]::Negotiate -bor
[System.DirectoryServices.AccountManagement.ContextOptions]::Signing -bor
[System.DirectoryServices.AccountManagement.ContextOptions]::Sealing
[System.DirectoryServices.AccountManagement.ContextOptions]::Signing -bor
[System.DirectoryServices.AccountManagement.ContextOptions]::Sealing
);
}
else
Expand Down
3 changes: 2 additions & 1 deletion DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class MSFT_xADUser : OMI_BaseResource
[Write, Description("Specifies the authentication context type used when testing passwords"), ValueMap{"Default","Negotiate"},Values{"Default","Negotiate"}] String PasswordAuthentication;
[Write, Description("Specifies whether existing user's password should be reset (default $false)")] Boolean PasswordNeverResets;
[Write, Description("Specifies whether an account is trusted for Kerberos delegation (default $false)")] Boolean TrustedForDelegation;
[Write, Description("Try to restore the organizational unit from the recycle bin before creating a new one.")] Boolean RestoreFromRecycleBin;
[Write, Description("Try to restore the user object from the recycle bin before creating a new one.")] Boolean RestoreFromRecycleBin;
[Write, Description("Specifies the service principal names for the user account.")] String ServicePrincipalNames[];
[Read, Description("Returns the X.500 path of the object")] String DistinguishedName;
};
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,9 @@ The xADServicePrincipalName DSC resource will manage service principal names.
* The 'Negotiate' option supports NTLM authentication - which may be required when testing users' passwords when Active Directory Certificate Services (ADCS) is deployed.
* **`[Boolean]` PasswordNeverResets** _(Write)_: Specifies whether existing user's password should be reset (default $false).
* **`[Boolean]` TrustedForDelegation** _(Write)_: Specifies whether an account is trusted for Kerberos delegation (default $false).
* **`[Boolean]` RestoreFromRecycleBin** _(Write)_: Try to restore the organizational unit from the recycle bin before creating a new one.
* **`[Boolean]` RestoreFromRecycleBin** _(Write)_: Try to restore the user object from the recycle bin before creating a new one.
* **`[String]` DistinguishedName** _(Read)_: The user distinguished name, returned with Get.
* **`[String]` ServicePrincipalNames** _(Write)_: Specifies the service principal names for the user account.

### **xWaitForADDomain**

Expand Down
Loading

0 comments on commit 58d8dfa

Please sign in to comment.