From 14734877afa2f61df643ef7c5d1605bd3d48d170 Mon Sep 17 00:00:00 2001 From: Iain Brighton Date: Mon, 23 May 2016 19:42:35 +0100 Subject: [PATCH 1/4] Adds 'Negotiate' option when testing user passwords to support Active Directory Certificate Services integration Adds descriptions to parameters Adds descriptions to MSFT_xADUser.schema.mof Fixes #61 --- DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 | 175 ++++++++++++++++-- .../MSFT_xADUser/MSFT_xADUser.schema.mof | 90 ++++----- README.md | 3 + Tests/Unit/MSFT_xADUser.Tests.ps1 | 14 +- 4 files changed, 207 insertions(+), 75 deletions(-) diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 b/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 index ce9bb694a..2218af2ab 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 @@ -1,4 +1,4 @@ -# Localized messages +# Localized messages data LocalizedData { # culture="en-US" @@ -70,146 +70,186 @@ $adPropertyMap = @( function Get-TargetResource { + [CmdletBinding()] [OutputType([System.Collections.Hashtable])] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', '')] param ( - ## Only used if password is managed. + ## Name of the domain where the user account is located (only used if password is managed) [Parameter(Mandatory)] [System.String] $DomainName, - # SamAccountName + # Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName') [Parameter(Mandatory)] [System.String] $UserName, + ## Specifies a new password value for an account [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Password, + ## Specifies whether the user account is created or deleted [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', - # Common name (CN) + ## Specifies the common nane assigned to the user account (ldapDisplayName 'cn') [ValidateNotNull()] [System.String] $CommonName = $UserName, + ## Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName') [ValidateNotNull()] [System.String] $UserPrincipalName, + ## Specifies the display name of the object (ldapDisplayName 'displayName') [ValidateNotNull()] [System.String] $DisplayName, + ## Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created [ValidateNotNull()] [System.String] $Path, + ## Specifies the user's given name (ldapDisplayName 'givenName') [ValidateNotNull()] [System.String] $GivenName, + ## Specifies the initials that represent part of a user's name (ldapDisplayName 'initials') [ValidateNotNull()] [System.String] $Initials, + ## Specifies the user's last name or surname (ldapDisplayName 'sn') [ValidateNotNull()] [System.String] $Surname, + ## Specifies a description of the object (ldapDisplayName 'description') [ValidateNotNull()] [System.String] $Description, + ## Specifies the user's street address (ldapDisplayName 'streetAddress') [ValidateNotNull()] [System.String] $StreetAddress, + ## Specifies the user's post office box number (ldapDisplayName 'postOfficeBox') [ValidateNotNull()] [System.String] $POBox, + ## Specifies the user's town or city (ldapDisplayName 'l') [ValidateNotNull()] [System.String] $City, + ## Specifies the user's or Organizational Unit's state or province (ldapDisplayName 'st') [ValidateNotNull()] [System.String] $State, + ## Specifies the user's postal code or zip code (ldapDisplayName 'postalCode') [ValidateNotNull()] [System.String] $PostalCode, + ## Specifies the country or region code for the user's language of choice (ldapDisplayName 'c') [ValidateNotNull()] [System.String] $Country, + ## Specifies the user's department (ldapDisplayName 'department') [ValidateNotNull()] [System.String] $Department, + ## Specifies the user's division (ldapDisplayName 'division') [ValidateNotNull()] [System.String] $Division, + ## Specifies the user's company (ldapDisplayName 'company') [ValidateNotNull()] [System.String] $Company, + ## Specifies the location of the user's office or place of business (ldapDisplayName 'physicalDeliveryOfficeName') [ValidateNotNull()] [System.String] $Office, + ## Specifies the user's title (ldapDisplayName 'title') [ValidateNotNull()] [System.String] $JobTitle, + ## Specifies the user's e-mail address (ldapDisplayName 'mail') [ValidateNotNull()] [System.String] $EmailAddress, + ## Specifies the user's employee ID (ldapDisplayName 'employeeID') [ValidateNotNull()] [System.String] $EmployeeID, + ## Specifies the user's employee number (ldapDisplayName 'employeeNumber') [ValidateNotNull()] [System.String] $EmployeeNumber, + ## Specifies a user's home directory path (ldapDisplayName 'homeDirectory') [ValidateNotNull()] [System.String] $HomeDirectory, + ## Specifies a drive that is associated with the UNC path defined by the HomeDirectory property (ldapDisplayName 'homeDrive') [ValidateNotNull()] [System.String] $HomeDrive, + ## Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage') [ValidateNotNull()] [System.String] $HomePage, + ## Specifies a path to the user's profile (ldapDisplayName 'profilePath') [ValidateNotNull()] [System.String] $ProfilePath, + ## Specifies a path to the user's log on script (ldapDisplayName 'scriptPath') [ValidateNotNull()] [System.String] $LogonScript, + ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') [ValidateNotNull()] [System.String] $Notes, + ## Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber') [ValidateNotNull()] [System.String] $OfficePhone, + ## Specifies the user's mobile phone number (ldapDisplayName 'mobile') [ValidateNotNull()] [System.String] $MobilePhone, + ## Specifies the user's fax phone number (ldapDisplayName 'facsimileTelephoneNumber') [ValidateNotNull()] [System.String] $Fax, + ## Specifies the user's home telephone number (ldapDisplayName 'homePhone') [ValidateNotNull()] [System.String] $HomePhone, + ## Specifies the user's pager number (ldapDisplayName 'pager') [ValidateNotNull()] [System.String] $Pager, + ## Specifies the user's IP telephony phone number (ldapDisplayName 'ipPhone') [ValidateNotNull()] [System.String] $IPPhone, - ## User's manager specified as a Distinguished Name (DN) + ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, + ## Specifies if the account is enabled (default True) [ValidateNotNull()] [System.Boolean] $Enabled = $true, + ## Specifies whether the account password can be changed [ValidateNotNull()] [System.Boolean] $CannotChangePassword, + ## Specifies whether the password of an account can expire [ValidateNotNull()] [System.Boolean] $PasswordNeverExpires, + ## Specifies the Active Directory Domain Services instance to use to perform the task. [ValidateNotNull()] [System.String] $DomainController, - ## Ideally this should just be called 'Credential' but is here for backwards compatibility + ## Specifies the user account credentials to use to perform this task. Ideally this should just be called 'Credential' but is here for backwards compatibility [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] @@ -288,145 +328,186 @@ function Get-TargetResource function Test-TargetResource { + [CmdletBinding()] [OutputType([System.Boolean])] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', '')] param ( - ## Only used if password is managed. + ## Name of the domain where the user account is located (only used if password is managed) [Parameter(Mandatory)] [System.String] $DomainName, - # SamAccountName + # Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName') [Parameter(Mandatory)] [System.String] $UserName, + ## Specifies a new password value for an account [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Password, + ## Specifies whether the user account is created or deleted [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', - # Common name (CN) + ## Specifies the common nane assigned to the user account (ldapDisplayName 'cn') [ValidateNotNull()] [System.String] $CommonName = $UserName, - + + ## Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName') [ValidateNotNull()] [System.String] $UserPrincipalName, + ## Specifies the display name of the object (ldapDisplayName 'displayName') [ValidateNotNull()] [System.String] $DisplayName, + ## Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created [ValidateNotNull()] [System.String] $Path, + ## Specifies the user's given name (ldapDisplayName 'givenName') [ValidateNotNull()] [System.String] $GivenName, + ## Specifies the initials that represent part of a user's name (ldapDisplayName 'initials') [ValidateNotNull()] [System.String] $Initials, + ## Specifies the user's last name or surname (ldapDisplayName 'sn') [ValidateNotNull()] [System.String] $Surname, + ## Specifies a description of the object (ldapDisplayName 'description') [ValidateNotNull()] [System.String] $Description, + ## Specifies the user's street address (ldapDisplayName 'streetAddress') [ValidateNotNull()] [System.String] $StreetAddress, + ## Specifies the user's post office box number (ldapDisplayName 'postOfficeBox') [ValidateNotNull()] [System.String] $POBox, + ## Specifies the user's town or city (ldapDisplayName 'l') [ValidateNotNull()] [System.String] $City, + ## Specifies the user's or Organizational Unit's state or province (ldapDisplayName 'st') [ValidateNotNull()] [System.String] $State, + ## Specifies the user's postal code or zip code (ldapDisplayName 'postalCode') [ValidateNotNull()] [System.String] $PostalCode, + ## Specifies the country or region code for the user's language of choice (ldapDisplayName 'c') [ValidateNotNull()] [System.String] $Country, + ## Specifies the user's department (ldapDisplayName 'department') [ValidateNotNull()] [System.String] $Department, + ## Specifies the user's division (ldapDisplayName 'division') [ValidateNotNull()] [System.String] $Division, + ## Specifies the user's company (ldapDisplayName 'company') [ValidateNotNull()] [System.String] $Company, + ## Specifies the location of the user's office or place of business (ldapDisplayName 'physicalDeliveryOfficeName') [ValidateNotNull()] [System.String] $Office, + ## Specifies the user's title (ldapDisplayName 'title') [ValidateNotNull()] [System.String] $JobTitle, + ## Specifies the user's e-mail address (ldapDisplayName 'mail') [ValidateNotNull()] [System.String] $EmailAddress, + ## Specifies the user's employee ID (ldapDisplayName 'employeeID') [ValidateNotNull()] [System.String] $EmployeeID, + ## Specifies the user's employee number (ldapDisplayName 'employeeNumber') [ValidateNotNull()] [System.String] $EmployeeNumber, + ## Specifies a user's home directory path (ldapDisplayName 'homeDirectory') [ValidateNotNull()] [System.String] $HomeDirectory, + ## Specifies a drive that is associated with the UNC path defined by the HomeDirectory property (ldapDisplayName 'homeDrive') [ValidateNotNull()] [System.String] $HomeDrive, + ## Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage') [ValidateNotNull()] [System.String] $HomePage, + ## Specifies a path to the user's profile (ldapDisplayName 'profilePath') [ValidateNotNull()] [System.String] $ProfilePath, + ## Specifies a path to the user's log on script (ldapDisplayName 'scriptPath') [ValidateNotNull()] [System.String] $LogonScript, + ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') [ValidateNotNull()] [System.String] $Notes, + ## Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber') [ValidateNotNull()] [System.String] $OfficePhone, + ## Specifies the user's mobile phone number (ldapDisplayName 'mobile') [ValidateNotNull()] [System.String] $MobilePhone, + ## Specifies the user's fax phone number (ldapDisplayName 'facsimileTelephoneNumber') [ValidateNotNull()] [System.String] $Fax, + ## Specifies the user's home telephone number (ldapDisplayName 'homePhone') [ValidateNotNull()] [System.String] $HomePhone, + ## Specifies the user's pager number (ldapDisplayName 'pager') [ValidateNotNull()] [System.String] $Pager, + ## Specifies the user's IP telephony phone number (ldapDisplayName 'ipPhone') [ValidateNotNull()] [System.String] $IPPhone, - ## User's manager specified as a Distinguished Name (DN) + ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, + ## Specifies if the account is enabled (default True) [ValidateNotNull()] [System.Boolean] $Enabled = $true, + ## Specifies whether the account password can be changed [ValidateNotNull()] [System.Boolean] $CannotChangePassword, + ## Specifies whether the password of an account can expire [ValidateNotNull()] [System.Boolean] $PasswordNeverExpires, + ## Specifies the Active Directory Domain Services instance to use to perform the task. [ValidateNotNull()] [System.String] $DomainController, + ## Specifies the user account credentials to use to perform this task. Ideally this should just be called 'Credential' but is here for backwards compatibility [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] @@ -493,143 +574,185 @@ function Test-TargetResource function Set-TargetResource { + [CmdletBinding()] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', '')] param ( - ## Only used if password is managed. + ## Name of the domain where the user account is located (only used if password is managed) [Parameter(Mandatory)] [System.String] $DomainName, - # SamAccountName + # Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName') [Parameter(Mandatory)] [System.String] $UserName, + ## Specifies a new password value for an account [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Password, + ## Specifies whether the user account is created or deleted [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', + ## Specifies the common nane assigned to the user account (ldapDisplayName 'cn') [ValidateNotNull()] [System.String] $CommonName = $UserName, + ## Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName') [ValidateNotNull()] [System.String] $UserPrincipalName, + ## Specifies the display name of the object (ldapDisplayName 'displayName') [ValidateNotNull()] [System.String] $DisplayName, + ## Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created [ValidateNotNull()] [System.String] $Path, + ## Specifies the user's given name (ldapDisplayName 'givenName') [ValidateNotNull()] [System.String] $GivenName, + ## Specifies the initials that represent part of a user's name (ldapDisplayName 'initials') [ValidateNotNull()] [System.String] $Initials, + ## Specifies the user's last name or surname (ldapDisplayName 'sn') [ValidateNotNull()] [System.String] $Surname, + ## Specifies a description of the object (ldapDisplayName 'description') [ValidateNotNull()] [System.String] $Description, + ## Specifies the user's street address (ldapDisplayName 'streetAddress') [ValidateNotNull()] [System.String] $StreetAddress, + ## Specifies the user's post office box number (ldapDisplayName 'postOfficeBox') [ValidateNotNull()] [System.String] $POBox, + ## Specifies the user's town or city (ldapDisplayName 'l') [ValidateNotNull()] [System.String] $City, + ## Specifies the user's or Organizational Unit's state or province (ldapDisplayName 'st') [ValidateNotNull()] [System.String] $State, + ## Specifies the user's postal code or zip code (ldapDisplayName 'postalCode') [ValidateNotNull()] [System.String] $PostalCode, + ## Specifies the country or region code for the user's language of choice (ldapDisplayName 'c') [ValidateNotNull()] [System.String] $Country, + ## Specifies the user's department (ldapDisplayName 'department') [ValidateNotNull()] [System.String] $Department, + ## Specifies the user's division (ldapDisplayName 'division') [ValidateNotNull()] [System.String] $Division, + ## Specifies the user's company (ldapDisplayName 'company') [ValidateNotNull()] [System.String] $Company, + ## Specifies the location of the user's office or place of business (ldapDisplayName 'physicalDeliveryOfficeName') [ValidateNotNull()] [System.String] $Office, + ## Specifies the user's title (ldapDisplayName 'title') [ValidateNotNull()] [System.String] $JobTitle, + ## Specifies the user's e-mail address (ldapDisplayName 'mail') [ValidateNotNull()] [System.String] $EmailAddress, + ## Specifies the user's employee ID (ldapDisplayName 'employeeID') [ValidateNotNull()] [System.String] $EmployeeID, + ## Specifies the user's employee number (ldapDisplayName 'employeeNumber') [ValidateNotNull()] [System.String] $EmployeeNumber, + ## Specifies a user's home directory path (ldapDisplayName 'homeDirectory') [ValidateNotNull()] [System.String] $HomeDirectory, + ## Specifies a drive that is associated with the UNC path defined by the HomeDirectory property (ldapDisplayName 'homeDrive') [ValidateNotNull()] [System.String] $HomeDrive, + ## Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage') [ValidateNotNull()] [System.String] $HomePage, + ## Specifies a path to the user's profile (ldapDisplayName 'profilePath') [ValidateNotNull()] [System.String] $ProfilePath, + ## Specifies a path to the user's log on script (ldapDisplayName 'scriptPath') [ValidateNotNull()] [System.String] $LogonScript, + ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') [ValidateNotNull()] [System.String] $Notes, + ## Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber') [ValidateNotNull()] [System.String] $OfficePhone, + ## Specifies the user's mobile phone number (ldapDisplayName 'mobile') [ValidateNotNull()] [System.String] $MobilePhone, + ## Specifies the user's fax phone number (ldapDisplayName 'facsimileTelephoneNumber') [ValidateNotNull()] [System.String] $Fax, + ## Specifies the user's home telephone number (ldapDisplayName 'homePhone') [ValidateNotNull()] [System.String] $HomePhone, + ## Specifies the user's pager number (ldapDisplayName 'pager') [ValidateNotNull()] [System.String] $Pager, + ## Specifies the user's IP telephony phone number (ldapDisplayName 'ipPhone') [ValidateNotNull()] [System.String] $IPPhone, - ## User's manager specified as a Distinguished Name (DN) + ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, + ## Specifies if the account is enabled (default True) [ValidateNotNull()] [System.Boolean] $Enabled = $true, - + + ## Specifies whether the account password can be changed [ValidateNotNull()] [System.Boolean] $CannotChangePassword, + ## Specifies whether the password of an account can expire [ValidateNotNull()] [System.Boolean] $PasswordNeverExpires, + ## Specifies the Active Directory Domain Services instance to use to perform the task. [ValidateNotNull()] [System.String] $DomainController, + ## Specifies the user account credentials to use to perform this task. Ideally this should just be called 'Credential' but is here for backwards compatibility [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] @@ -824,22 +947,34 @@ function Test-Password [System.Management.Automation.CredentialAttribute()] $DomainAdministratorCredential ) - + Write-Verbose -Message ($LocalizedData.CreatingADDomainConnection -f $DomainName); Add-Type -AssemblyName 'System.DirectoryServices.AccountManagement'; if ($DomainAdministratorCredential) { $principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( - '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('Domain', $DomainName, $null, $null); + $principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( + [System.DirectoryServices.AccountManagement.ContextType]::Domain, + $DomainName, + $null, + $null + ); } Write-Verbose -Message ($LocalizedData.CheckingADUserPassword -f $UserName); - return $principalContext.ValidateCredentials($UserName, $Password.GetNetworkCredential().Password); + return $principalContext.ValidateCredentials( + $UserName, + $Password.GetNetworkCredential().Password, + [System.DirectoryServices.AccountManagement.ContextOptions]::Negotiate + ); } #end function Test-Password diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof index f3f35589b..93fba3259 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof @@ -1,49 +1,49 @@ [ClassVersion("1.0.1.0"), FriendlyName("xADUser")] class MSFT_xADUser : OMI_BaseResource { - [Key] String DomainName; - [Key] String UserName; - [Write, EmbeddedInstance("MSFT_Credential")] String Password; - [Write, ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] String Ensure; - [Write] String CommonName; - [Write] String UserPrincipalName; - [Write] String DisplayName; - [Write] String Path; - [Write] String GivenName; - [Write] String Initials; - [Write] String Surname; - [Write] String Description; - [Write] String StreetAddress; - [Write] String POBox; - [Write] String City; - [Write] String State; - [Write] String PostalCode; - [Write] String Country; - [Write] String Department; - [Write] String Division; - [Write] String Company; - [Write] String Office; - [Write] String JobTitle; - [Write] String EmailAddress; - [Write] String EmployeeID; - [Write] String EmployeeNumber; - [Write] String HomeDirectory; - [Write] String HomeDrive; - [Write] String HomePage; - [Write] String ProfilePath; - [Write] String LogonScript; - [Write] String Notes; - [Write] String OfficePhone; - [Write] String MobilePhone; - [Write] String Fax; - [Write] String HomePhone; - [Write] String Pager; - [Write] String IPPhone; - [Write] String Manager; - [Write] Boolean Enabled; - [Write] Boolean CannotChangePassword; - [Write] Boolean PasswordNeverExpires; - [Write] String DomainController; - [Write, EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential; - [Read, Description("")] String DistinguishedName; + [Key, Description("Name of the domain where the user account is located (only used if password is managed)")] String DomainName; + [Key, Description("Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName')")] String UserName; + [Write, Description("Specifies a new password value for the account"), EmbeddedInstance("MSFT_Credential")] String Password; + [Write, Description("Specifies whether the user account is created or deleted"), ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] String Ensure; + [Write, Description("Specifies the common nane assigned to the user account (ldapDisplayName 'cn')")] String CommonName; + [Write, Description("Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName')")] String UserPrincipalName; + [Write, Description("Specifies the display name of the object (ldapDisplayName 'displayName')")] String DisplayName; + [Write, Description("Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created")] String Path; + [Write, Description("Specifies the user's given name (ldapDisplayName 'givenName')")] String GivenName; + [Write, Description("Specifies the initials that represent part of a user's name (ldapDisplayName 'initials')")] String Initials; + [Write, Description("Specifies the user's last name or surname (ldapDisplayName 'sn')")] String Surname; + [Write, Description("Specifies a description of the object (ldapDisplayName 'description')")] String Description; + [Write, Description("Specifies the user's street address (ldapDisplayName 'streetAddress')")] String StreetAddress; + [Write, Description("Specifies the user's post office box number (ldapDisplayName 'postOfficeBox')")] String POBox; + [Write, Description("Specifies the user's town or city (ldapDisplayName 'l')")] String City; + [Write, Description("Specifies the user's or Organizational Unit's state or province (ldapDisplayName 'st')")] String State; + [Write, Description("Specifies the user's postal code or zip code (ldapDisplayName 'postalCode')")] String PostalCode; + [Write, Description("Specifies the country or region code for the user's language of choice (ldapDisplayName 'c')")] String Country; + [Write, Description("Specifies the user's department (ldapDisplayName 'department')")] String Department; + [Write, Description("Specifies the user's division (ldapDisplayName 'division')")] String Division; + [Write, Description("Specifies the user's company (ldapDisplayName 'company')")] String Company; + [Write, Description("Specifies the location of the user's office or place of business (ldapDisplayName 'physicalDeliveryOfficeName')")] String Office; + [Write, Description("Specifies the user's title (ldapDisplayName 'title')")] String JobTitle; + [Write, Description("Specifies the user's e-mail address (ldapDisplayName 'mail')")] String EmailAddress; + [Write, Description("Specifies the user's employee ID (ldapDisplayName 'employeeID')")] String EmployeeID; + [Write, Description("Specifies the user's employee number (ldapDisplayName 'employeeNumber')")] String EmployeeNumber; + [Write, Description("Specifies a user's home directory path (ldapDisplayName 'homeDirectory')")] String HomeDirectory; + [Write, Description("Specifies a drive that is associated with the UNC path defined by the HomeDirectory property (ldapDisplayName 'homeDrive')")] String HomeDrive; + [Write, Description("Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage')")] String HomePage; + [Write, Description("Specifies a path to the user's profile (ldapDisplayName 'profilePath')")] String ProfilePath; + [Write, Description("Specifies a path to the user's log on script (ldapDisplayName 'scriptPath')")] String LogonScript; + [Write, Description("Specifies the notes attached to the user's accoutn (ldapDisplayName 'info')")] String Notes; + [Write, Description("Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber')")] String OfficePhone; + [Write, Description("Specifies the user's mobile phone number (ldapDisplayName 'mobile')")] String MobilePhone; + [Write, Description("Specifies the user's fax phone number (ldapDisplayName 'facsimileTelephoneNumber')")] String Fax; + [Write, Description("Specifies the user's home telephone number (ldapDisplayName 'homePhone')")] String HomePhone; + [Write, Description("Specifies the user's pager number (ldapDisplayName 'pager')")] String Pager; + [Write, Description("Specifies the user's IP telephony phone number (ldapDisplayName 'ipPhone')")] String IPPhone; + [Write, Description("User's manager specified as a Distinguished Name (ldapDisplayName 'manager')")] String Manager; + [Write, Description("Specifies if the account is enabled (default True)")] Boolean Enabled; + [Write, Description("Specifies whether the account password can be changed")] Boolean CannotChangePassword; + [Write, Description("Specifies whether the password of an account can expire")] Boolean PasswordNeverExpires; + [Write, Description("Specifies the Active Directory Domain Services instance to use to perform the task.")] String DomainController; + [Write, Description("Specifies the user account credentials to use to perform this task"), EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential; + [Read, Description("Returns the X.500 path of the object")] String DistinguishedName; }; diff --git a/README.md b/README.md index 399b90a2a..d4e2ab51b 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,9 @@ The xADDomainDefaultPasswordPolicy DSC resource will manage an Active Directory ### Unreleased +* xADUser: Adds 'Negotiate' option when testing user passwords to support Active Directory Certificate Services integration +* xADUser: Adds descriptions to user properties within the schema file. + ### 2.11.0.0 * xWaitForADDomain: Made explicit credentials optional and other various updates diff --git a/Tests/Unit/MSFT_xADUser.Tests.ps1 b/Tests/Unit/MSFT_xADUser.Tests.ps1 index 10d1959be..ad78d1e2e 100644 --- a/Tests/Unit/MSFT_xADUser.Tests.ps1 +++ b/Tests/Unit/MSFT_xADUser.Tests.ps1 @@ -1,24 +1,20 @@ -$Global:DSCModuleName = 'xActiveDirectory' # Example xNetworking -$Global:DSCResourceName = 'MSFT_xADUser' # Example MSFT_xFirewall +$Global:DSCModuleName = 'xActiveDirectory' +$Global:DSCResourceName = 'MSFT_xADUser' #region HEADER [String] $moduleRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $Script:MyInvocation.MyCommand.Path)) -Write-Host $moduleRoot -ForegroundColor Green; if ( (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) { & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\')) } -else -{ - & git @('-C',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\'),'pull') -} + Import-Module (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force $TestEnvironment = Initialize-TestEnvironment ` -DSCModuleName $Global:DSCModuleName ` -DSCResourceName $Global:DSCResourceName ` -TestType Unit -#endregion +#endregion HEADER # Begin Testing @@ -27,8 +23,6 @@ try #region Pester Tests - # The InModuleScope command allows you to perform white-box unit testing on the internal - # (non-exported) code of a Script Module. InModuleScope $Global:DSCResourceName { $testPresentParams = @{ From 720bdd0b58e0737948f0d10f81ba66eb6da8ff84 Mon Sep 17 00:00:00 2001 From: Iain Brighton Date: Thu, 9 Jun 2016 21:51:41 +0100 Subject: [PATCH 2/4] Adds PasswordAuthenticationContext support to MSFT_xADUser --- DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 | 204 +++-- .../MSFT_xADUser/MSFT_xADUser.schema.mof | 3 +- README.md | 838 +++++++++--------- Tests/Unit/MSFT_xADUser.Tests.ps1 | 198 +++-- 4 files changed, 648 insertions(+), 595 deletions(-) diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 b/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 index 2218af2ab..aefd61eb8 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 @@ -6,14 +6,14 @@ data LocalizedData RoleNotFoundError = Please ensure that the PowerShell module for role '{0}' is installed. RetrievingADUserError = Error looking up Active Directory user '{0}' ({0}@{1}). PasswordParameterConflictError = Parameter '{0}' cannot be set to '{1}' when the '{2}' parameter is specified. - + RetrievingADUser = Retrieving Active Directory user '{0}' ({0}@{1}) ... CreatingADDomainConnection = Creating connection to Active Directory domain '{0}' ... CheckingADUserPassword = Checking Active Directory user '{0}' password ... ADUserIsPresent = Active Directory user '{0}' ({0}@{1}) is present. ADUserNotPresent = Active Directory user '{0}' ({0}@{1}) was NOT present. ADUserNotDesiredPropertyState = User '{0}' property is NOT in the desired state. Expected '{1}', actual '{2}'. - + AddingADUser = Adding Active Directory user '{0}'. RemovingADUser = Removing Active Directory user '{0}'. UpdatingADUser = Updating Active Directory user '{0}'. @@ -78,11 +78,11 @@ function Get-TargetResource ## Name of the domain where the user account is located (only used if password is managed) [Parameter(Mandatory)] [System.String] $DomainName, - + # Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName') [Parameter(Mandatory)] [System.String] $UserName, - + ## Specifies a new password value for an account [ValidateNotNull()] [System.Management.Automation.PSCredential] @@ -92,7 +92,7 @@ function Get-TargetResource ## Specifies whether the user account is created or deleted [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', - + ## Specifies the common nane assigned to the user account (ldapDisplayName 'cn') [ValidateNotNull()] [System.String] $CommonName = $UserName, @@ -100,27 +100,27 @@ function Get-TargetResource ## Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName') [ValidateNotNull()] [System.String] $UserPrincipalName, - + ## Specifies the display name of the object (ldapDisplayName 'displayName') [ValidateNotNull()] [System.String] $DisplayName, - + ## Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created [ValidateNotNull()] [System.String] $Path, - + ## Specifies the user's given name (ldapDisplayName 'givenName') [ValidateNotNull()] [System.String] $GivenName, - + ## Specifies the initials that represent part of a user's name (ldapDisplayName 'initials') [ValidateNotNull()] [System.String] $Initials, - + ## Specifies the user's last name or surname (ldapDisplayName 'sn') [ValidateNotNull()] [System.String] $Surname, - + ## Specifies a description of the object (ldapDisplayName 'description') [ValidateNotNull()] [System.String] $Description, @@ -172,7 +172,7 @@ function Get-TargetResource ## Specifies the user's e-mail address (ldapDisplayName 'mail') [ValidateNotNull()] [System.String] $EmailAddress, - + ## Specifies the user's employee ID (ldapDisplayName 'employeeID') [ValidateNotNull()] [System.String] $EmployeeID, @@ -192,23 +192,23 @@ function Get-TargetResource ## Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage') [ValidateNotNull()] [System.String] $HomePage, - + ## Specifies a path to the user's profile (ldapDisplayName 'profilePath') [ValidateNotNull()] [System.String] $ProfilePath, - + ## Specifies a path to the user's log on script (ldapDisplayName 'scriptPath') [ValidateNotNull()] [System.String] $LogonScript, - - ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') + + ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') [ValidateNotNull()] [System.String] $Notes, - + ## Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber') [ValidateNotNull()] [System.String] $OfficePhone, - + ## Specifies the user's mobile phone number (ldapDisplayName 'mobile') [ValidateNotNull()] [System.String] $MobilePhone, @@ -232,7 +232,7 @@ function Get-TargetResource ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, - + ## Specifies if the account is enabled (default True) [ValidateNotNull()] [System.Boolean] $Enabled = $true, @@ -240,28 +240,32 @@ function Get-TargetResource ## Specifies whether the account password can be changed [ValidateNotNull()] [System.Boolean] $CannotChangePassword, - + ## Specifies whether the password of an account can expire [ValidateNotNull()] [System.Boolean] $PasswordNeverExpires, - + ## Specifies the Active Directory Domain Services instance to use to perform the task. [ValidateNotNull()] [System.String] $DomainController, - + ## Specifies the user account credentials to use to perform this task. Ideally this should just be called 'Credential' but is here for backwards compatibility [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] - $DomainAdministratorCredential + $DomainAdministratorCredential, + + ## Specifies the authentication context type when testing user passwords #61 + [ValidateSet('Default','Negotiate')] + [System.String] $PasswordAuthenticationContext = 'Default' ) - + Assert-Module -ModuleName 'ActiveDirectory'; try { $adCommonParameters = Get-ADCommonParameters @PSBoundParameters; - + $adProperties = @(); ## Create an array of the AD propertie names to retrieve from the property map foreach ($property in $adPropertyMap) @@ -270,7 +274,7 @@ function Get-TargetResource { $adProperties += $property.ADProperty; } - else + else { $adProperties += $property.Parameter; } @@ -336,11 +340,11 @@ function Test-TargetResource ## Name of the domain where the user account is located (only used if password is managed) [Parameter(Mandatory)] [System.String] $DomainName, - + # Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName') [Parameter(Mandatory)] [System.String] $UserName, - + ## Specifies a new password value for an account [ValidateNotNull()] [System.Management.Automation.PSCredential] @@ -350,7 +354,7 @@ function Test-TargetResource ## Specifies whether the user account is created or deleted [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', - + ## Specifies the common nane assigned to the user account (ldapDisplayName 'cn') [ValidateNotNull()] [System.String] $CommonName = $UserName, @@ -358,27 +362,27 @@ function Test-TargetResource ## Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName') [ValidateNotNull()] [System.String] $UserPrincipalName, - + ## Specifies the display name of the object (ldapDisplayName 'displayName') [ValidateNotNull()] [System.String] $DisplayName, - + ## Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created [ValidateNotNull()] [System.String] $Path, - + ## Specifies the user's given name (ldapDisplayName 'givenName') [ValidateNotNull()] [System.String] $GivenName, - + ## Specifies the initials that represent part of a user's name (ldapDisplayName 'initials') [ValidateNotNull()] [System.String] $Initials, - + ## Specifies the user's last name or surname (ldapDisplayName 'sn') [ValidateNotNull()] [System.String] $Surname, - + ## Specifies a description of the object (ldapDisplayName 'description') [ValidateNotNull()] [System.String] $Description, @@ -430,7 +434,7 @@ function Test-TargetResource ## Specifies the user's e-mail address (ldapDisplayName 'mail') [ValidateNotNull()] [System.String] $EmailAddress, - + ## Specifies the user's employee ID (ldapDisplayName 'employeeID') [ValidateNotNull()] [System.String] $EmployeeID, @@ -450,23 +454,23 @@ function Test-TargetResource ## Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage') [ValidateNotNull()] [System.String] $HomePage, - + ## Specifies a path to the user's profile (ldapDisplayName 'profilePath') [ValidateNotNull()] [System.String] $ProfilePath, - + ## Specifies a path to the user's log on script (ldapDisplayName 'scriptPath') [ValidateNotNull()] [System.String] $LogonScript, - - ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') + + ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') [ValidateNotNull()] [System.String] $Notes, - + ## Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber') [ValidateNotNull()] [System.String] $OfficePhone, - + ## Specifies the user's mobile phone number (ldapDisplayName 'mobile') [ValidateNotNull()] [System.String] $MobilePhone, @@ -490,7 +494,7 @@ function Test-TargetResource ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, - + ## Specifies if the account is enabled (default True) [ValidateNotNull()] [System.Boolean] $Enabled = $true, @@ -498,20 +502,24 @@ function Test-TargetResource ## Specifies whether the account password can be changed [ValidateNotNull()] [System.Boolean] $CannotChangePassword, - + ## Specifies whether the password of an account can expire [ValidateNotNull()] [System.Boolean] $PasswordNeverExpires, - + ## Specifies the Active Directory Domain Services instance to use to perform the task. [ValidateNotNull()] [System.String] $DomainController, - + ## Specifies the user account credentials to use to perform this task. Ideally this should just be called 'Credential' but is here for backwards compatibility [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] - $DomainAdministratorCredential + $DomainAdministratorCredential, + + ## Specifies the authentication context type when testing user passwords #61 + [ValidateSet('Default','Negotiate')] + [System.String] $PasswordAuthenticationContext = 'Default' ) Assert-Parameters @PSBoundParameters; @@ -531,7 +539,7 @@ function Test-TargetResource ## Add common name, ensure and enabled as they may not be explicitly passed and we want to enumerate them $PSBoundParameters['Ensure'] = $Ensure; $PSBoundParameters['Enabled'] = $Enabled; - + foreach ($parameter in $PSBoundParameters.Keys) { if ($parameter -eq 'Password') @@ -540,6 +548,7 @@ function Test-TargetResource Username = $UserName; Password = $Password; DomainName = $DomainName; + PasswordAuthenticationContext = $PasswordAuthenticationContext; } if ($DomainAdministratorCredential) { @@ -581,11 +590,11 @@ function Set-TargetResource ## Name of the domain where the user account is located (only used if password is managed) [Parameter(Mandatory)] [System.String] $DomainName, - + # Specifies the Security Account Manager (SAM) account name of the user (ldapDisplayName 'sAMAccountName') [Parameter(Mandatory)] [System.String] $UserName, - + ## Specifies a new password value for an account [ValidateNotNull()] [System.Management.Automation.PSCredential] @@ -595,7 +604,7 @@ function Set-TargetResource ## Specifies whether the user account is created or deleted [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', - + ## Specifies the common nane assigned to the user account (ldapDisplayName 'cn') [ValidateNotNull()] [System.String] $CommonName = $UserName, @@ -603,27 +612,27 @@ function Set-TargetResource ## Specifies the UPN assigned to the user account (ldapDisplayName 'userPrincipalName') [ValidateNotNull()] [System.String] $UserPrincipalName, - + ## Specifies the display name of the object (ldapDisplayName 'displayName') [ValidateNotNull()] [System.String] $DisplayName, - + ## Specifies the X.500 path of the Organizational Unit (OU) or container where the new object is created [ValidateNotNull()] [System.String] $Path, - + ## Specifies the user's given name (ldapDisplayName 'givenName') [ValidateNotNull()] [System.String] $GivenName, - + ## Specifies the initials that represent part of a user's name (ldapDisplayName 'initials') [ValidateNotNull()] [System.String] $Initials, - + ## Specifies the user's last name or surname (ldapDisplayName 'sn') [ValidateNotNull()] [System.String] $Surname, - + ## Specifies a description of the object (ldapDisplayName 'description') [ValidateNotNull()] [System.String] $Description, @@ -675,7 +684,7 @@ function Set-TargetResource ## Specifies the user's e-mail address (ldapDisplayName 'mail') [ValidateNotNull()] [System.String] $EmailAddress, - + ## Specifies the user's employee ID (ldapDisplayName 'employeeID') [ValidateNotNull()] [System.String] $EmployeeID, @@ -695,23 +704,23 @@ function Set-TargetResource ## Specifies the URL of the home page of the object (ldapDisplayName 'wWWHomePage') [ValidateNotNull()] [System.String] $HomePage, - + ## Specifies a path to the user's profile (ldapDisplayName 'profilePath') [ValidateNotNull()] [System.String] $ProfilePath, - + ## Specifies a path to the user's log on script (ldapDisplayName 'scriptPath') [ValidateNotNull()] [System.String] $LogonScript, - - ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') + + ## Specifies the notes attached to the user's accoutn (ldapDisplayName 'info') [ValidateNotNull()] [System.String] $Notes, - + ## Specifies the user's office telephone number (ldapDisplayName 'telephoneNumber') [ValidateNotNull()] [System.String] $OfficePhone, - + ## Specifies the user's mobile phone number (ldapDisplayName 'mobile') [ValidateNotNull()] [System.String] $MobilePhone, @@ -735,7 +744,7 @@ function Set-TargetResource ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, - + ## Specifies if the account is enabled (default True) [ValidateNotNull()] [System.Boolean] $Enabled = $true, @@ -743,20 +752,24 @@ function Set-TargetResource ## Specifies whether the account password can be changed [ValidateNotNull()] [System.Boolean] $CannotChangePassword, - + ## Specifies whether the password of an account can expire [ValidateNotNull()] [System.Boolean] $PasswordNeverExpires, - + ## Specifies the Active Directory Domain Services instance to use to perform the task. [ValidateNotNull()] [System.String] $DomainController, - + ## Specifies the user account credentials to use to perform this task. Ideally this should just be called 'Credential' but is here for backwards compatibility [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] - $DomainAdministratorCredential + $DomainAdministratorCredential, + + ## Specifies the authentication context type when testing user passwords #61 + [ValidateSet('Default','Negotiate')] + [System.String] $PasswordAuthenticationContext = 'Default' ) Assert-Parameters @PSBoundParameters; @@ -824,7 +837,7 @@ function Set-TargetResource { ## Find the associated AD property $adProperty = $adPropertyMap | Where-Object { $_.Parameter -eq $parameter }; - + if ([System.String]::IsNullOrEmpty($adProperty)) { ## We can't do anything is an empty AD property! @@ -870,20 +883,20 @@ function Set-TargetResource } } #end if replace existing value } - + } #end if TargetResource parameter } #end foreach PSBoundParameter - + ## Only pass -Remove and/or -Replace if we have something to set/change if ($replaceUserProperties.Count -gt 0) - { + { $setADUserParams['Replace'] = $replaceUserProperties; } if ($removeUserProperties.Count -gt 0) - { + { $setADUserParams['Remove'] = $removeUserProperties; } - + Write-Verbose -Message ($LocalizedData.UpdatingADUser -f $UserName); [ref] $null = Set-ADUser @setADUserParams -Enabled $Enabled; } @@ -912,7 +925,7 @@ function Assert-Parameters [Parameter(ValueFromRemainingArguments)] $IgnoredArguments ) - + ## We cannot test/set passwords on disabled AD accounts if (($PSBoundParameters.ContainsKey('Password')) -and ($Enabled -eq $false)) { @@ -936,21 +949,26 @@ function Test-Password [Parameter(Mandatory)] [System.String] $UserName, - + [Parameter(Mandatory)] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Password, - + [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] - $DomainAdministratorCredential + $DomainAdministratorCredential, + + ## Specifies the authentication context type when testing user passwords #61 + [Parameter(Mandatory)] + [ValidateSet('Default','Negotiate')] + [System.String] $PasswordAuthenticationContext ) - + Write-Verbose -Message ($LocalizedData.CreatingADDomainConnection -f $DomainName); Add-Type -AssemblyName 'System.DirectoryServices.AccountManagement'; - + if ($DomainAdministratorCredential) { $principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( @@ -970,11 +988,25 @@ function Test-Password ); } Write-Verbose -Message ($LocalizedData.CheckingADUserPassword -f $UserName); - return $principalContext.ValidateCredentials( - $UserName, - $Password.GetNetworkCredential().Password, - [System.DirectoryServices.AccountManagement.ContextOptions]::Negotiate - ); + + if ($PasswordAuthenticationContext -eq 'Negotiate') + { + return $principalContext.ValidateCredentials( + $UserName, + $Password.GetNetworkCredential().Password, + [System.DirectoryServices.AccountManagement.ContextOptions]::Negotiate -bor + [System.DirectoryServices.AccountManagement.ContextOptions]::Signing -bor + [System.DirectoryServices.AccountManagement.ContextOptions]::Sealing + ); + } + else + { + ## Use default authentication context + return $principalContext.ValidateCredentials( + $UserName, + $Password.GetNetworkCredential().Password + ); + } } #end function Test-Password diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof index 93fba3259..c8e9df080 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof @@ -1,4 +1,4 @@ -[ClassVersion("1.0.1.0"), FriendlyName("xADUser")] +[ClassVersion("1.0.1.0"), FriendlyName("xADUser")] class MSFT_xADUser : OMI_BaseResource { [Key, Description("Name of the domain where the user account is located (only used if password is managed)")] String DomainName; @@ -45,5 +45,6 @@ class MSFT_xADUser : OMI_BaseResource [Write, Description("Specifies whether the password of an account can expire")] Boolean PasswordNeverExpires; [Write, Description("Specifies the Active Directory Domain Services instance to use to perform the task.")] String DomainController; [Write, Description("Specifies the user account credentials to use to perform this task"), EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential; + [Write, Description("Specifies the authentication context type used when testing passwords")] ValueMap{"Default","Negotiate"}, Values{"Default","Negotiate"}] String PasswordAuthenticationContext; [Read, Description("Returns the X.500 path of the object")] String DistinguishedName; }; diff --git a/README.md b/README.md index d4e2ab51b..e307d9768 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ These DSC Resources allow you to configure new domains, child domains, and high * **xADDomainTrust** establishes cross-domain trusts. * **xADGroup** modifies and removes Active Directory groups. * **xADOrganizationalUnit** creates and deletes Active Directory OUs. -* **xADUser** modifies and removes Active Directory Users. +* **xADUser** modifies and removes Active Directory Users. * **xWaitForDomain** waits for new, remote domain to setup. (Note: the RSAT tools will not be installed when these resources are used to configure AD.) @@ -32,14 +32,14 @@ These DSC Resources allow you to configure new domains, child domains, and high * **ParentDomainName**: Fully qualified name of the parent domain (optional). * **DomainAdministratorCredential**: Credentials used to query for domain existence. * __Note: These are NOT used during domain creation.__ -(AD sets the localadmin credentials as new domain administrator credentials during setup.) +(AD sets the localadmin credentials as new domain administrator credentials during setup.) * **SafemodeAdministratorPassword**: Password for the administrator account when the computer is started in Safe Mode. * **DnsDelegationCredential**: Credential used for creating DNS delegation (optional). * **DomainNetBIOSName**: Specifies the NetBIOS name for the new domain (optional). * If not specified, then the default is automatically computed from the value of the DomainName parameter. * **DatabasePath**: Specifies the fully qualified, non-Universal Naming Convention (UNC) path to a directory on a fixed disk of the local computer that contains the domain database (optional). * **LogPath**: Specifies the fully qualified, non-UNC path to a directory on a fixed disk of the local computer where the log file for this operation will be written (optional). -* **SysvolPath**: Specifies the fully qualified, non-UNC path to a directory on a fixed disk of the local computer where the Sysvol file will be written. (optional) +* **SysvolPath**: Specifies the fully qualified, non-UNC path to a directory on a fixed disk of the local computer where the Sysvol file will be written. (optional) ### **xADDomainController** @@ -61,7 +61,7 @@ These DSC Resources allow you to configure new domains, child domains, and high * **Ensure**: Specifies whether the given user is present or absent (optional). * If not specified, this value defaults to Present. * **DomainController**: Specifies the Active Directory Domain Services instance to connect to (optional). - * This is only required if not executing the task on a domain controller. + * This is only required if not executing the task on a domain controller. * **DomainAdministratorCredential**: User account credentials used to perform the task (optional). * This is only required if not executing the task on a domain controller or using the -DomainController parameter. * **CommonName**: Specifies the user's CN of the user account (optional). @@ -112,6 +112,8 @@ These DSC Resources allow you to configure new domains, child domains, and high * If not specified, this value defaults to False. * **CannotChangePassword**: Specifies whether the account password can be changed (optional). * If not specified, this value defaults to False. +* **PasswordAuthenticationContext**: Specifies the authentication context used when testing users' passwords (optional). + * The 'Negotiate' option supports NTLM authentication - which may be required when testing users' passwords when Active Directory Certificate Services (ADCS) is deployed. ### **xWaitForADDomain** @@ -121,23 +123,23 @@ These DSC Resources allow you to configure new domains, child domains, and high ### **xADDomainTrust** -* **Ensure**: Specifies whether the domain trust is present or absent -* **TargetDomainAdministratorCredential**: Credentials to authenticate to the target domain -* **TargetDomainName**: Name of the AD domain that is being trusted -* **TrustType**: Type of trust -* **TrustDirection**: Direction of trust, the values for which may be Bidirectional,Inbound, or Outbound -* **SourceDomainName**: Name of the AD domain that is requesting the trust +* **Ensure**: Specifies whether the domain trust is present or absent +* **TargetDomainAdministratorCredential**: Credentials to authenticate to the target domain +* **TargetDomainName**: Name of the AD domain that is being trusted +* **TrustType**: Type of trust +* **TrustDirection**: Direction of trust, the values for which may be Bidirectional,Inbound, or Outbound +* **SourceDomainName**: Name of the AD domain that is requesting the trust ### **xADRecycleBin** -The xADRecycleBin DSC resource will enable the Active Directory Recycle Bin feature for the target forest. -This resource first verifies that the forest mode is Windows Server 2008 R2 or greater. If the forest mode -is insufficient, then the resource will exit with an error message. The change is executed against the -Domain Naming Master FSMO of the forest. +The xADRecycleBin DSC resource will enable the Active Directory Recycle Bin feature for the target forest. +This resource first verifies that the forest mode is Windows Server 2008 R2 or greater. If the forest mode +is insufficient, then the resource will exit with an error message. The change is executed against the +Domain Naming Master FSMO of the forest. (Note: This resource is compatible with a Windows 2008 R2 or above target node. ) -* **ForestFQDN**: Fully qualified domain name of forest to enable Active Directory Recycle Bin. -* **EnterpriseAdministratorCredential**: Credential with Enterprise Administrator rights to the forest. -* **RecycleBinEnabled**: Read-only. Returned by Get. -* **ForestMode**: Read-only. Returned by Get. +* **ForestFQDN**: Fully qualified domain name of forest to enable Active Directory Recycle Bin. +* **EnterpriseAdministratorCredential**: Credential with Enterprise Administrator rights to the forest. +* **RecycleBinEnabled**: Read-only. Returned by Get. +* **ForestMode**: Read-only. Returned by Get. ### **xADGroup** The xADGroup DSC resource will manage groups within Active Directory. @@ -209,7 +211,7 @@ The xADDomainDefaultPasswordPolicy DSC resource will manage an Active Directory ### Unreleased -* xADUser: Adds 'Negotiate' option when testing user passwords to support Active Directory Certificate Services integration +* xADUser: Adds 'PasswordAuthenticationContext' option when testing user passwords to support NTLM authentication with Active Directory Certificate Services deployments * xADUser: Adds descriptions to user properties within the schema file. ### 2.11.0.0 @@ -290,7 +292,7 @@ In the following example configuration, a highly available domain is created by This example uses the xWaitForDomain resource to ensure that the domain is present before the second domain controller is added. ```powershell -# A configuration to Create High Availability Domain Controller +# A configuration to Create High Availability Domain Controller Configuration AssertHADC { param @@ -363,26 +365,26 @@ Configuration AssertHADC } } } -# Configuration Data for AD +# Configuration Data for AD $ConfigData = @{ AllNodes = @( @{ Nodename = "dsc-testNode1" Role = "Primary DC" DomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 20 - RetryIntervalSec = 30 + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 20 + RetryIntervalSec = 30 }, @{ Nodename = "dsc-testNode2" Role = "Replica DC" DomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 20 - RetryIntervalSec = 30 + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 20 + RetryIntervalSec = 30 } ) } @@ -395,131 +397,131 @@ Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path -Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertHADC ` -Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") -# A configuration to Create High Availability Domain Controller - -Configuration AssertHADC -{ - - param - ( - [Parameter(Mandatory)] - [pscredential]$safemodeAdministratorCred, - - [Parameter(Mandatory)] - [pscredential]$domainCred, - - [Parameter(Mandatory)] - [pscredential]$DNSDelegationCred, - - [Parameter(Mandatory)] - [pscredential]$NewADUserCred - ) - - Import-DscResource -ModuleName xActiveDirectory - - Node $AllNodes.Where{$_.Role -eq "Primary DC"}.Nodename - { - WindowsFeature ADDSInstall - { - Ensure = "Present" - Name = "AD-Domain-Services" - } - - xADDomain FirstDS - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domainCred - SafemodeAdministratorPassword = $safemodeAdministratorCred - DnsDelegationCredential = $DNSDelegationCred - DependsOn = "[WindowsFeature]ADDSInstall" - } - - xWaitForADDomain DscForestWait - { - DomainName = $Node.DomainName - DomainUserCredential = $domainCred - RetryCount = $Node.RetryCount - RetryIntervalSec = $Node.RetryIntervalSec - DependsOn = "[xADDomain]FirstDS" - } - - xADUser FirstUser - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domainCred - UserName = "dummy" - Password = $NewADUserCred - Ensure = "Present" - DependsOn = "[xWaitForADDomain]DscForestWait" - } - - } - - Node $AllNodes.Where{$_.Role -eq "Replica DC"}.Nodename - { - WindowsFeature ADDSInstall - { - Ensure = "Present" - Name = "AD-Domain-Services" - } - - xWaitForADDomain DscForestWait - { - DomainName = $Node.DomainName - DomainUserCredential = $domainCred - RetryCount = $Node.RetryCount - RetryIntervalSec = $Node.RetryIntervalSec - DependsOn = "[WindowsFeature]ADDSInstall" - } - - xADDomainController SecondDC - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domainCred - SafemodeAdministratorPassword = $safemodeAdministratorCred - DnsDelegationCredential = $DNSDelegationCred - DependsOn = "[xWaitForADDomain]DscForestWait" - } - } -} - -# Configuration Data for AD - -$ConfigData = @{ - AllNodes = @( - @{ - Nodename = "dsc-testNode1" - Role = "Primary DC" - DomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 20 - RetryIntervalSec = 30 - }, - - @{ - Nodename = "dsc-testNode2" - Role = "Replica DC" - DomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 20 - RetryIntervalSec = 30 - } - ) -} - -AssertHADC -configurationData $ConfigData ` --safemodeAdministratorCred (Get-Credential -Message "New Domain Safe Mode Admin Credentials") ` --domainCred (Get-Credential -Message "New Domain Admin Credentials") ` --DNSDelegationCred (Get-Credential -Message "Credentials to Setup DNS Delegation") ` --NewADUserCred (Get-Credential -Message "New AD User Credentials") - -Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path $PSScriptRoot\AssertHADC ` --Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") - -Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertHADC ` --Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") +# A configuration to Create High Availability Domain Controller + +Configuration AssertHADC +{ + + param + ( + [Parameter(Mandatory)] + [pscredential]$safemodeAdministratorCred, + + [Parameter(Mandatory)] + [pscredential]$domainCred, + + [Parameter(Mandatory)] + [pscredential]$DNSDelegationCred, + + [Parameter(Mandatory)] + [pscredential]$NewADUserCred + ) + + Import-DscResource -ModuleName xActiveDirectory + + Node $AllNodes.Where{$_.Role -eq "Primary DC"}.Nodename + { + WindowsFeature ADDSInstall + { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + xADDomain FirstDS + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DnsDelegationCredential = $DNSDelegationCred + DependsOn = "[WindowsFeature]ADDSInstall" + } + + xWaitForADDomain DscForestWait + { + DomainName = $Node.DomainName + DomainUserCredential = $domainCred + RetryCount = $Node.RetryCount + RetryIntervalSec = $Node.RetryIntervalSec + DependsOn = "[xADDomain]FirstDS" + } + + xADUser FirstUser + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domainCred + UserName = "dummy" + Password = $NewADUserCred + Ensure = "Present" + DependsOn = "[xWaitForADDomain]DscForestWait" + } + + } + + Node $AllNodes.Where{$_.Role -eq "Replica DC"}.Nodename + { + WindowsFeature ADDSInstall + { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + xWaitForADDomain DscForestWait + { + DomainName = $Node.DomainName + DomainUserCredential = $domainCred + RetryCount = $Node.RetryCount + RetryIntervalSec = $Node.RetryIntervalSec + DependsOn = "[WindowsFeature]ADDSInstall" + } + + xADDomainController SecondDC + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DnsDelegationCredential = $DNSDelegationCred + DependsOn = "[xWaitForADDomain]DscForestWait" + } + } +} + +# Configuration Data for AD + +$ConfigData = @{ + AllNodes = @( + @{ + Nodename = "dsc-testNode1" + Role = "Primary DC" + DomainName = "dsc-test.contoso.com" + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 20 + RetryIntervalSec = 30 + }, + + @{ + Nodename = "dsc-testNode2" + Role = "Replica DC" + DomainName = "dsc-test.contoso.com" + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 20 + RetryIntervalSec = 30 + } + ) +} + +AssertHADC -configurationData $ConfigData ` +-safemodeAdministratorCred (Get-Credential -Message "New Domain Safe Mode Admin Credentials") ` +-domainCred (Get-Credential -Message "New Domain Admin Credentials") ` +-DNSDelegationCred (Get-Credential -Message "Credentials to Setup DNS Delegation") ` +-NewADUserCred (Get-Credential -Message "New AD User Credentials") + +Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path $PSScriptRoot\AssertHADC ` +-Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") + +Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertHADC ` +-Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") ``` @@ -528,132 +530,132 @@ Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path In this example, we create a domain, and then create a child domain on another node. ```powershell -# Configuration to Setup Parent Child Domains - -Configuration AssertParentChildDomains -{ - param - ( - [Parameter(Mandatory)] - [pscredential]$safemodeAdministratorCred, - - [Parameter(Mandatory)] - [pscredential]$domainCred, - - [Parameter(Mandatory)] - [pscredential]$DNSDelegationCred, - - [Parameter(Mandatory)] - [pscredential]$NewADUserCred - ) - - Import-DscResource -ModuleName xActiveDirectory - - Node $AllNodes.Where{$_.Role -eq "Parent DC"}.Nodename - { - WindowsFeature ADDSInstall - { - Ensure = "Present" - Name = "AD-Domain-Services" - } - - xADDomain FirstDS - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domainCred - SafemodeAdministratorPassword = $safemodeAdministratorCred - DnsDelegationCredential = $DNSDelegationCred - DependsOn = "[WindowsFeature]ADDSInstall" - } - - xWaitForADDomain DscForestWait - { - DomainName = $Node.DomainName - DomainUserCredential = $domainCred - RetryCount = $Node.RetryCount - RetryIntervalSec = $Node.RetryIntervalSec - DependsOn = "[xADDomain]FirstDS" - } - - xADUser FirstUser - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domaincred - UserName = "dummy" - Password = $NewADUserCred - Ensure = "Present" - DependsOn = "[xWaitForADDomain]DscForestWait" - } - - } - - Node $AllNodes.Where{$_.Role -eq "Child DC"}.Nodename - { - WindowsFeature ADDSInstall - { - Ensure = "Present" - Name = "AD-Domain-Services" - } - - xWaitForADDomain DscForestWait - { - DomainName = $Node.ParentDomainName - DomainUserCredential = $domainCred - RetryCount = $Node.RetryCount - RetryIntervalSec = $Node.RetryIntervalSec - DependsOn = "[WindowsFeature]ADDSInstall" - } - - xADDomain ChildDS - { - DomainName = $Node.DomainName - ParentDomainName = $Node.ParentDomainName - DomainAdministratorCredential = $domainCred - SafemodeAdministratorPassword = $safemodeAdministratorCred - DependsOn = "[xWaitForADDomain]DscForestWait" - } - } -} - -$ConfigData = @{ - - AllNodes = @( - @{ - Nodename = "dsc-testNode1" - Role = "Parent DC" - DomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 50 - RetryIntervalSec = 30 - }, - - @{ - Nodename = "dsc-testNode2" - Role = "Child DC" - DomainName = "dsc-child" - ParentDomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 50 - RetryIntervalSec = 30 - } - ) -} - -AssertParentChildDomains -configurationData $ConfigData ` --safemodeAdministratorCred (Get-Credential -Message "New Domain Safe Mode Admin Credentials") ` --domainCred (Get-Credential -Message "New Domain Admin Credentials") ` --DNSDelegationCred (Get-Credential -Message "Credentials to Setup DNS Delegation") ` --NewADUserCred (Get-Credential -Message "New AD User Credentials") - - -Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path $PSScriptRoot\AssertParentChildDomains ` --Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") -Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertParentChildDomains ` --Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") -``` - +# Configuration to Setup Parent Child Domains + +Configuration AssertParentChildDomains +{ + param + ( + [Parameter(Mandatory)] + [pscredential]$safemodeAdministratorCred, + + [Parameter(Mandatory)] + [pscredential]$domainCred, + + [Parameter(Mandatory)] + [pscredential]$DNSDelegationCred, + + [Parameter(Mandatory)] + [pscredential]$NewADUserCred + ) + + Import-DscResource -ModuleName xActiveDirectory + + Node $AllNodes.Where{$_.Role -eq "Parent DC"}.Nodename + { + WindowsFeature ADDSInstall + { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + xADDomain FirstDS + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DnsDelegationCredential = $DNSDelegationCred + DependsOn = "[WindowsFeature]ADDSInstall" + } + + xWaitForADDomain DscForestWait + { + DomainName = $Node.DomainName + DomainUserCredential = $domainCred + RetryCount = $Node.RetryCount + RetryIntervalSec = $Node.RetryIntervalSec + DependsOn = "[xADDomain]FirstDS" + } + + xADUser FirstUser + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domaincred + UserName = "dummy" + Password = $NewADUserCred + Ensure = "Present" + DependsOn = "[xWaitForADDomain]DscForestWait" + } + + } + + Node $AllNodes.Where{$_.Role -eq "Child DC"}.Nodename + { + WindowsFeature ADDSInstall + { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + xWaitForADDomain DscForestWait + { + DomainName = $Node.ParentDomainName + DomainUserCredential = $domainCred + RetryCount = $Node.RetryCount + RetryIntervalSec = $Node.RetryIntervalSec + DependsOn = "[WindowsFeature]ADDSInstall" + } + + xADDomain ChildDS + { + DomainName = $Node.DomainName + ParentDomainName = $Node.ParentDomainName + DomainAdministratorCredential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DependsOn = "[xWaitForADDomain]DscForestWait" + } + } +} + +$ConfigData = @{ + + AllNodes = @( + @{ + Nodename = "dsc-testNode1" + Role = "Parent DC" + DomainName = "dsc-test.contoso.com" + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 50 + RetryIntervalSec = 30 + }, + + @{ + Nodename = "dsc-testNode2" + Role = "Child DC" + DomainName = "dsc-child" + ParentDomainName = "dsc-test.contoso.com" + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 50 + RetryIntervalSec = 30 + } + ) +} + +AssertParentChildDomains -configurationData $ConfigData ` +-safemodeAdministratorCred (Get-Credential -Message "New Domain Safe Mode Admin Credentials") ` +-domainCred (Get-Credential -Message "New Domain Admin Credentials") ` +-DNSDelegationCred (Get-Credential -Message "Credentials to Setup DNS Delegation") ` +-NewADUserCred (Get-Credential -Message "New AD User Credentials") + + +Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path $PSScriptRoot\AssertParentChildDomains ` +-Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") +Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertParentChildDomains ` +-Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") +``` + ### Create a cross-domain trust In this example, we setup one-way trust between two domains. @@ -667,7 +669,7 @@ Configuration Sample_xADDomainTrust_OneWayTrust [String]$SourceDomain, [Parameter(Mandatory)] [String]$TargetDomain, - + [Parameter(Mandatory)] [PSCredential]$TargetDomainAdminCred, [Parameter(Mandatory)] @@ -702,130 +704,130 @@ Sample_xADDomainTrust_OneWayTrust -configurationdata $config ` -TargetDomain corporate.contoso.com ` -TargetDomainAdminCred (get-credential) ` -TrustDirection 'Inbound' -# Configuration to Setup Parent Child Domains - -configuration AssertParentChildDomains -{ - param - ( - [Parameter(Mandatory)] - [pscredential]$safemodeAdministratorCred, - - [Parameter(Mandatory)] - [pscredential]$domainCred, - - [Parameter(Mandatory)] - [pscredential]$DNSDelegationCred, - - [Parameter(Mandatory)] - [pscredential]$NewADUserCred - ) - - Import-DscResource -ModuleName xActiveDirectory - - Node $AllNodes.Where{$_.Role -eq "Parent DC"}.Nodename - { - WindowsFeature ADDSInstall - { - Ensure = "Present" - Name = "AD-Domain-Services" - } - - xADDomain FirstDS - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domainCred - SafemodeAdministratorPassword = $safemodeAdministratorCred - DnsDelegationCredential = $DNSDelegationCred - DependsOn = "[WindowsFeature]ADDSInstall" - } - - xWaitForADDomain DscForestWait - { - DomainName = $Node.DomainName - DomainUserCredential = $domainCred - RetryCount = $Node.RetryCount - RetryIntervalSec = $Node.RetryIntervalSec - DependsOn = "[xADDomain]FirstDS" - } - - xADUser FirstUser - { - DomainName = $Node.DomainName - DomainAdministratorCredential = $domaincred - UserName = "dummy" - Password = $NewADUserCred - Ensure = "Present" - DependsOn = "[xWaitForADDomain]DscForestWait" - } - - } - - Node $AllNodes.Where{$_.Role -eq "Child DC"}.Nodename - { - WindowsFeature ADDSInstall - { - Ensure = "Present" - Name = "AD-Domain-Services" - } - - xWaitForADDomain DscForestWait - { - DomainName = $Node.ParentDomainName - DomainUserCredential = $domainCred - RetryCount = $Node.RetryCount - RetryIntervalSec = $Node.RetryIntervalSec - DependsOn = "[WindowsFeature]ADDSInstall" - } - - xADDomain ChildDS - { - DomainName = $Node.DomainName - ParentDomainName = $Node.ParentDomainName - DomainAdministratorCredential = $domainCred - SafemodeAdministratorPassword = $safemodeAdministratorCred - DependsOn = "[xWaitForADDomain]DscForestWait" - } - } -} - -$ConfigData = @{ - - AllNodes = @( - @{ - Nodename = "dsc-testNode1" - Role = "Parent DC" - DomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 50 - RetryIntervalSec = 30 - }, - - @{ - Nodename = "dsc-testNode2" - Role = "Child DC" - DomainName = "dsc-child" - ParentDomainName = "dsc-test.contoso.com" - CertificateFile = "C:\publicKeys\targetNode.cer" - Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" - RetryCount = 50 - RetryIntervalSec = 30 - } - ) -} - -AssertParentChildDomains -configurationData $ConfigData ` --safemodeAdministratorCred (Get-Credential -Message "New Domain Safe Mode Admin Credentials") ` --domainCred (Get-Credential -Message "New Domain Admin Credentials") ` --DNSDelegationCred (Get-Credential -Message "Credentials to Setup DNS Delegation") ` --NewADUserCred (Get-Credential -Message "New AD User Credentials") - - -Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path $PSScriptRoot\AssertParentChildDomains ` --Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") -Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertParentChildDomains ` --Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") +# Configuration to Setup Parent Child Domains + +configuration AssertParentChildDomains +{ + param + ( + [Parameter(Mandatory)] + [pscredential]$safemodeAdministratorCred, + + [Parameter(Mandatory)] + [pscredential]$domainCred, + + [Parameter(Mandatory)] + [pscredential]$DNSDelegationCred, + + [Parameter(Mandatory)] + [pscredential]$NewADUserCred + ) + + Import-DscResource -ModuleName xActiveDirectory + + Node $AllNodes.Where{$_.Role -eq "Parent DC"}.Nodename + { + WindowsFeature ADDSInstall + { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + xADDomain FirstDS + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DnsDelegationCredential = $DNSDelegationCred + DependsOn = "[WindowsFeature]ADDSInstall" + } + + xWaitForADDomain DscForestWait + { + DomainName = $Node.DomainName + DomainUserCredential = $domainCred + RetryCount = $Node.RetryCount + RetryIntervalSec = $Node.RetryIntervalSec + DependsOn = "[xADDomain]FirstDS" + } + + xADUser FirstUser + { + DomainName = $Node.DomainName + DomainAdministratorCredential = $domaincred + UserName = "dummy" + Password = $NewADUserCred + Ensure = "Present" + DependsOn = "[xWaitForADDomain]DscForestWait" + } + + } + + Node $AllNodes.Where{$_.Role -eq "Child DC"}.Nodename + { + WindowsFeature ADDSInstall + { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + xWaitForADDomain DscForestWait + { + DomainName = $Node.ParentDomainName + DomainUserCredential = $domainCred + RetryCount = $Node.RetryCount + RetryIntervalSec = $Node.RetryIntervalSec + DependsOn = "[WindowsFeature]ADDSInstall" + } + + xADDomain ChildDS + { + DomainName = $Node.DomainName + ParentDomainName = $Node.ParentDomainName + DomainAdministratorCredential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DependsOn = "[xWaitForADDomain]DscForestWait" + } + } +} + +$ConfigData = @{ + + AllNodes = @( + @{ + Nodename = "dsc-testNode1" + Role = "Parent DC" + DomainName = "dsc-test.contoso.com" + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 50 + RetryIntervalSec = 30 + }, + + @{ + Nodename = "dsc-testNode2" + Role = "Child DC" + DomainName = "dsc-child" + ParentDomainName = "dsc-test.contoso.com" + CertificateFile = "C:\publicKeys\targetNode.cer" + Thumbprint = "AC23EA3A9E291A75757A556D0B71CBBF8C4F6FD8" + RetryCount = 50 + RetryIntervalSec = 30 + } + ) +} + +AssertParentChildDomains -configurationData $ConfigData ` +-safemodeAdministratorCred (Get-Credential -Message "New Domain Safe Mode Admin Credentials") ` +-domainCred (Get-Credential -Message "New Domain Admin Credentials") ` +-DNSDelegationCred (Get-Credential -Message "Credentials to Setup DNS Delegation") ` +-NewADUserCred (Get-Credential -Message "New AD User Credentials") + + +Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode1" -Path $PSScriptRoot\AssertParentChildDomains ` +-Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") +Start-DscConfiguration -Wait -Force -Verbose -ComputerName "dsc-testNode2" -Path $PSScriptRoot\AssertParentChildDomains ` +-Credential (Get-Credential -Message "Local Admin Credentials on Remote Machine") ``` ### Enable the Active Directory Recycle Bin @@ -842,7 +844,7 @@ Param( [parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] - $EACredential + $EACredential ) Import-DscResource -Module xActiveDirectory @@ -881,15 +883,15 @@ Param( [parameter(Mandatory = $true)] [System.String] $GroupName, - - [ValidateSet('DomainLocal','Global','Universal')] + + [ValidateSet('DomainLocal','Global','Universal')] [System.String] $Scope = 'Global', - - [ValidateSet('Security','Distribution')] + + [ValidateSet('Security','Distribution')] [System.String] $Category = 'Security', - + [ValidateNotNullOrEmpty()] [System.String] $Description @@ -926,14 +928,14 @@ Param( [parameter(Mandatory = $true)] [System.String] $Name, - - [parameter(Mandatory = $true)] + + [parameter(Mandatory = $true)] [System.String] $Path, - + [System.Boolean] $ProtectedFromAccidentalDeletion = $true, - + [ValidateNotNull()] [System.String] $Description = '' @@ -972,11 +974,11 @@ configuration Example_xADDomainDefaultPasswordPolicy [parameter(Mandatory = $true)] [System.String] $DomainName, - - [parameter(Mandatory = $true)] + + [parameter(Mandatory = $true)] [System.Boolean] $ComplexityEnabled, - + [parameter(Mandatory = $true)] [System.Int32] $MinPasswordLength, diff --git a/Tests/Unit/MSFT_xADUser.Tests.ps1 b/Tests/Unit/MSFT_xADUser.Tests.ps1 index ad78d1e2e..1dae6a22b 100644 --- a/Tests/Unit/MSFT_xADUser.Tests.ps1 +++ b/Tests/Unit/MSFT_xADUser.Tests.ps1 @@ -13,7 +13,7 @@ Import-Module (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHel $TestEnvironment = Initialize-TestEnvironment ` -DSCModuleName $Global:DSCModuleName ` -DSCResourceName $Global:DSCResourceName ` - -TestType Unit + -TestType Unit #endregion HEADER @@ -30,10 +30,10 @@ try UserName = 'TestUser'; Ensure = 'Present'; } - + $testAbsentParams = $testPresentParams.Clone(); $testAbsentParams['Ensure'] = 'Absent'; - + $fakeADUser = @{ DistinguishedName = "CN=$($testPresentParams.UserName),CN=Users,DC=contoso,DC=com"; Enabled = $true; @@ -57,93 +57,111 @@ try #region Function Get-TargetResource Describe "$($Global:DSCResourceName)\Get-TargetResource" { - + It "Returns a 'System.Collections.Hashtable' object type" { Mock Get-ADUser { return [PSCustomObject] $fakeADUser; } - + $adUser = Get-TargetResource @testPresentParams; - + $adUser -is [System.Collections.Hashtable] | Should Be $true; } - + It "Returns 'Ensure' is 'Present' when user account exists" { Mock Get-ADUser { return [PSCustomObject] $fakeADUser; } - + $adUser = Get-TargetResource @testPresentParams; - + $adUser.Ensure | Should Be 'Present'; } - + It "Returns 'Ensure' is 'Absent' when user account does not exist" { Mock Get-ADUser { throw New-Object Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException } - + $adUser = Get-TargetResource @testPresentParams; - + $adUser.Ensure | Should Be 'Absent'; } - + It "Calls 'Get-ADUser' with 'Server' parameter when 'DomainController' specified" { Mock Get-ADUser -ParameterFilter { $Server -eq $testDomainController } -MockWith { return [PSCustomObject] $fakeADUser; } - + Get-TargetResource @testPresentParams -DomainController $testDomainController; - + Assert-MockCalled Get-ADUser -ParameterFilter { $Server -eq $testDomainController } -Scope It; } - + It "Calls 'Get-ADUser' with 'Credential' parameter when 'DomainAdministratorCredential' specified" { Mock Get-ADUser -ParameterFilter { $Credential -eq $testCredential } -MockWith { return [PSCustomObject] $fakeADUser; } - + Get-TargetResource @testPresentParams -DomainAdministratorCredential $testCredential; - + Assert-MockCalled Get-ADUser -ParameterFilter { $Credential -eq $testCredential } -Scope It; } - + } #endregion - + #region Function Test-TargetResource Describe "$($Global:DSCResourceName)\Test-TargetResource" { - + It "Passes when user account does not exist and 'Ensure' is 'Absent'" { Mock Get-TargetResource { return $testAbsentParams } - + Test-TargetResource @testAbsentParams | Should Be $true; } - + It "Passes when user account exists and 'Ensure' is 'Present'" { Mock Get-TargetResource { return $testPresentParams } - + Test-TargetResource @testPresentParams | Should Be $true; } - + It "Passes when user account password matches and 'Password' is specified" { Mock Get-TargetResource { return $testPresentParams } Mock Test-Password { return $true; } - + Test-TargetResource @testPresentParams -Password $testCredential | Should Be $true; } - + It "Fails when user account does not exist and 'Ensure' is 'Present'" { Mock Get-TargetResource { return $testAbsentParams } - + Test-TargetResource @testPresentParams | Should Be $false; } - + It "Fails when user account exists, and 'Ensure' is 'Absent'" { Mock Get-TargetResource { return $testPresentParams } - + Test-TargetResource @testAbsentParams | Should Be $false; } - + It "Fails when user account password is incorrect and 'Password' is specified" { Mock Get-TargetResource { return $testPresentParams } Mock Test-Password { return $false; } - + Test-TargetResource @testPresentParams -Password $testCredential | Should Be $false; } - + + It "Calls 'Test-Password' with 'Default' PasswordAuthenticationContext by default" { + Mock Get-TargetResource { return $testPresentParams } + Mock Test-Password -ParameterFilter { $PasswordAuthenticationContext -eq 'Default' } { return $true; } + + Test-TargetResource @testPresentParams -Password $testCredential; + + Assert-MockCalled Test-Password -ParameterFilter { $PasswordAuthenticationContext -eq 'Default' } -Scope It; + } + + It "Calls 'Test-Password' with 'Negotiate' PasswordAuthenticationContext when specified" { + Mock Get-TargetResource { return $testPresentParams } + Mock Test-Password -ParameterFilter { $PasswordAuthenticationContext -eq 'Negotiate' } { return $false; } + + Test-TargetResource @testPresentParams -Password $testCredential -PasswordAuthenticationContext 'Negotiate'; + + Assert-MockCalled Test-Password -ParameterFilter { $PasswordAuthenticationContext -eq 'Negotiate' } -Scope It; + } + foreach ($testParameter in $testStringProperties) { - + It "Passes when user account '$testParameter' matches AD account property" { $testParameterValue = 'Test Parameter String Value'; $testValidPresentParams = $testPresentParams.Clone(); @@ -154,10 +172,10 @@ try $validADUser[$testParameter] = $testParameterValue; return $validADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $true; } - + It "Fails when user account '$testParameter' does not match incorrect AD account property value" { $testParameterValue = 'Test Parameter String Value'; $testValidPresentParams = $testPresentParams.Clone(); @@ -168,10 +186,10 @@ try $invalidADUser[$testParameter] = $testParameterValue.Substring(0, ([System.Int32] $testParameterValue.Length/2)); return $invalidADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $false; } - + It "Fails when user account '$testParameter' does not match empty AD account property value" { $testParameterValue = 'Test Parameter String Value'; $testValidPresentParams = $testPresentParams.Clone(); @@ -182,10 +200,10 @@ try $invalidADUser[$testParameter] = ''; return $invalidADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $false; } - + It "Fails when user account '$testParameter' does not match null AD account property value" { $testParameterValue = 'Test Parameter String Value'; $testValidPresentParams = $testPresentParams.Clone(); @@ -196,10 +214,10 @@ try $invalidADUser[$testParameter] = $null; return $invalidADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $false; } - + It "Passes when empty user account '$testParameter' matches empty AD account property" { $testValidPresentParams = $testPresentParams.Clone(); $testValidPresentParams[$testParameter] = $testParameterValue; @@ -208,10 +226,10 @@ try $validADUser[$testParameter] = ''; return $validADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $true; } - + It "Passes when empty user account '$testParameter' matches null AD account property" { $testValidPresentParams = $testPresentParams.Clone(); $testValidPresentParams[$testParameter] = $testParameterValue; @@ -220,14 +238,14 @@ try $validADUser[$testParameter] = $null; return $validADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $true; } - + } #end foreach test string property - + foreach ($testParameter in $testBooleanProperties) { - + It "Passes when user account '$testParameter' matches AD account property" { $testParameterValue = $true; $testValidPresentParams = $testPresentParams.Clone(); @@ -238,10 +256,10 @@ try $validADUser[$testParameter] = $testParameterValue; return $validADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $true; } - + It "Fails when user account '$testParameter' does not match AD account property value" { $testParameterValue = $true; $testValidPresentParams = $testPresentParams.Clone(); @@ -252,33 +270,33 @@ try $invalidADUser[$testParameter] = -not $testParameterValue; return $invalidADUser; } - + Test-TargetResource @testValidPresentParams | Should Be $false; } - + } #end foreach test boolean property - + } #endregion - + #region Function Set-TargetResource Describe "$($Global:DSCResourceName)\Set-TargetResource" { - + It "Calls 'New-ADUser' when 'Ensure' is 'Present' and the account does not exist" { $newUserName = 'NewUser' $newAbsentParams = $testAbsentParams.Clone(); $newAbsentParams['UserName'] = $newUserName; $newPresentParams = $testPresentParams.Clone(); - $newPresentParams['UserName'] = $newUserName; + $newPresentParams['UserName'] = $newUserName; Mock New-ADUser -ParameterFilter { $Name -eq $newUserName } { } Mock Set-ADUser { } Mock Get-TargetResource -ParameterFilter { $Username -eq $newUserName } { return $newAbsentParams; } - + Set-TargetResource @newPresentParams; - + Assert-MockCalled New-ADUser -ParameterFilter { $Name -eq $newUserName } -Scope It; } - + It "Calls 'Move-ADObject' when 'Ensure' is 'Present', the account exists but Path is incorrect" { $testTargetPath = 'CN=Users,DC=contoso,DC=com'; Mock Set-ADUser { } @@ -288,9 +306,9 @@ try return $duffADUser; } Mock Move-ADObject -ParameterFilter { $TargetPath -eq $testTargetPath } -MockWith { } - + Set-TargetResource @testPresentParams -Path $testTargetPath -Enabled $true; - + Assert-MockCalled Move-ADObject -ParameterFilter { $TargetPath -eq $testTargetPath } -Scope It; } @@ -299,22 +317,22 @@ try Mock Set-ADUser { } Mock Get-ADUser { return $fakeADUser; } Mock Rename-ADObject -ParameterFilter { $NewName -eq $testCommonName } -MockWith { } - + Set-TargetResource @testPresentParams -CommonName $testCommonName -Enabled $true; - + Assert-MockCalled Rename-ADObject -ParameterFilter { $NewName -eq $testCommonName } -Scope It; } - + It "Calls 'Set-ADAccountPassword' when 'Password' parameter is specified" { Mock Get-ADUser { return $fakeADUser; } Mock Set-ADUser { } Mock Set-ADAccountPassword -ParameterFilter { $NewPassword -eq $testCredential.Password } -MockWith { } - + Set-TargetResource @testPresentParams -Password $testCredential; - + Assert-MockCalled Set-ADAccountPassword -ParameterFilter { $NewPassword -eq $testCredential.Password } -Scope It; } - + It "Calls 'Set-ADUser' with 'Replace' when existing matching AD property is null" { $testADPropertyName = 'Description'; Mock Get-ADUser { @@ -323,12 +341,12 @@ try return $duffADUser; } Mock Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -MockWith { } - + Set-TargetResource @testPresentParams -Description 'My custom description'; - + Assert-MockCalled Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1; } - + It "Calls 'Set-ADUser' with 'Replace' when existing matching AD property is empty" { $testADPropertyName = 'Description'; Mock Get-ADUser { @@ -337,12 +355,12 @@ try return $duffADUser; } Mock Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -MockWith { } - + Set-TargetResource @testPresentParams -Description 'My custom description'; - + Assert-MockCalled Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1; } - + It "Calls 'Set-ADUser' with 'Remove' when new matching AD property is empty" { $testADPropertyName = 'Description'; Mock Get-ADUser { @@ -351,12 +369,12 @@ try return $duffADUser; } Mock Set-ADUser -ParameterFilter { $Remove.ContainsKey($testADPropertyName) } -MockWith { } - + Set-TargetResource @testPresentParams -Description ''; - + Assert-MockCalled Set-ADUser -ParameterFilter { $Remove.ContainsKey($testADPropertyName) } -Scope It -Exactly 1; } - + It "Calls 'Set-ADUser' with 'Replace' when existing mismatched AD property is null" { $testADPropertyName = 'Title'; Mock Get-ADUser { @@ -365,12 +383,12 @@ try return $duffADUser; } Mock Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -MockWith { } - + Set-TargetResource @testPresentParams -JobTitle 'Gaffer'; - + Assert-MockCalled Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1; } - + It "Calls 'Set-ADUser' with 'Replace' when existing mismatched AD property is empty" { $testADPropertyName = 'Title'; Mock Get-ADUser { @@ -379,12 +397,12 @@ try return $duffADUser; } Mock Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -MockWith { } - + Set-TargetResource @testPresentParams -JobTitle 'Gaffer'; - + Assert-MockCalled Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1; } - + It "Calls 'Set-ADUser' with 'Remove' when new mismatched AD property is empty" { $testADPropertyName = 'Title'; Mock Get-ADUser { @@ -393,24 +411,24 @@ try return $duffADUser; } Mock Set-ADUser -ParameterFilter { $Remove.ContainsKey($testADPropertyName) } -MockWith { } - + Set-TargetResource @testPresentParams -JobTitle ''; - + Assert-MockCalled Set-ADUser -ParameterFilter { $Remove.ContainsKey($testADPropertyName) } -Scope It -Exactly 1; } - + It "Calls 'Remove-ADUser' when 'Ensure' is 'Absent' and user account exists" { Mock Get-ADUser { return [PSCustomObject] $fakeADUser; } Mock Remove-ADUser -ParameterFilter { $Identity.ToString() -eq $testAbsentParams.UserName } -MockWith { } - + Set-TargetResource @testAbsentParams; - + Assert-MockCalled Remove-ADUser -ParameterFilter { $Identity.ToString() -eq $testAbsentParams.UserName } -Scope It; } - + } #endregion - + #region Function Assert-TargetResource Describe "$($Global:DSCResourceName)\Assert-Parameters" { @@ -424,7 +442,7 @@ try } #endregion - + } #endregion } From b85849dd6714e44ec4d500f018dab3e3affb73af Mon Sep 17 00:00:00 2001 From: Iain Brighton Date: Thu, 9 Jun 2016 22:12:18 +0100 Subject: [PATCH 3/4] Fixes PasswordAuthenticationContext schema error --- DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof index c8e9df080..543ac158c 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof @@ -45,6 +45,6 @@ class MSFT_xADUser : OMI_BaseResource [Write, Description("Specifies whether the password of an account can expire")] Boolean PasswordNeverExpires; [Write, Description("Specifies the Active Directory Domain Services instance to use to perform the task.")] String DomainController; [Write, Description("Specifies the user account credentials to use to perform this task"), EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential; - [Write, Description("Specifies the authentication context type used when testing passwords")] ValueMap{"Default","Negotiate"}, Values{"Default","Negotiate"}] String PasswordAuthenticationContext; + [Write, Description("Specifies the authentication context type used when testing passwords"), ValueMap{"Default","Negotiate"},Values{"Default","Negotiate"}] String PasswordAuthenticationContext; [Read, Description("Returns the X.500 path of the object")] String DistinguishedName; }; From 2f5a3fcfacf95e36cbf385736b1c471f890a9589 Mon Sep 17 00:00:00 2001 From: Iain Brighton Date: Tue, 5 Jul 2016 12:22:41 +0100 Subject: [PATCH 4/4] Renames missed PasswordAuthenticationContext parameter to PasswordAuthentication in MSFT_xADUser.schema.mof Updates manager description --- DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 | 6 +++--- DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 b/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 index b099d4514..e5f0f84cd 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.psm1 @@ -231,7 +231,7 @@ function Get-TargetResource [ValidateNotNull()] [System.String] $IPPhone, - ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') + ## Specifies the user's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, @@ -492,7 +492,7 @@ function Test-TargetResource [ValidateNotNull()] [System.String] $IPPhone, - ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') + ## Specifies the user's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, @@ -741,7 +741,7 @@ function Set-TargetResource [ValidateNotNull()] [System.String] $IPPhone, - ## User's manager specified as a Distinguished Name (ldapDisplayName 'manager') + ## Specifies the user's manager specified as a Distinguished Name (ldapDisplayName 'manager') [ValidateNotNull()] [System.String] $Manager, diff --git a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof index 543ac158c..c0ad1d63e 100644 --- a/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof +++ b/DSCResources/MSFT_xADUser/MSFT_xADUser.schema.mof @@ -39,12 +39,12 @@ class MSFT_xADUser : OMI_BaseResource [Write, Description("Specifies the user's home telephone number (ldapDisplayName 'homePhone')")] String HomePhone; [Write, Description("Specifies the user's pager number (ldapDisplayName 'pager')")] String Pager; [Write, Description("Specifies the user's IP telephony phone number (ldapDisplayName 'ipPhone')")] String IPPhone; - [Write, Description("User's manager specified as a Distinguished Name (ldapDisplayName 'manager')")] String Manager; + [Write, Description("Specifies the user's manager specified as a Distinguished Name (ldapDisplayName 'manager')")] String Manager; [Write, Description("Specifies if the account is enabled (default True)")] Boolean Enabled; [Write, Description("Specifies whether the account password can be changed")] Boolean CannotChangePassword; [Write, Description("Specifies whether the password of an account can expire")] Boolean PasswordNeverExpires; [Write, Description("Specifies the Active Directory Domain Services instance to use to perform the task.")] String DomainController; [Write, Description("Specifies the user account credentials to use to perform this task"), EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential; - [Write, Description("Specifies the authentication context type used when testing passwords"), ValueMap{"Default","Negotiate"},Values{"Default","Negotiate"}] String PasswordAuthenticationContext; + [Write, Description("Specifies the authentication context type used when testing passwords"), ValueMap{"Default","Negotiate"},Values{"Default","Negotiate"}] String PasswordAuthentication; [Read, Description("Returns the X.500 path of the object")] String DistinguishedName; };