# # URL: http://blogs.msdn.com/adpowershell # NOTE: This script is just for proof-of-concept and is not intended to be production quality. # new-module -name ActiveDirectoryExtension -scriptblock { # # Description: This function sorts all the properties found in a ADEntity and # writes it to the console as string. # Tested using: Windows 2008 R2 Beta. # function Out-SortADProperties() { foreach ($msADE in $input) { $msADEProps = $msADE.PropertyNames | sort if ($msADEProps -ne $null) { foreach ($msADEProp in $msADEProps) { $msADEProp.ToString().PadRight(23) + ": " + $msADE[$msADEProp] } } } } # # Description: This function lists all the Ldap attributes that can be set on # the specified objectClass. # Tested using: Windows 2008 R2 Beta. # function Get-PossibleLdapAttributes() { Param ([Parameter(Mandatory=$true, Position=0)] [String] $ObjectClass) $rootDSE = Get-ADRootDSE $schemaObject = get-adobject -filter { ldapdisplayname -like $ObjectClass } -Properties mayContain, SystemMayContain, SubClassOf -searchbase $rootDSE.SchemaNamingContext $schemaObject.MayContain $schemaObject.SystemMayContain if ($ObjectClass -ne "top" -and $schemaObject.SubClassOf -ne "" -and $schemaObject.SubClassOf -ne $null) { Get-PossibleLdapAttributes $schemaObject.SubClassOf } } # # Description: The following functions are an extension (or wrapper) over Get-ADUser, # Get-ADGroup, Get-ADComputer and Get-ADServiceAccount cmdlets. # In addition to all the accepted form of identities for Get-ADUser, this function # supports NT4 style names (ex: fabrikam\administrator) and UserPrincipalName - UPN (ex: # administrator@fabrikam.com) # NOTE: NT4 style names would work for cross-forest and cross-domain scenarios. # UPN names would work only for cross-domain scenarios. # Tested using: Windows 2008 R2 Beta. # function Get-XADUser() { Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the User. NOTE: NT4 Style names such as: fabrikam\administrator and UPNs such as: administrator@fabrikam.com is acceptable" )] [Object] $Identity, [Parameter(Mandatory=$false, Position=1, HelpMessage="List of properties to fetch" )] [Object] $Properties ) Get-XADPrincipal -Identity $Identity -ObjectType "ADUser" -Properties $Properties } function Get-XADGroup() { Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the Group. NOTE: NT4 Style names such as: fabrikam\administrators" )] [Object] $Identity, [Parameter(Mandatory=$false, Position=1, HelpMessage="List of properties to fetch" )] [Object] $Properties ) Get-XADPrincipal -Identity $Identity -ObjectType "ADGroup" -Properties $Properties } function Get-XADComputer() { Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the Computer. NOTE: NT4 Style names such as: fabrikam\mymachine" )] [Object] $Identity, [Parameter(Mandatory=$false, Position=1, HelpMessage="List of properties to fetch" )] [Object] $Properties ) Get-XADPrincipal -Identity $Identity -ObjectType "ADComputer" -Properties $Properties } function Get-XADServiceAccount() { Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the ServiceAccount. NOTE: NT4 Style names such as: fabrikam\svcacct1" )] [Object] $Identity, [Parameter(Mandatory=$false, Position=1, HelpMessage="List of properties to fetch" )] [Object] $Properties ) Get-XADPrincipal -Identity $Identity -ObjectType "ADServiceAccount" -Properties $Properties } # # Advanced Function to create a new Site. # function New-XADSite() { [CmdletBinding(ConfirmImpact="Low")] Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the site to be created. Name is the only supported identity for this version of the script." )] [Object] $Identity, [Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$false, HelpMessage="Site link name to which the site will belong." )] [Object] $SiteLinkName ) BEGIN { } PROCESS { # In this version of the script the only identity supported is the site name # Replace the line below to support other identities $newSiteName = $Identity if ([String]::IsNullOrEmpty($newSiteName)) { throw New-Object System.Management.Automation.PSArgumentException("Site name cannot be an empty string, please try again.") } if ($SiteLinkName -eq $null) { $SiteLinkName = "DEFAULTIPSITELINK" } # Get the configuration partition DN, the sites container and build the new site DN $configNCDN = (Get-ADRootDSE).ConfigurationNamingContext $sitesContainerDN = ("CN=Sites," + $configNCDN) $newSiteDN = ("CN=" + $newSiteName +"," + $sitesContainerDN) $siteLinkContainerDN = ("CN=" + $SiteLinkName + ",CN=IP,CN=Inter-Site Transports,CN=Sites," + $configNCDN) # Verify if the site link exists $siteLinkExists = Test-XADObject -Identity $siteLinkContainerDN if ($siteLinkExists -eq $false) { throw New-Object System.Management.Automation.RuntimeException("The site link you provided does not exist. Please check the name and try again.") } # Verify if the site already exists $siteExists = Test-XADObject -Identity $newSiteDN if ($siteExists) { throw New-Object System.Management.Automation.RuntimeException("Site already exists. Please check the name and try again.") } else { $siteObjectCreated = $false trap [Exception] { # Output the error to the pipeline Write-Host $_ # Remove any objects created for consistency if ($siteObjectCreated -eq $true) { Remove-ADObject -Identity $newSiteDN -Recursive -Confirm:$false } # Throw a new exception with the trapped exception as inner exception throw New-Object System.Management.Automation.RuntimeException("An exception occurred when creating the site. See inner exceptions for more details.", $_.Exception) } # Create Site, NTDS Site Settings and Server objects New-ADObject -Name $newSiteName -Path $sitesContainerDN -Type site $siteObjectCreated = $true New-ADObject -Name "NTDS Site Settings" -Path $newSiteDN -Type nTDSSiteSettings New-ADObject -Name "Servers" -Path $newSiteDN -Type serversContainer $siteLink = Get-ADObject $siteLinkContainerDN -Properties siteList $numberOfSitesInSiteLink = $siteLink.siteList.Add($newSiteDN) Set-ADObject -Instance $siteLink # Return the directory objects that make the AD site Get-ADObject -Identity $newSiteDN Get-ADObject -Identity ("CN=NTDS Site Settings," + $newSiteDN) Get-ADObject -Identity ("CN=Servers," + $newSiteDN) } } END { } } # # Internal utility function # This is a function that returns true if a given AD object exists provided its identity # function Test-XADObject() { [CmdletBinding(ConfirmImpact="Low")] Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the AD object to verify if exists or not." )] [Object] $Identity ) trap [Exception] { return $false } $auxObject = Get-ADObject -Identity $Identity return $true } # # Internal utility function # function GetServer() { Param ([String] $serverName) if ($serverName -ne $null -and $serverName -ne "") { $portSeparatorInd = $serverName.IndexOf(":") if ($portSeparatorInd -ge 0) { $serverName.SubString(0, $portSeparatorInd) } else { $serverName } } else { $rootdse = get-adrootdse $rootdse.dnsHostName } } # # Internal utility function # # Description: This is an utility function that acts as a or wrapper over Get-ADUser, Get-ADGroup etc. . # Tested using: Windows 2008 R2 Beta. # function Get-XADPrincipal() { [CmdletBinding(ConfirmImpact="Low")] Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the Principal. NOTE: NT4 Style names such as: fabrikam\administrator is acceptable" )] [Object] $Identity, [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$false, HelpMessage="Type of the Principal. Supported types: G or ADGroup, U or ADUser, C or ADComputer, S or ADServiceAccount" )] [String] $ObjectType, [Parameter(Mandatory=$false, Position=2, HelpMessage="List of properties to fetch" )] [Object] $Properties ) BEGIN { $ActualProperties = $null if ($ObjectType -eq "ADUser" -or $ObjectType -eq "u") { $commandStr = "Get-ADUser " if ($Properties -ne $null) { $ActualProperties = $ADPS_ADUserAllProperties | Select-String -Pattern $Properties } } elseif ($ObjectType -eq "ADGroup"-or $ObjectType -eq "g") { $commandStr = "Get-ADGroup " if ($Properties -ne $null) { $ActualProperties = $ADPS_ADGroupAllProperties | Select-String -Pattern $Properties } } elseif ($ObjectType -eq "ADComputer"-or $ObjectType -eq "c") { $commandStr = "Get-ADComputer " if ($Properties -ne $null) { $ActualProperties = $ADPS_ADComputerAllProperties | Select-String -Pattern $Properties } } elseif ($ObjectType -eq "ADServiceAccount"-or $ObjectType -eq "s") { $commandStr = "Get-ADServiceAccount " if ($Properties -ne $null) { $ActualProperties = $ADPS_ADServiceAccountAllProperties | Select-String -Pattern $Properties } } } PROCESS { if ($Identity.GetType() -eq [String] ) { # # A valid NT4 style name would always contain backward slash \ # Check if char '=' is not found .. so that we don't process DNs with \. # if ($Identity.Contains("\") -and ! $Identity.Contains("=") ) { $xNewServer,$xNewIdentity = $Identity.split("\", 2) $commandStr += " -Identity $xNewIdentity -Server $xNewServer " } # # A valid UPN would always contain @ # Check if char '=' is not found .. so that we don't process DNs with @. # elseif ($Identity.Contains("@") -and ! $Identity.Contains("=") ) { $xNewServer = (GetServer $null) + ":3268" #Talk to a GC for cracking UPN names $xFilter = " { userPrincipalName -eq '$Identity' } " $commandStr += " -Filter $xFilter -Server $xNewServer " } else { $commandStr += " -Identity $Identity " } } else { $commandStr += " -Identity '" + $Identity.ToString() + "'" } if ($ActualProperties -ne $null) { $commandStr += " -Properties " foreach($prop in $ActualProperties) { $commandStr += "'" + $prop + "', " } $commandStr = $commandStr.SubString(0, $commandStr.Length - 2) ## Remove the last comma and space character. } $scriptBlock = [ScriptBlock]::Create( $commandStr ) $scriptBlock.Invoke() } END { } } # # Internal utility function # # Description: This is function creates a query variable # Tested using: Windows 2008 R2 RC. # function CreateXADQueryVariable() { [CmdletBinding(ConfirmImpact="Low")] Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="All Object property list" )] [Array] $AllProperties, [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$false, HelpMessage="Property Class Name" )] [string] $PropertyClassName ) PROCESS { $memberDefinition = "" foreach ($propValue in $AllProperties) { $propName = $propValue.Replace("-", "_") $memberDefinition += ' public string ' + $propName + '{ get { return "' + $propValue + '"; }}' } add-type -Name $PropertyClassName -MemberDefinition $memberDefinition -NameSpace "Microsoft.ActiveDirectoryExtensions" $qObject = New-Object -Type ("Microsoft.ActiveDirectoryExtensions." + $PropertyClassName) $qObject } } # # Internal utility function # # Description: Main function # Tested using: Windows 2008 R2 RC. # function XADMain() { $ADPS_ADObjectExtendedPropertyArray = "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADPrincipalExtendedPropertyArray = "SamAccountName", "SID", "HomePage", "SIDHistory", "MemberOf", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADAccountExtendedPropertyArray = "UserPrincipalName", "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", "BadLogonCount", "CannotChangePassword", "Certificates", "AccountNotDelegated", "Enabled", "LastBadPasswordAttempt", "LastLogonDate", "LockedOut", "PasswordLastSet", "PasswordNeverExpires", "PasswordNotRequired", "PrimaryGroup", "ServicePrincipalNames", "TrustedForDelegation", "TrustedToAuthForDelegation", "MNSLogonAccount", "DoesNotRequirePreAuth", "PasswordExpired", "HomedirRequired", "UseDESKeyOnly", "SamAccountName", "SID", "HomePage", "SIDHistory", "MemberOf", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADGroupExtendedPropertyArray = "GroupScope", "GroupCategory", "ManagedBy", "Members", "SamAccountName", "SID", "HomePage", "SIDHistory", "MemberOf", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADUserExtendedPropertyArray = "GivenName", "Surname", "HomeDirectory", "HomeDrive", "Manager", "OtherName", "LogonWorkstations", "ProfilePath", "ScriptPath", "SmartcardLogonRequired", "OfficePhone", "Company", "Department", "Fax", "Initials", "MobilePhone", "HomePhone", "Office", "PostalCode", "POBox", "State", "StreetAddress", "Title", "Division", "Country", "City", "EmployeeID", "EmployeeNumber", "Organization", "EmailAddress", "UserPrincipalName", "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", "BadLogonCount", "CannotChangePassword", "Certificates", "AccountNotDelegated", "Enabled", "LastBadPasswordAttempt", "LastLogonDate", "LockedOut", "PasswordLastSet", "PasswordNeverExpires", "PasswordNotRequired", "PrimaryGroup", "ServicePrincipalNames", "TrustedForDelegation", "TrustedToAuthForDelegation", "MNSLogonAccount", "DoesNotRequirePreAuth", "PasswordExpired", "HomedirRequired", "UseDESKeyOnly", "SamAccountName", "SID", "HomePage", "SIDHistory", "MemberOf", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADComputerExtendedPropertyArray = "SamAccountName", "DNSHostName", "ServiceAccount", "IPv4Address", "IPv6Address", "Location", "ManagedBy", "OperatingSystem", "OperatingSystemHotfix", "OperatingSystemServicePack", "OperatingSystemVersion", "UserPrincipalName", "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", "BadLogonCount", "CannotChangePassword", "Certificates", "AccountNotDelegated", "Enabled", "LastBadPasswordAttempt", "LastLogonDate", "LockedOut", "PasswordLastSet", "PasswordNeverExpires", "PasswordNotRequired", "PrimaryGroup", "ServicePrincipalNames", "TrustedForDelegation", "TrustedToAuthForDelegation", "MNSLogonAccount", "DoesNotRequirePreAuth", "PasswordExpired", "HomedirRequired", "UseDESKeyOnly", "SID", "HomePage", "SIDHistory", "MemberOf", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADOrganizationalUnitExtendedPropertyArray = "ManagedBy", "StreetAddress", "PostalCode", "City", "State", "Country", "LinkedGroupPolicyObjects", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADFineGrainedPasswordPolicyExtendedPropertyArray = "LockoutDuration", "LockoutObservationWindow", "LockoutThreshold", "MaxPasswordAge", "MinPasswordAge", "MinPasswordLength", "PasswordHistoryCount", "ComplexityEnabled", "ReversibleEncryptionEnabled", "Precedence", "AppliesTo", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADServiceAccountExtendedPropertyArray = "SamAccountName", "HostComputers", "UserPrincipalName", "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", "BadLogonCount", "CannotChangePassword", "Certificates", "AccountNotDelegated", "Enabled", "LastBadPasswordAttempt", "LastLogonDate", "LockedOut", "PasswordLastSet", "PasswordNeverExpires", "PasswordNotRequired", "PrimaryGroup", "ServicePrincipalNames", "TrustedForDelegation", "TrustedToAuthForDelegation", "MNSLogonAccount", "DoesNotRequirePreAuth", "PasswordExpired", "HomedirRequired", "UseDESKeyOnly", "SID", "HomePage", "SIDHistory", "MemberOf", "DistinguishedName", "ObjectClass", "CanonicalName", "ObjectGUID", "CN", "Created", "Description", "DisplayName", "Deleted", "LastKnownParent", "Modified", "ObjectCategory", "Name", "ProtectedFromAccidentalDeletion" $ADPS_ADDomainControllerExtendedPropertyArray = "IsReadOnly", "IsGlobalCatalog", "Enabled", "OperatingSystemVersion", "OperatingSystem", "OperatingSystemServicePack", "OperatingSystemHotfix", "ComputerObjectDN", "Domain", "Forest", "Name", "Site", "IPv4Address", "IPv6Address", "Partitions", "DefaultPartition", "HostName", "LdapPort", "SslPort", "OperationMasterRoles", "NTDSSettingsObjectDN", "ServerObjectDN", "ServerObjectGuid", "InvocationId" $global:ADPS_ADObjectAllProperties = ($ADPS_ADObjectExtendedPropertyArray + (Get-PossibleLdapAttributes top)) | sort -unique $global:ADPS_ADPrincipalAllProperties = ($ADPS_ADPrincipalExtendedPropertyArray + (Get-PossibleLdapAttributes top)) | sort -unique $global:ADPS_ADAccountAllProperties = ($ADPS_ADAccountExtendedPropertyArray + (Get-PossibleLdapAttributes user)) | sort -unique $global:ADPS_ADGroupAllProperties = ($ADPS_ADGroupExtendedPropertyArray + (Get-PossibleLdapAttributes group)) | sort -unique $global:ADPS_ADUserAllProperties = ($ADPS_ADUserExtendedPropertyArray + (Get-PossibleLdapAttributes user)) | sort -unique $global:ADPS_ADComputerAllProperties = ($ADPS_ADComputerExtendedPropertyArray + (Get-PossibleLdapAttributes computer )) | sort -unique $global:ADPS_ADOrganizationalUnitAllProperties = ($ADPS_ADOrganizationalUnitExtendedPropertyArray + (Get-PossibleLdapAttributes organizationalUnit)) | sort -unique $global:ADPS_ADFineGrainedPasswordPolicyAllProperties = ($ADPS_ADFineGrainedPasswordPolicyExtendedPropertyArray + (Get-PossibleLdapAttributes "msDS-PasswordSettings")) | sort -unique $global:ADPS_ADServiceAccountAllProperties = ($ADPS_ADServiceAccountExtendedPropertyArray + (Get-PossibleLdapAttributes "msDS-ManagedServiceAccount")) | sort -unique $global:ADPS_ADDomainControllerAllProperties = ($ADPS_ADDomainControllerExtendedPropertyArray) $global:xADObject = CreateXADQueryVariable $ADPS_ADObjectAllProperties ADObjectProp $global:xADPrincipal = CreateXADQueryVariable $ADPS_ADPrincipalAllProperties ADPrincipalProp $global:xADAccount = CreateXADQueryVariable $ADPS_ADAccountAllProperties ADAccountProp $global:xADGroup = CreateXADQueryVariable $ADPS_ADGroupAllProperties ADGroupProp $global:xADUser = CreateXADQueryVariable $ADPS_ADUserAllProperties ADUserProp $global:xADComputer = CreateXADQueryVariable $ADPS_ADComputerAllProperties ADComputerProp $global:xADOrganizationalUnit = CreateXADQueryVariable $ADPS_ADOrganizationalUnitAllProperties ADOrganizationalUnitProp $global:xADFineGrainedPasswordPolicy = CreateXADQueryVariable $ADPS_ADFineGrainedPasswordPolicyAllProperties ADFineGrainedPasswordPolicyProp $global:xADServiceAccount = CreateXADQueryVariable $ADPS_ADServiceAccountAllProperties ADServiceAccountProp $global:xADDomainController = CreateXADQueryVariable $ADPS_ADDomainControllerAllProperties ADDomainControllerProp } # # Invoke Main function from the script # XADMain }