Added Files
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Update the DistinguishedName Attribute for all Active Directory Users
|
||||
|
||||
.DESCRIPTION
|
||||
Update the DistinguishedName Attribute for all Active Directory Users.
|
||||
It will update the 'CN=' to match the SamAccountName
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> .\Convert-ADDistinguishedNameForAllUser.ps1
|
||||
|
||||
.NOTES
|
||||
MIND THE GAP:
|
||||
This will change the DistinguishedName and this might break things
|
||||
|
||||
It will only update/change the DistinguishedName if the 'CN=' does NOT match the SamAccountName
|
||||
|
||||
I created this to bulk migrate older users, they had german umlauts and other crappy character in the DistinguishedName
|
||||
|
||||
.LINK
|
||||
https://github.com/jhochwald/PowerShell-collection/
|
||||
|
||||
.LINK
|
||||
Get-ADUser
|
||||
|
||||
.LINK
|
||||
Rename-ADObject
|
||||
#>
|
||||
[CmdletBinding(ConfirmImpact = 'Medium',
|
||||
SupportsShouldProcess)]
|
||||
param ()
|
||||
|
||||
if ($pscmdlet.ShouldProcess('All Users', 'Set'))
|
||||
{
|
||||
try
|
||||
{
|
||||
$AllUsers = (Get-ADUser -Filter * -Properties SamAccountName, UserPrincipalName, DistinguishedName -ErrorAction Stop | Select-Object -Property SamAccountName, UserPrincipalName, DistinguishedName | Where-Object -FilterScript {
|
||||
($_.UserPrincipalName) -and ($_.SamAccountName)
|
||||
})
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message $e.Exception.Message -ErrorAction Stop
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach ($User in $AllUsers)
|
||||
{
|
||||
$OldRDN = (($User | Select-Object -Property @{
|
||||
l = 'OldRDN'
|
||||
e = {
|
||||
$_.DistinguishedName.split(',')[0].split('=')[1]
|
||||
}
|
||||
}) | Select-Object -ExpandProperty OldRDN)
|
||||
|
||||
if ($OldRDN -ne ($User.SamAccountName))
|
||||
{
|
||||
# Mind the Gap: This will change the DistinguishedName and this might break things
|
||||
$null = (Rename-ADObject -Identity $User.DistinguishedName -NewName $User.SamAccountName -Confirm:$false -ErrorAction Stop)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,399 @@
|
||||
function Copy-ADGroupUserMembership
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Copy the membership of a given group to another group in Active Directory
|
||||
|
||||
.DESCRIPTION
|
||||
Copy the membership of a given group to another group in Active Directory.
|
||||
By default only the members of the Source Group will be copied to the Target Group.
|
||||
If the Parameter FULL is used, the members of the Target Group that are not a member of the Source Group will be removed.
|
||||
If the Parameter SYNC is used, the Membership is synced between both groups. If a User is Member of the Target Group only, this membership will be copied to the Source as well.
|
||||
|
||||
.PARAMETER SourceGroup
|
||||
Source-Group Object.
|
||||
|
||||
Specifies an Active Directory group object by providing one of the following values. The identifier in
|
||||
parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
|
||||
Example: CN=saradavisreports,OU=europe,CN=users,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
Security Identifier (objectSid)
|
||||
|
||||
Example: S-1-5-21-3165297888-301567370-576410423-1103
|
||||
|
||||
Security Accounts Manager (SAM) Account Name (sAMAccountName)
|
||||
|
||||
Example: saradavisreports
|
||||
|
||||
The cmdlet searches the default naming context or partition to find the object. If two or more objects are
|
||||
found, the cmdlet returns a non-terminating error.
|
||||
|
||||
This parameter can also get this object through the pipeline or you can set this parameter to an object
|
||||
instance.
|
||||
|
||||
.PARAMETER TargetGroup
|
||||
Target-Group Object.
|
||||
|
||||
Specifies an Active Directory group object by providing one of the following values. The identifier in
|
||||
parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
|
||||
Example: CN=saradavisreports,OU=europe,CN=users,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
Security Identifier (objectSid)
|
||||
|
||||
Example: S-1-5-21-3165297888-301567370-576410423-1103
|
||||
|
||||
Security Accounts Manager (SAM) Account Name (sAMAccountName)
|
||||
|
||||
Example: saradavisreports
|
||||
|
||||
The cmdlet searches the default naming context or partition to find the object. If two or more objects are
|
||||
found, the cmdlet returns a non-terminating error.
|
||||
|
||||
This parameter can also get this object through the pipeline or you can set this parameter to an object
|
||||
instance.
|
||||
|
||||
.PARAMETER full
|
||||
Remove all memberships from the Targewt that does NOT exist in the the Source.
|
||||
|
||||
.PARAMETER sync
|
||||
Synchronies the group membership between Source-Group and Target-Group.
|
||||
Even if a user is a member of the Target-Group only, it will be copied to the Source-Group as well.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADGroupUserMembership -SourceGroup 'Sales' -TargetGroup 'Salesforce'
|
||||
|
||||
Copy the membership of the Group 'Sales' to 'Salesforce'
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADGroupUserMembership -SourceGroup 'Sales' -TargetGroup 'Salesforce' -sync
|
||||
|
||||
Copy the membership of the Group 'Sales' to 'Salesforce' and the other way around.
|
||||
All Memberships of 'Salesforce' that does NOT exist in 'Sales' will be created in 'Sales' as well.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADGroupUserMembership -SourceGroup 'Sales' -TargetGroup 'Salesforce' -full
|
||||
|
||||
Copy the membership of the Group 'Sales' to 'Salesforce'.
|
||||
All Memberships of 'Salesforce' that does NOT exist in 'Sales' will be removed.
|
||||
|
||||
.NOTES
|
||||
Initial AIT version of the function
|
||||
|
||||
.LINK
|
||||
https://github.com/jhochwald/PowerShell-collection/
|
||||
|
||||
.LINK
|
||||
Get-ADGroupMember
|
||||
|
||||
.LINK
|
||||
Remove-ADGroupMember
|
||||
|
||||
.LINK
|
||||
Add-ADGroupMember
|
||||
|
||||
.LINK
|
||||
Copy-ADUserGroupMemberships
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = 'default',
|
||||
ConfirmImpact = 'Low',
|
||||
SupportsShouldProcess)]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 0,
|
||||
HelpMessage = 'Source-Group Object.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Source')]
|
||||
[string]
|
||||
$SourceGroup,
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 1,
|
||||
HelpMessage = 'Target-Group Object.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Target')]
|
||||
[string]
|
||||
$TargetGroup,
|
||||
[Parameter(ParameterSetName = 'full',
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 2)]
|
||||
[Alias('RemoveTargetOnlyMembers')]
|
||||
[switch]
|
||||
$full = $null,
|
||||
[Parameter(ParameterSetName = 'sync',
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 2)]
|
||||
[Alias('MakeFullSync')]
|
||||
[switch]
|
||||
$sync = $null
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess('Groups', 'Get information from Active Directory'))
|
||||
{
|
||||
try
|
||||
{
|
||||
$SourceMembers = (Get-ADGroupMember -Identity $SourceGroup -ErrorAction Stop | Select-Object -ExpandProperty distinguishedName | Sort-Object)
|
||||
$TargetMembers = (Get-ADGroupMember -Identity $TargetGroup -ErrorAction Stop | Select-Object -ExpandProperty distinguishedName | Sort-Object)
|
||||
|
||||
# Check if we have any diferences
|
||||
if (($SourceMembers) -and ($TargetMembers))
|
||||
{
|
||||
# Yep, there are differences
|
||||
$Differences = (Compare-Object -ReferenceObject $SourceMembers -DifferenceObject $TargetMembers)
|
||||
}
|
||||
elseif (($SourceMembers) -and (-not($TargetMembers)))
|
||||
{
|
||||
# Target has no members
|
||||
$Differences = 'SourceOnly'
|
||||
}
|
||||
elseif (-not($SourceMembers))
|
||||
{
|
||||
# Source has no members
|
||||
Write-Error -Message ('{0} has no members!' -f $SourceGroup) -ErrorAction Stop
|
||||
}
|
||||
else
|
||||
{
|
||||
# Nope, there are no differences
|
||||
$Differences = $null
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message $e.Exception.Message -ErrorAction Stop
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
|
||||
switch ($pscmdlet.ParameterSetName)
|
||||
{
|
||||
'full'
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess($TargetGroup, 'Set'))
|
||||
{
|
||||
if ($Differences)
|
||||
{
|
||||
Write-Verbose -Message 'Remove Target-User from all groups where the Source-User is not a member of.'
|
||||
|
||||
$TargetOnlyMembers = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>')
|
||||
|
||||
if ($TargetOnlyMembers)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ($TargetOnlyMember in $TargetOnlyMembers.InputObject)
|
||||
{
|
||||
Write-Verbose -Message ('Process: {0}' -f $TargetOnlyMember)
|
||||
|
||||
$paramRemoveADGroupMember = @{
|
||||
Identity = $TargetGroup
|
||||
Members = $TargetOnlyMember
|
||||
ErrorAction = 'Stop'
|
||||
Confirm = $false
|
||||
}
|
||||
$null = (Remove-ADGroupMember @paramRemoveADGroupMember -Verbose)
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose -Message 'No group difference found where the Target-User is a member and Source-User is not.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'sync'
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess($SourceGroup, 'Set'))
|
||||
{
|
||||
if ($Differences)
|
||||
{
|
||||
Write-Verbose -Message 'Make the Source-user a Member of all Groups only the Target-User is a member of.'
|
||||
|
||||
$TargetOnlyMembers = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>')
|
||||
|
||||
if ($TargetOnlyMembers)
|
||||
{
|
||||
Write-Verbose -Message ('Process: {0}' -f $TargetOnlyMembers)
|
||||
|
||||
try
|
||||
{
|
||||
$paramAddADGroupMember = @{
|
||||
Identity = $SourceGroup
|
||||
Members = $TargetOnlyMembers.InputObject
|
||||
ErrorAction = 'Stop'
|
||||
Confirm = $false
|
||||
}
|
||||
$null = (Add-ADGroupMember @paramAddADGroupMember)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose -Message 'No group difference found where the Target-User is a member and Source-User is not.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'default'
|
||||
{
|
||||
# Do nothing special
|
||||
}
|
||||
}
|
||||
|
||||
if ($pscmdlet.ShouldProcess($TargetGroup, 'Set'))
|
||||
{
|
||||
if ($Differences)
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Verbose -Message 'Process all Source-Group only members.'
|
||||
|
||||
$paramAddADGroupMember = @{
|
||||
Identity = $TargetGroup
|
||||
ErrorAction = 'Stop'
|
||||
Confirm = $false
|
||||
}
|
||||
|
||||
if ($Differences -eq 'SourceOnly')
|
||||
{
|
||||
# Target has no members
|
||||
$paramAddADGroupMember.Members = $SourceMembers
|
||||
}
|
||||
else
|
||||
{
|
||||
$paramAddADGroupMember.Members = ($Differences | Where-Object -Property SideIndicator -EQ -Value '<=' | Select-Object -ExpandProperty InputObject)
|
||||
}
|
||||
|
||||
$null = (Add-ADGroupMember @paramAddADGroupMember)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,385 @@
|
||||
function Copy-ADUserGroupMembership
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Copy group memberships from a given Source-User to a Target-User in Active Directory
|
||||
|
||||
.DESCRIPTION
|
||||
Copy group memberships from a given Source-User to a Target-User in Active Directory.
|
||||
The function can also remove the Target-User from all groups where the Source-User is not a member off (optional) or make the Source-User a member of all groups where only the Target-User is a member of.
|
||||
|
||||
.PARAMETER SourceUser
|
||||
Source-User Object.
|
||||
|
||||
Specifies an Active Directory user object by providing one of the following property values.
|
||||
The identifier in parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
|
||||
Example: CN=SaraDavis,CN=Europe,CN=Users,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
Security Identifier (objectSid)
|
||||
|
||||
Example: S-1-5-21-3165297888-301567370-576410423-1103
|
||||
|
||||
SAM account name (sAMAccountName)
|
||||
|
||||
Example: saradavis
|
||||
|
||||
.PARAMETER TargetUser
|
||||
Target-User Object.
|
||||
|
||||
Specifies an Active Directory user object by providing one of the following property values.
|
||||
The identifier in parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
|
||||
Example: CN=SaraDavis,CN=Europe,CN=Users,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
Security Identifier (objectSid)
|
||||
|
||||
Example: S-1-5-21-3165297888-301567370-576410423-1103
|
||||
|
||||
SAM account name (sAMAccountName)
|
||||
|
||||
Example: saradavis
|
||||
|
||||
.PARAMETER full
|
||||
Remove the Target User from all groups where the Source-User is not a member of.
|
||||
|
||||
.PARAMETER sync
|
||||
Make the Source-User a member of all Groups where only the Target-User is a member of.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADUserGroupMembership -SourceUser 'johndoe' -TargetUser 'janedoe'
|
||||
|
||||
Make janedoe a member of all groups where johndoe is a member of. Existing group memberships of janedoe will NOT be removed.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADUserGroupMembership -SourceUser 'johndoe' -TargetUser 'janedoe' -full
|
||||
|
||||
Make janedoe a member of all groups where johndoe is a member of. Existing group memberships of janedoe WILL be removed.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADUserGroupMembership -SourceUser 'johndoe' -TargetUser 'janedoe' -sync
|
||||
|
||||
Make janedoe a member of all groups where johndoe is a member of. Existing group memberships of janedoe WILL be applied to johndoe.
|
||||
Lets call this a reverse Full Sync :)
|
||||
|
||||
.NOTES
|
||||
Initial AIT version of the function
|
||||
|
||||
.LINK
|
||||
https://github.com/jhochwald/PowerShell-collection/
|
||||
|
||||
.LINK
|
||||
Get-ADUser
|
||||
|
||||
.LINK
|
||||
Remove-ADGroupMember
|
||||
|
||||
.LINK
|
||||
Add-ADGroupMember
|
||||
|
||||
.LINK
|
||||
Copy-ADGroupUserMemberships
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = 'default',
|
||||
SupportsShouldProcess)]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 0,
|
||||
HelpMessage = 'Source-User Object.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Source')]
|
||||
[string]
|
||||
$SourceUser,
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 1,
|
||||
HelpMessage = 'Target-User Object.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Target')]
|
||||
[string]
|
||||
$TargetUser,
|
||||
[Parameter(ParameterSetName = 'full',
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 2)]
|
||||
[Alias('RemoveTargetOnlyGroups')]
|
||||
[switch]
|
||||
$full = $null,
|
||||
[Parameter(ParameterSetName = 'sync',
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 2)]
|
||||
[Alias('MakeFullSync')]
|
||||
[switch]
|
||||
$sync = $null
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess('User', 'Get information from Active Directory'))
|
||||
{
|
||||
try
|
||||
{
|
||||
# Get the Target-User
|
||||
$TargetUserObject = (Get-ADUser -Identity $TargetUser -Properties memberOf -ErrorAction Stop)
|
||||
|
||||
# Get the Source-User
|
||||
$SourceUserObject = (Get-ADUser -Identity $SourceUser -Properties memberOf -ErrorAction Stop)
|
||||
|
||||
# Sort and save the information we collected above
|
||||
$SourceUserMembership = ($SourceUserObject.MemberOf | Sort-Object)
|
||||
$TargetUserMembership = ($TargetUserObject.MemberOf | Sort-Object)
|
||||
|
||||
# Check if we have any diferences
|
||||
if (($SourceUserMembership) -and ($TargetUserMembership))
|
||||
{
|
||||
# Yep, there are differences
|
||||
$Differences = (Compare-Object -ReferenceObject $SourceUserMembership -DifferenceObject $TargetUserMembership)
|
||||
}
|
||||
else
|
||||
{
|
||||
# Nope, there are no differences
|
||||
$Differences = $null
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message $e.Exception.Message -ErrorAction Stop
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
switch ($pscmdlet.ParameterSetName)
|
||||
{
|
||||
'full'
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess($SourceUser, 'Set'))
|
||||
{
|
||||
if ($Differences)
|
||||
{
|
||||
Write-Verbose -Message 'Remove Target-User from all groups where the Source-User is not a member of.'
|
||||
|
||||
$TargetOnlyGroups = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>')
|
||||
|
||||
if ($TargetOnlyGroups)
|
||||
{
|
||||
foreach ($TargetOnlyGroup in $TargetOnlyGroups.InputObject)
|
||||
{
|
||||
Write-Verbose -Message ('Process: {0}' -f $TargetOnlyGroup)
|
||||
|
||||
try
|
||||
{
|
||||
$paramRemoveADGroupMember = @{
|
||||
Identity = $TargetOnlyGroup
|
||||
Members = $TargetUser
|
||||
ErrorAction = 'Stop'
|
||||
Confirm = $false
|
||||
}
|
||||
$null = (Remove-ADGroupMember @paramRemoveADGroupMember)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose -Message 'No group difference fround where the Target-User is a member and Source-User is not.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'sync'
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess($SourceUser, 'Set'))
|
||||
{
|
||||
if ($Differences)
|
||||
{
|
||||
Write-Verbose -Message 'Make the Source-user a Member of all Groups only the Target-User is a member of.'
|
||||
|
||||
$TargetOnlyGroups = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>')
|
||||
|
||||
if ($TargetOnlyGroups)
|
||||
{
|
||||
foreach ($TargetOnlyGroup in $TargetOnlyGroups.InputObject)
|
||||
{
|
||||
Write-Verbose -Message ('Process: {0}' -f $TargetOnlyGroup)
|
||||
|
||||
try
|
||||
{
|
||||
$paramAddADGroupMember = @{
|
||||
Identity = $TargetOnlyGroup
|
||||
Members = $SourceUser
|
||||
ErrorAction = 'Stop'
|
||||
Confirm = $false
|
||||
}
|
||||
$null = (Add-ADGroupMember @paramAddADGroupMember)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose -Message 'No group difference fround where the Target-User is a member and Source-User is not.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'default'
|
||||
{
|
||||
# Do nothing special
|
||||
}
|
||||
}
|
||||
|
||||
if ($pscmdlet.ShouldProcess($TargetUser, 'Set'))
|
||||
{
|
||||
if ($Differences)
|
||||
{
|
||||
$SourceOnlyGroups = ($Differences | Where-Object -Property SideIndicator -EQ -Value '<=')
|
||||
|
||||
if ($SourceOnlyGroups)
|
||||
{
|
||||
Write-Verbose -Message 'Process all Groups where only the Source-user is a member of.'
|
||||
|
||||
foreach ($SourceOnlyGroup in $SourceOnlyGroups.InputObject)
|
||||
{
|
||||
Write-Verbose -Message ('Process: {0}' -f $SourceOnlyGroup)
|
||||
|
||||
try
|
||||
{
|
||||
$paramAddADGroupMember = @{
|
||||
Identity = $SourceOnlyGroup
|
||||
Members = $TargetUser
|
||||
ErrorAction = 'Stop'
|
||||
Confirm = $false
|
||||
}
|
||||
$null = (Add-ADGroupMember @paramAddADGroupMember)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Warning -Message 'No group difference fround where the Source-User is a member and Source-User is not.' -WarningAction Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,224 @@
|
||||
function Copy-ADUserGroupMembershipSimple
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Copy group memberships from a given Source User to a Target User(s) in Active Directory
|
||||
|
||||
.DESCRIPTION
|
||||
Copy group memberships from a given Source User to a Target User(s) in Active Directory.
|
||||
Simple Version of Copy-ADUserGroupMemberships
|
||||
|
||||
.PARAMETER SourceUser
|
||||
Source-User Object.
|
||||
|
||||
Specifies an Active Directory group object by providing one of the following values.
|
||||
The identifier in parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
Example: CN=johndoe,OU=europe,CN=users,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
Security Identifier (objectSid)
|
||||
Example: S-1-5-21-3165297888-301567370-576410423-1103
|
||||
|
||||
Security Accounts Manager (SAM) Account Name (sAMAccountName)
|
||||
Example: johndoe
|
||||
|
||||
.PARAMETER TargetUser
|
||||
Target-User Object.
|
||||
|
||||
Specifies an Active Directory group object by providing one of the following values.
|
||||
The identifier in parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
Example: CN=janedoe,OU=europe,CN=users,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
Security Identifier (objectSid)
|
||||
Example: S-1-5-21-3165297888-301567370-576410423-1103
|
||||
|
||||
Security Accounts Manager (SAM) Account Name (sAMAccountName)
|
||||
Example: janedoe
|
||||
|
||||
.PARAMETER PassThru
|
||||
Use the -PassThru parameter with the previous command to receive feedback about what groups the Target is being added as a member of.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADUserGroupMembershipSimple -SourceUser 'SourceUser' -TargetUser 'TargetUser'
|
||||
|
||||
Copy group memberships from SourceUser to TargetUser
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADUserGroupMembershipSimple -SourceUser 'SourceUser' -TargetUser 'TargetUser1', 'TargetUser2'
|
||||
|
||||
Copy group memberships from SourceUser to TargetUser1 and TargetUser2
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Copy-ADUserGroupMembershipSimple -SourceUser 'SourceUser' -TargetUser 'TargetUser' -PassThru
|
||||
|
||||
Use the -PassThru parameter with the previous command to receive feedback about what groups the Target is being added as a member of.
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.0 2019-07-09: Initial Release
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
.LINK
|
||||
Copy-ADUserGroupMemberships
|
||||
|
||||
.LINK
|
||||
https://github.com/jhochwald/PowerShell-collection/
|
||||
|
||||
.LINK
|
||||
Get-ADUser
|
||||
|
||||
.LINK
|
||||
Add-ADGroupMember
|
||||
#>
|
||||
|
||||
[CmdletBinding(ConfirmImpact = 'Low',
|
||||
SupportsShouldProcess = $true)]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true,
|
||||
ValueFromPipelineByPropertyName = $true,
|
||||
Position = 0,
|
||||
HelpMessage = 'Source-User Object.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Source')]
|
||||
[string]
|
||||
$SourceUser,
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true,
|
||||
ValueFromPipelineByPropertyName = $true,
|
||||
Position = 1,
|
||||
HelpMessage = 'Target-User Object.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Target')]
|
||||
[string[]]
|
||||
$TargetUser,
|
||||
[Parameter(ValueFromPipeline = $true,
|
||||
ValueFromPipelineByPropertyName = $true,
|
||||
Position = 2)]
|
||||
[switch]
|
||||
$PassThru = $null
|
||||
)
|
||||
|
||||
process
|
||||
{
|
||||
if ($pscmdlet.ShouldProcess($TargetUser, 'Modify/add Group Membership'))
|
||||
{
|
||||
try
|
||||
{
|
||||
$paramGetADUser = @{
|
||||
Identity = $SourceUser
|
||||
Properties = 'memberof'
|
||||
Verbose = $(if ($pscmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent)
|
||||
{
|
||||
$true
|
||||
}
|
||||
else
|
||||
{
|
||||
$false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
$paramAddADGroupMember = @{
|
||||
Members = $TargetUser
|
||||
Verbose = $(if ($pscmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent)
|
||||
{
|
||||
$true
|
||||
}
|
||||
else
|
||||
{
|
||||
# Workaround: If not present it is empty not false
|
||||
$false
|
||||
}
|
||||
)
|
||||
PassThru = $(if ($pscmdlet.MyInvocation.BoundParameters['PassThru'].IsPresent)
|
||||
{
|
||||
$true
|
||||
}
|
||||
else
|
||||
{
|
||||
# Workaround: If not present it is empty not false
|
||||
$false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (($pscmdlet.MyInvocation.BoundParameters['PassThru'].IsPresent))
|
||||
{
|
||||
# Show the output / PassThru in a nice format
|
||||
((Get-ADUser @paramGetADUser) | Select-Object -ExpandProperty memberof | Add-ADGroupMember @paramAddADGroupMember | Select-Object -ExpandProperty SamAccountName)
|
||||
}
|
||||
else
|
||||
{
|
||||
# Do not show any output / Verbose will be shown
|
||||
$null = ((Get-ADUser @paramGetADUser) | Select-Object -ExpandProperty memberof | Add-ADGroupMember @paramAddADGroupMember)
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
#region ErrorHandler
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message ($info.Exception) -ErrorAction Stop
|
||||
|
||||
# Only here to catch a global ErrorAction overwrite
|
||||
break
|
||||
#endregion ErrorHandler
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,169 @@
|
||||
function Find-enADDuplicateServicePrincipalName
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Find all duplicate Service Principal Names (SPNs)
|
||||
|
||||
.DESCRIPTION
|
||||
Find all duplicate Service Principal Names (SPNs) in the Active Directory
|
||||
|
||||
.INPUTS
|
||||
NONE
|
||||
|
||||
.OUTPUTS
|
||||
Boolean
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Find-enADDuplicateServicePrincipalName
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
Dependencies:
|
||||
Active Directory PowerShell Module
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADObject
|
||||
#>
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([bool])]
|
||||
param ()
|
||||
|
||||
begin
|
||||
{
|
||||
# Create a new Object
|
||||
$AllObject = @()
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
try
|
||||
{
|
||||
# We use Get-ADObject because this seems to be fast enough
|
||||
$paramGetADObject = @{
|
||||
Filter = "(objectClass -eq 'user') -or (objectClass -eq 'computer') -and (servicePrincipalName -like '*')"
|
||||
Properties = 'SamAccountName', 'servicePrincipalName'
|
||||
ErrorAction = 'Stop'
|
||||
WarningAction = 'Continue'
|
||||
}
|
||||
$AllServicePrincipalNames = (Get-ADObject @paramGetADObject)
|
||||
|
||||
# Loop over the List we got from Get-ADObject
|
||||
foreach ($SPNObject in $AllServicePrincipalNames)
|
||||
{
|
||||
$SamAccountName = $SPNObject.SamAccountName
|
||||
$ServicePrincipalNames = $SPNObject.ServicePrincipalName
|
||||
|
||||
|
||||
foreach ($ServicePrincipalName in $ServicePrincipalNames)
|
||||
{
|
||||
if ($AllObject.ServicePrincipalName -like $ServicePrincipalName)
|
||||
{
|
||||
$MatchedSPNs = ($AllObject.ServicePrincipalName -like $ServicePrincipalName)
|
||||
|
||||
# Loop over the matching list og SPNs
|
||||
foreach ($MatchSPN in $MatchedSPNs)
|
||||
{
|
||||
$MatchSamAccountName = $MatchSPN.SamAccountName
|
||||
|
||||
# Ding. ding, we have a winner
|
||||
if ($MatchSamAccountName -ne $SamAccountName)
|
||||
{
|
||||
$paramWriteWarning = @{
|
||||
Message = ('Duplicated SPN has been found for {0}!!!' -f $ServicePrincipalName)
|
||||
ErrorAction = 'Continue'
|
||||
WarningAction = 'Continue'
|
||||
}
|
||||
Write-Warning @paramWriteWarning
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# Create a new Object
|
||||
$SingleObject = (New-Object -TypeName PSObject -Property @{
|
||||
SamAccountName = $SamAccountName
|
||||
ServicePrincipalName = $ServicePrincipalName
|
||||
})
|
||||
|
||||
# Add the Values to the List
|
||||
$AllObject += $SingleObject
|
||||
|
||||
# Cleanup
|
||||
$SingleObject = $null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
#region ErrorHandler
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message ($info.Exception) -ErrorAction Stop
|
||||
|
||||
# Only here to catch a global ErrorAction overwrite
|
||||
break
|
||||
#endregion ErrorHandler
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
# Dump all SPNs, if verbose
|
||||
$AllObject | Out-String | Write-Verbose
|
||||
|
||||
# Cleanup
|
||||
$AllObject = $null
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,203 @@
|
||||
function Get-ADUserLockouts
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tracking down account lockout sources with PowerShell
|
||||
|
||||
.DESCRIPTION
|
||||
Tracking down account lockout sources with PowerShell
|
||||
|
||||
.PARAMETER Identity
|
||||
Just scan for a single User?
|
||||
|
||||
.PARAMETER StartTime
|
||||
Start-point
|
||||
|
||||
.PARAMETER EndTime
|
||||
Endpoint
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Get-ADUserLockout
|
||||
|
||||
Tracking down account lockout sources for all users for the last 7 days
|
||||
|
||||
.EXAMPLE
|
||||
Get-ADUser -Filter {Department -eq 'Development'} | Get-ADUserLockout
|
||||
|
||||
Tracking down account lockout sources for all users in the Development Department for the last 7 days
|
||||
|
||||
.EXAMPLE
|
||||
Get-ADUserLockout -StartTime (Get-Date).AddDays(-2) -EndTime (Get-Date).AddDays(-1)
|
||||
|
||||
Tracking down account lockout sources for all users for the last day
|
||||
|
||||
.NOTES
|
||||
Original by Anthony Howell (@ThePoShWolf) - MIT Licenses
|
||||
Copyright (c) 2018 Anthony Howell
|
||||
|
||||
.LINK
|
||||
https://theposhwolf.com/howtos/Get-ADUserLockouts/
|
||||
|
||||
.LINK
|
||||
https://github.com/ThePoShWolf/Utilities/blob/master/ActiveDirectory/Get-ADUserLockouts.ps1
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = 'All',
|
||||
ConfirmImpact = 'None')]
|
||||
[OutputType([pscustomobject])]
|
||||
param
|
||||
(
|
||||
[Parameter(ParameterSetName = 'ByUser',
|
||||
ValueFromPipeline)]
|
||||
[string]
|
||||
$Identity,
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[Alias('Start')]
|
||||
[datetime]
|
||||
$StartTime = (Get-Date).AddDays(-8),
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[Alias('End')]
|
||||
[datetime]
|
||||
$EndTime = (Get-Date).AddDays(-1)
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
$filterHt = @{
|
||||
LogName = 'Security'
|
||||
ID = 4740
|
||||
}
|
||||
|
||||
if ($PSBoundParameters.ContainsKey('StartTime'))
|
||||
{
|
||||
$filterHt['StartTime'] = $StartTime
|
||||
}
|
||||
|
||||
if ($PSBoundParameters.ContainsKey('EndTime'))
|
||||
{
|
||||
$filterHt['EndTime'] = $EndTime
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$PDCEmulator = ((Get-ADDomain -ErrorAction Stop).PDCEmulator)
|
||||
|
||||
Write-Verbose -Message ('Use {0} to find the lockout events' -f $PDCEmulator)
|
||||
|
||||
# Query the event log just once instead of for each user if using the pipeline
|
||||
$events = (Get-WinEvent -ComputerName $PDCEmulator -FilterHashtable $filterHt -ErrorAction Stop)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
# output information. Post-process collected info, and log info (optional)
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message $e.Exception.Message -ErrorAction Stop -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
Write-Verbose -Message 'Found the following events:'
|
||||
Write-Verbose -Message $events
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
if ($PSCmdlet.ParameterSetName -eq 'ByUser')
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Verbose -Message ('Querry AD Info for {0}' -f $Identity)
|
||||
|
||||
$user = (Get-ADUser -Identity $Identity -ErrorAction Stop)
|
||||
|
||||
Write-Verbose -Message ('Found the following AD Info for {0}:' -f $Identity)
|
||||
Write-Verbose -Message $user
|
||||
|
||||
# Filter the events
|
||||
$output = $events | Where-Object -FilterScript {
|
||||
$_.Properties[0].Value -eq $user.SamAccountName
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
# output information. Post-process collected info, and log info (optional)
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message $e.Exception.Message -ErrorAction Stop -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = $events
|
||||
}
|
||||
|
||||
foreach ($event in $output)
|
||||
{
|
||||
[pscustomobject]@{
|
||||
UserName = $event.Properties[0].Value
|
||||
CallerComputer = $event.Properties[1].Value
|
||||
TimeStamp = $event.TimeCreated
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,196 @@
|
||||
function Get-enADDNSServerInformation
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve information about the Active Directory Domain Name Servers
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieve information about the Active Directory Domain Name Servers
|
||||
|
||||
.PARAMETER Domain
|
||||
A description of the Domain parameter.
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADDNSServerInformation
|
||||
|
||||
Retrieve information about the Active Directory Domain Name Servers, use the current domain
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADDNSServerInformation | Export-CSV -Path C:\scripts\PowerShell\Reports\DNS_Zones.csv -NoTypeInformation -Force -Confirm:$false
|
||||
Retrieve information about the Active Directory Domain Name Servers, use the current domain and exports it to CSV
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADDNSServerInformation | ConvertTo-Json -Depth 10 | Set-Content -Path C:\scripts\PowerShell\Reports\DNS_Zones.json -Force -Confirm:$false
|
||||
Retrieve information about the Active Directory Domain Name Servers, use the current domain and exports it to a JSON File
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADDNSServerInformation -Domain 'contoso.com'
|
||||
|
||||
Retrieve information about the Active Directory Domain Name Servers in the Domain contoso.com
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADDNSServerInformation -Domain 'contoso.com', 'corp.contoso.net'
|
||||
|
||||
Retrieve information about the Active Directory Domain Name Servers in the Domain contoso.com and corp.contoso.net
|
||||
|
||||
.OUTPUTS
|
||||
psobject
|
||||
|
||||
.INPUTS
|
||||
String
|
||||
|
||||
.NOTES
|
||||
TODO: Need refactoring: Object handler sucks
|
||||
TODO: Find a non WMI based Solution for this
|
||||
|
||||
Version: 1.0.1
|
||||
|
||||
GUID: 4404141a-1731-4786-8bbf-ee6706765050
|
||||
|
||||
Author: Joerg Hochwald
|
||||
|
||||
Companyname: enabling Technology
|
||||
|
||||
Copyright: Copyright (c) 2ß18-2019, enabling Technology - All rights reserved.
|
||||
|
||||
License: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/aa393295(v=vs.85).aspx
|
||||
|
||||
.LINK
|
||||
Get-ADDomainController
|
||||
|
||||
.LINK
|
||||
Get-WmiObject
|
||||
#>
|
||||
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param
|
||||
(
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[string[]]
|
||||
$Domain = ([DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name.ToString())
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
$DNSReport = @()
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
foreach ($DomainEach in $Domain)
|
||||
{
|
||||
$AllDomainControllers = (Get-ADDomainController -Filter {
|
||||
Site -like '*' -and Domain -eq $DomainEach
|
||||
} | Select-Object -ExpandProperty Name)
|
||||
|
||||
foreach ($SingleDomainController in $AllDomainControllers)
|
||||
{
|
||||
# Prevent Null Pointer Exceptions
|
||||
if ($SingleDomainController)
|
||||
{
|
||||
# TODO: Find a non WMI based Solution for this
|
||||
$Forwarders = (Get-WmiObject -ComputerName $SingleDomainController -Namespace root\MicrosoftDNS -Class MicrosoftDNS_Server -ErrorAction SilentlyContinue)
|
||||
|
||||
# TODO: Find a non WMI based Solution for this
|
||||
$NetworkInterface = (Get-WmiObject -ComputerName $SingleDomainController -Query 'Select * From Win32_NetworkAdapterConfiguration Where IPEnabled=TRUE' -ErrorAction SilentlyContinue)
|
||||
|
||||
$DNSReport += 1 | Select-Object -Property @{
|
||||
name = 'DC'
|
||||
expression = {
|
||||
$SingleDomainController
|
||||
}
|
||||
}, @{
|
||||
name = 'Domain'
|
||||
expression = {
|
||||
$DomainEach
|
||||
}
|
||||
}, @{
|
||||
name = 'DNSHostName'
|
||||
expression = {
|
||||
$NetworkInterface.DNSHostName
|
||||
}
|
||||
}, @{
|
||||
name = 'IPAddress'
|
||||
expression = {
|
||||
$NetworkInterface.IPAddress
|
||||
}
|
||||
}, @{
|
||||
name = 'DNSServerAddresses'
|
||||
expression = {
|
||||
$Forwarders.ServerAddresses
|
||||
}
|
||||
}, @{
|
||||
name = 'DNSServerSearchOrder'
|
||||
expression = {
|
||||
$NetworkInterface.DNSServerSearchOrder
|
||||
}
|
||||
}, @{
|
||||
name = 'Forwarders'
|
||||
expression = {
|
||||
$Forwarders.Forwarders
|
||||
}
|
||||
}, @{
|
||||
name = 'BootMethod'
|
||||
expression = {
|
||||
$Forwarders.BootMethod
|
||||
}
|
||||
}, @{
|
||||
name = 'ScavengingInterval'
|
||||
expression = {
|
||||
$Forwarders.ScavengingInterval
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
$DNSReport
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,100 @@
|
||||
Function Get-enDomainControllerInfo
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get a list of domain controllers
|
||||
|
||||
.DESCRIPTION
|
||||
Will provide a list of domain controllers in your current domain.
|
||||
Optionally you can also request a discovery of the "closest" one.
|
||||
|
||||
.PARAMETER ComputerName
|
||||
Retrieve information about the specified domain controller.
|
||||
This is a RegEx match so you can match multiple domain controllers with your pattern.
|
||||
|
||||
.PARAMETER Discover
|
||||
Use Discover to return the information of the closest domain controller.
|
||||
|
||||
.EXAMPLE
|
||||
Get-enDomainControllerInfo
|
||||
|
||||
Retrieve a list of all domain controllers in your domain.
|
||||
|
||||
.EXAMPLE
|
||||
Get-enDomainControllerInfo -Computer 01
|
||||
|
||||
Retrieve a list of all domain controllers with "01" in their name.
|
||||
|
||||
.EXAMPLE
|
||||
Get-enDomainControllerInfo -Discover
|
||||
|
||||
Retrieve the name of the closest domain controller.
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = 'all')]
|
||||
Param (
|
||||
[Parameter(Position = 0, ParameterSetName = 'dc')]
|
||||
[string]$ComputerName,
|
||||
[Parameter(ParameterSetName = 'all')]
|
||||
[switch]$Discover
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
$DirectoryContext = [DirectoryServices.ActiveDirectory.DirectoryContext]::New('Domain')
|
||||
$SelectProperties = 'Name', 'Forest', 'Domain', 'SiteName', 'Roles', 'CurrentTime', 'HighestCommittedUsn', 'OSVersion'
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
If ($Discover)
|
||||
{
|
||||
$LocatorFlag = [DirectoryServices.ActiveDirectory.LocatorOptions]::ForceRediscovery
|
||||
$Info = ([DirectoryServices.ActiveDirectory.DomainController]::FindOne($DirectoryContext, $LocatorFlag) | Select-Object -Property $SelectProperties)
|
||||
}
|
||||
elseif ($ComputerName)
|
||||
{
|
||||
$Info = ([DirectoryServices.ActiveDirectory.DomainController]::FindAll($DirectoryContext) | Where-Object -Property Name -Match -Value $ComputerName | Select-Object -Property $SelectProperties)
|
||||
}
|
||||
else
|
||||
{
|
||||
$Info = ([DirectoryServices.ActiveDirectory.DomainController]::FindAll($DirectoryContext) | Select-Object -Property $SelectProperties)
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
$Info
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,148 @@
|
||||
#requires -Version 3.0 -Modules ActiveDirectory
|
||||
|
||||
function Get-enADFSMORole
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve the FSMO Role in the Forest/Domain
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieve the FSMO Role in the Forest/Domain of Active Directory
|
||||
|
||||
.PARAMETER Credential
|
||||
Specify the alternative credential to use
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADFSMORole
|
||||
|
||||
Retrieve the FSMO Role in the Forest/Domain of Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADFSMORole -Credential (Get-Credential)
|
||||
|
||||
Retrieve the FSMO Role in the Forest/Domain of Active Directory
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
Dependencies:
|
||||
Active Directory PowerShell Module
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADForest
|
||||
|
||||
.LINK
|
||||
Get-ADDomain
|
||||
#>
|
||||
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param
|
||||
(
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[System.Management.Automation.Credential()]
|
||||
[Alias('RunAs')]
|
||||
[pscredential]
|
||||
$Credential = [pscredential]::Empty
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
$Properties = $null
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($PSBoundParameters['Credential'])
|
||||
{
|
||||
# Query with the credentials specified
|
||||
$ForestRoles = (Get-ADForest -Credential $Credential -ErrorAction 'Stop' -ErrorVariable ErrorGetADForest)
|
||||
$DomainRoles = (Get-ADDomain -Credential $Credential -ErrorAction 'Stop' -ErrorVariable ErrorGetADDomain)
|
||||
}
|
||||
else
|
||||
{
|
||||
# Query with the current credentials
|
||||
$ForestRoles = (Get-ADForest)
|
||||
$DomainRoles = (Get-ADDomain)
|
||||
}
|
||||
|
||||
# Define Properties
|
||||
$Properties = @{
|
||||
SchemaMaster = $ForestRoles.SchemaMaster
|
||||
DomainNamingMaster = $ForestRoles.DomainNamingMaster
|
||||
InfraStructureMaster = $DomainRoles.InfraStructureMaster
|
||||
RIDMaster = $DomainRoles.RIDMaster
|
||||
PDCEmulator = $DomainRoles.PDCEmulator
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
#region ErrorHandler
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message ($info.Exception) -ErrorAction Stop
|
||||
|
||||
# Only here to catch a global ErrorAction overwrite
|
||||
break
|
||||
#endregion ErrorHandler
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
$Properties
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,189 @@
|
||||
function Get-enADForestInformation
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve information about an Active Directory Forest
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieve information about an Active Directory Forest
|
||||
|
||||
.PARAMETER ForestName
|
||||
Forest name to retrieve information about
|
||||
|
||||
.PARAMETER Credential
|
||||
Credential to use for retrieval
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation
|
||||
|
||||
Retrieve information about the current Active Directory Forest
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation | Select-Object ApplicationPartitions
|
||||
|
||||
Retrieve information about Application Partitions from the current Active Directory Forest
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation | Select-Object GlobalCatalogs
|
||||
|
||||
Retrieve als Global Catalog Servers from the current Active Directory Forest
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> (Get-enADForestInformation) | Select-Object -ExpandProperty GlobalCatalogs
|
||||
|
||||
Retrieve als Global Catalog Servers from the current Active Directory Forest. More details then the above example, cause it will show all the details for each Global Catalog Servers.
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation | Select-Object NamingRoleOwner
|
||||
|
||||
Retrieve information about the Naming master Roles holder from the current Active Directory Forest
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> (Get-enADForestInformation).Sites
|
||||
|
||||
Retrieve information about Active Directory Sites from the current Active Directory Forest
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation -Credential (Get-Credential)
|
||||
|
||||
Retrieve information about the current Active Directory Forest, with special credentials (e.g. RunAs)
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation -ForestName Value
|
||||
|
||||
Retrieve information about Active Directory Forest specified in Value
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADForestInformation -ForestName Value -Credential Value
|
||||
|
||||
Retrieve information about Active Directory Forest specified in Value, with special credentials (e.g. RunAs)
|
||||
|
||||
.OUTPUTS
|
||||
psobject
|
||||
|
||||
.INPUTS
|
||||
String
|
||||
pscredential
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADForest
|
||||
#>
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param
|
||||
(
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[Alias('Forest')]
|
||||
[string]
|
||||
$ForestName = ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Name.ToString()),
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[System.Management.Automation.Credential()]
|
||||
[pscredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
# Cleanup
|
||||
$output = $null
|
||||
$ActiveDirectoryContext = $null
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($Credential)
|
||||
{
|
||||
$credentialUser = ($Credential.UserName.ToString())
|
||||
$credentialPassword = ($Credential.GetNetworkCredential().Password.ToString())
|
||||
$ActiveDirectoryContext = (New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList ('forest', $ForestName, $credentialUser, $credentialPassword))
|
||||
|
||||
# Cleanup
|
||||
$credentialUser = $null
|
||||
$credentialPassword = $null
|
||||
}
|
||||
else
|
||||
{
|
||||
$ActiveDirectoryContext = (New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList ('forest', $ForestName))
|
||||
}
|
||||
|
||||
$output = ([DirectoryServices.ActiveDirectory.Forest]::GetForest($ActiveDirectoryContext))
|
||||
}
|
||||
catch
|
||||
{
|
||||
#region ErrorHandler
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message ($info.Exception) -ErrorAction Stop
|
||||
|
||||
# Only here to catch a global ErrorAction overwrite
|
||||
break
|
||||
#endregion ErrorHandler
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
$output
|
||||
|
||||
# Cleanup
|
||||
$output = $null
|
||||
$ActiveDirectoryContext = $null
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,158 @@
|
||||
function Get-enADGPOReplication
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve one or all the GPO and report their DSVersions and SysVolVersions
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieve one or all the GPO and report their DSVersions and SysVolVersions (Users and Computers)
|
||||
|
||||
.PARAMETER GPOName
|
||||
Specify the name of the GPO
|
||||
|
||||
.PARAMETER All
|
||||
Specify that you want to retrieve all the GPO (slow if you have a lot of Domain Controllers)
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGPOReplication -GPOName "Default Domain Policy"
|
||||
|
||||
Retrieve one GPO and report their DSVersions and SysVolVersions (Users and Computers)
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGPOReplication -All
|
||||
|
||||
Retrieve all the GPO and report their DSVersions and SysVolVersions (Users and Computers)
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
Dependencies:
|
||||
Active Directory PowerShell Module
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADDomainController
|
||||
|
||||
.LINK
|
||||
Get-GPO
|
||||
#>
|
||||
|
||||
[CmdletBinding(DefaultParameterSetName = 'All',
|
||||
ConfirmImpact = 'None')]
|
||||
param
|
||||
(
|
||||
[Parameter(ParameterSetName = 'One', HelpMessage = 'Specify the name of the GPO',
|
||||
Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('GPO')]
|
||||
[String[]]
|
||||
$GPOName,
|
||||
[Parameter(ParameterSetName = 'All',
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[Switch]
|
||||
$All
|
||||
)
|
||||
|
||||
process
|
||||
{
|
||||
foreach ($DomainController in ((Get-ADDomainController -ErrorAction Stop -ErrorVariable ErrorProcessGetDC -Filter *).hostname))
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($psBoundParameters['GPOName'])
|
||||
{
|
||||
foreach ($GPOItem in $GPOName)
|
||||
{
|
||||
$GPO = (Get-GPO -Name $GPOItem -Server $DomainController -ErrorAction Stop -ErrorVariable ErrorProcessGetGPO)
|
||||
|
||||
[pscustomobject][ordered] @{
|
||||
GroupPolicyName = $GPOItem
|
||||
DomainController = $DomainController
|
||||
UserVersion = $GPO.User.DSVersion
|
||||
UserSysVolVersion = $GPO.User.SysvolVersion
|
||||
ComputerVersion = $GPO.Computer.DSVersion
|
||||
ComputerSysVolVersion = $GPO.Computer.SysvolVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($psBoundParameters['All'])
|
||||
{
|
||||
$GPOList = (Get-GPO -All -Server $DomainController -ErrorAction Stop -ErrorVariable ErrorProcessGetGPOAll)
|
||||
|
||||
foreach ($GPO in $GPOList)
|
||||
{
|
||||
[pscustomobject][ordered] @{
|
||||
GroupPolicyName = $GPO.DisplayName
|
||||
DomainController = $DomainController
|
||||
UserVersion = $GPO.User.DSVersion
|
||||
UserSysVolVersion = $GPO.User.SysvolVersion
|
||||
ComputerVersion = $GPO.Computer.DSVersion
|
||||
ComputerSysVolVersion = $GPO.Computer.SysvolVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Warning -Message '[PROCESS] Something wrong happened'
|
||||
|
||||
if ($ErrorProcessGetDC)
|
||||
{
|
||||
Write-Warning -Message '[PROCESS] Error while running retrieving Domain Controllers with Get-ADDomainController'
|
||||
}
|
||||
|
||||
if ($ErrorProcessGetGPO)
|
||||
{
|
||||
Write-Warning -Message '[PROCESS] Error while running Get-GPO'
|
||||
}
|
||||
|
||||
if ($ErrorProcessGetGPOAll)
|
||||
{
|
||||
Write-Warning -Message '[PROCESS] Error while running Get-GPO -All'
|
||||
}
|
||||
|
||||
Write-Warning -Message "[PROCESS] $($Error[0].exception.message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,210 @@
|
||||
function Get-enADGroupChange
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve information about changed Active Directory groups
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieve information about one, or more, changed Active Directory groups
|
||||
|
||||
.PARAMETER Server
|
||||
Active DirectoryDomain Controller to querry.
|
||||
Default is the logon server
|
||||
|
||||
.PARAMETER MonitorGroup
|
||||
Group to monitor, multi value is supported.
|
||||
Defaults to all Groups with admins.
|
||||
|
||||
Specifies an Active Directory object by providing one of the following property values. The identifier in
|
||||
parentheses is the LDAP display name for the attribute.
|
||||
|
||||
Distinguished Name
|
||||
|
||||
Example: CN=DOM-ADM,OU=groups,OU=asia,DC=corp,DC=contoso,DC=com
|
||||
|
||||
GUID (objectGUID)
|
||||
|
||||
Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
|
||||
|
||||
The cmdlet searches the default naming context or partition to find the object. If two or more objects are
|
||||
found, the cmdlet returns a non-terminating error.
|
||||
|
||||
.PARAMETER Hour
|
||||
Period to query, value in hours
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGroupChange
|
||||
|
||||
Retrieve information about changed Active Directory groups
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGroupChange -MonitorGroup 'DOM-ADM'
|
||||
|
||||
Retrieve information about changes to theActive Directory group DOM-ADM
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGroupChange -Server DC03
|
||||
|
||||
Retrieve information about changed Active Directory groups on DC03
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGroupChange -Hour 72
|
||||
|
||||
Retrieve information about Active Directory groups that have been changed within the last 72 hours
|
||||
|
||||
.EXAMPLE
|
||||
Get-enADGroupChange -Server DC02 -Hour 96
|
||||
|
||||
Retrieve information about Active Directory groups that have been changed within the last 96 hours on DC02
|
||||
|
||||
.OUTPUTS
|
||||
psobject
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
.INPUTS
|
||||
String
|
||||
Int
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADDomainController
|
||||
|
||||
.LINK
|
||||
Get-ADGroup
|
||||
|
||||
.LINK
|
||||
Get-ADReplicationAttributeMetadata
|
||||
|
||||
.LINK
|
||||
Get-Date
|
||||
#>
|
||||
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param
|
||||
(
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('DomainController')]
|
||||
[string]
|
||||
$Server = (Get-ADDomainController -Discover | Select-Object -ExpandProperty HostName),
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Group')]
|
||||
[string[]]
|
||||
$MonitorGroup = (Get-ADGroup -Filter ' AdminCount -eq 1 ' -Server $Server | Select-Object -ExpandProperty ObjectGUID),
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName)]
|
||||
[Alias('Period')]
|
||||
[int]
|
||||
$Hour = 24
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
# Create a new object
|
||||
$Members = @()
|
||||
|
||||
Write-Verbose -Message ('Processing group {0} via Server {1}' -f $MonitorGroup, $Server)
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ($SingleGroup in $MonitorGroup)
|
||||
{
|
||||
Write-Verbose -Message ('Processing group {0}' -f $SingleGroup)
|
||||
|
||||
# Querry the info and add to the Object
|
||||
$Members += (Get-ADReplicationAttributeMetadata -Server $Server -Object $SingleGroup -ShowAllLinkedValues | Where-Object -FilterScript {
|
||||
$_.IsLinkValue
|
||||
} | Select-Object -Property @{
|
||||
name = 'GroupDN'
|
||||
expression = {
|
||||
$SingleGroup.DistinguishedName
|
||||
}
|
||||
}, @{
|
||||
name = 'GroupName'
|
||||
expression = {
|
||||
$SingleGroup.Name
|
||||
}
|
||||
}, *)
|
||||
}
|
||||
|
||||
# Filter
|
||||
$Members | Where-Object -FilterScript {
|
||||
$_.LastOriginatingChangeTime -gt (Get-Date).AddHours(-1 * $Hour)
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
#region ErrorHandler
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message ($info.Exception) -ErrorAction Stop
|
||||
|
||||
# Only here to catch a global ErrorAction overwrite
|
||||
break
|
||||
#endregion ErrorHandler
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
$Members = $null
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,378 @@
|
||||
function Get-enADObject
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Export Active Directory Objects
|
||||
|
||||
.DESCRIPTION
|
||||
Export Active Directory Objects
|
||||
|
||||
.PARAMETER ADObjectFilter
|
||||
Provide specific AD Objects to report on. Otherwise, all AD Objects will be reported. Please review the examples provided.
|
||||
|
||||
.PARAMETER DetailedReport
|
||||
Provides a full report of all attributes. Otherwise, only a refined report will be given.
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADObject | Export-Csv C:\scripts\PowerShell\Reports\ADObjects.csv -notypeinformation -encoding UTF8
|
||||
|
||||
Export Active Directory Objects
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> {objectclass -eq "publicFolder"} | Get-enADObject -DetailedReport | Export-Csv C:\scripts\PowerShell\Reports\PFs.csv -NoTypeInformation -Encoding UTF8
|
||||
|
||||
Export Active Directory Objects
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> '{proxyaddresses -like "*contoso.com"}' | Get-enADObject | Export-Csv C:\scripts\PowerShell\Reports\ADObjects.csv -notypeinformation -encoding UTF8
|
||||
|
||||
Export Active Directory Objects
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> '{proxyaddresses -like "*contoso.com"}' | Get-enADObject -DetailedReport | Export-Csv C:\scripts\PowerShell\Reports\ADObjects_Detailed.csv -notypeinformation -encoding UTF8
|
||||
|
||||
Export Active Directory Objects
|
||||
|
||||
.OUTPUTS
|
||||
PSObject
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
Dependencies:
|
||||
Active Directory PowerShell Module
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADObject
|
||||
#>
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param (
|
||||
[switch]
|
||||
$DetailedReport,
|
||||
[Parameter(ValueFromPipeline)]
|
||||
[string[]]
|
||||
$ADObjectFilter
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
if ($DetailedReport)
|
||||
{
|
||||
$Selectproperties = @(
|
||||
'DisplayName', 'UserPrincipalName', 'mail', 'CN', 'mailNickname', 'Name', 'GivenName', 'Surname', 'StreetAddress'
|
||||
'City', 'State', 'Country', 'PostalCode', 'Company', 'Title', 'Department', 'Description', 'OfficePhone'
|
||||
'MobilePhone', 'HomePhone', 'Fax', 'SamAccountName', 'DistinguishedName', 'Office', 'Enabled'
|
||||
'whenChanged', 'whenCreated', 'adminCount', 'AccountNotDelegated', 'AllowReversiblePasswordEncryption'
|
||||
'CannotChangePassword', 'Deleted', 'DoesNotRequirePreAuth', 'HomedirRequired', 'isDeleted', 'LockedOut'
|
||||
'mAPIRecipient', 'mDBUseDefaults', 'MNSLogonAccount', 'msExchHideFromAddressLists'
|
||||
'msNPAllowDialin', 'PasswordExpired', 'PasswordNeverExpires', 'PasswordNotRequired', 'ProtectedFromAccidentalDeletion'
|
||||
'SmartcardLogonRequired', 'TrustedForDelegation', 'TrustedToAuthForDelegation', 'UseDESKeyOnly', 'logonHours'
|
||||
'msExchMailboxGuid', 'replicationSignature', 'AccountExpirationDate', 'AccountLockoutTime', 'Created', 'createTimeStamp'
|
||||
'LastBadPasswordAttempt', 'LastLogonDate', 'Modified', 'modifyTimeStamp', 'msTSExpireDate', 'PasswordLastSet'
|
||||
'msExchMailboxSecurityDescriptor', 'nTSecurityDescriptor', 'BadLogonCount', 'codePage', 'countryCode'
|
||||
'deletedItemFlags', 'dLMemDefault', 'garbageCollPeriod', 'instanceType', 'msDS-SupportedEncryptionTypes'
|
||||
'msDS-User-Account-Control-Computed', 'msExchALObjectVersion', 'msExchMobileMailboxFlags', 'msExchRecipientDisplayType'
|
||||
'msExchUserAccountControl', 'primaryGroupID', 'replicatedObjectVersion', 'sAMAccountType', 'sDRightsEffective'
|
||||
'userAccountControl', 'accountExpires', 'lastLogonTimestamp', 'lockoutTime', 'msExchRecipientTypeDetails', 'msExchVersion'
|
||||
'pwdLastSet', 'uSNChanged', 'uSNCreated', 'ObjectGUID', 'objectSid', 'SID', 'autoReplyMessage', 'CanonicalName'
|
||||
'displayNamePrintable', 'Division', 'EmployeeID', 'EmployeeNumber', 'HomeDirectory', 'HomeDrive', 'homeMDB', 'homeMTA'
|
||||
'HomePage', 'Initials', 'LastKnownParent', 'legacyExchangeDN', 'LogonWorkstations'
|
||||
'Manager', 'msExchHomeServerName', 'msExchUserCulture', 'msTSLicenseVersion', 'msTSManagingLS'
|
||||
'ObjectCategory', 'ObjectClass', 'Organization', 'OtherName', 'POBox', 'PrimaryGroup'
|
||||
'ProfilePath', 'ScriptPath', 'sn', 'textEncodedORAddress', 'userParameters'
|
||||
)
|
||||
|
||||
$CalculatedProps = @(
|
||||
@{
|
||||
n = 'OU'
|
||||
e = {
|
||||
$_.DistinguishedName -replace '^.+?,(?=(OU|CN)=)'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'proxyAddresses'
|
||||
e = {
|
||||
($_.proxyAddresses | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join '|'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'altRecipientBL'
|
||||
e = {
|
||||
($_.altRecipientBL | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'AuthenticationPolicy'
|
||||
e = {
|
||||
($_.AuthenticationPolicy | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'AuthenticationPolicySilo'
|
||||
e = {
|
||||
($_.AuthenticationPolicySilo | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'Certificates'
|
||||
e = {
|
||||
($_.Certificates | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'CompoundIdentitySupported'
|
||||
e = {
|
||||
($_.CompoundIdentitySupported | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'dSCorePropagationData'
|
||||
e = {
|
||||
($_.dSCorePropagationData | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'KerberosEncryptionType'
|
||||
e = {
|
||||
($_.KerberosEncryptionType | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'managedObjects'
|
||||
e = {
|
||||
($_.managedObjects | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'MemberOf'
|
||||
e = {
|
||||
($_.MemberOf | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'msExchADCGlobalNames'
|
||||
e = {
|
||||
($_.msExchADCGlobalNames | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'msExchPoliciesExcluded'
|
||||
e = {
|
||||
($_.msExchPoliciesExcluded | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'PrincipalsAllowedToDelegateToAccount'
|
||||
e = {
|
||||
($_.PrincipalsAllowedToDelegateToAccount | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'protocolSettings'
|
||||
e = {
|
||||
($_.protocolSettings | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'publicDelegatesBL'
|
||||
e = {
|
||||
($_.publicDelegatesBL | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'securityProtocol'
|
||||
e = {
|
||||
($_.securityProtocol | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'ServicePrincipalNames'
|
||||
e = {
|
||||
($_.ServicePrincipalNames | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'showInAddressBook'
|
||||
e = {
|
||||
($_.showInAddressBook | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'SIDHistory'
|
||||
e = {
|
||||
($_.SIDHistory | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'userCertificate'
|
||||
e = {
|
||||
($_.userCertificate | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
$ExtensionAttribute = @(
|
||||
'extensionAttribute1', 'extensionAttribute2', 'extensionAttribute3', 'extensionAttribute4', 'extensionAttribute5'
|
||||
'extensionAttribute6', 'extensionAttribute7', 'extensionAttribute8', 'extensionAttribute9', 'extensionAttribute10'
|
||||
'extensionAttribute11', 'extensionAttribute12', 'extensionAttribute13', 'extensionAttribute14', 'extensionAttribute15'
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
$Props = @(
|
||||
'DisplayName', 'UserPrincipalName', 'mail', 'CN', 'mailNickname', 'Name', 'GivenName', 'Surname', 'StreetAddress',
|
||||
'City', 'State', 'Country', 'PostalCode', 'Company', 'Title', 'Department', 'Description', 'OfficePhone'
|
||||
'MobilePhone', 'HomePhone', 'Fax', 'SamAccountName', 'DistinguishedName', 'Office', 'Enabled'
|
||||
'whenChanged', 'whenCreated', 'adminCount', 'Memberof', 'msExchPoliciesExcluded', 'proxyAddresses'
|
||||
)
|
||||
|
||||
$Selectproperties = @(
|
||||
'DisplayName', 'UserPrincipalName', 'mail', 'CN', 'mailNickname', 'Name', 'GivenName', 'Surname', 'StreetAddress',
|
||||
'City', 'State', 'Country', 'PostalCode', 'Company', 'Title', 'Department', 'Description', 'OfficePhone'
|
||||
'MobilePhone', 'HomePhone', 'Fax', 'SamAccountName', 'DistinguishedName', 'Office', 'Enabled'
|
||||
'whenChanged', 'whenCreated', 'adminCount'
|
||||
)
|
||||
|
||||
|
||||
$CalculatedProps = @(
|
||||
@{
|
||||
n = 'proxyAddresses'
|
||||
e = {
|
||||
($_.proxyAddresses | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join '|'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'OU'
|
||||
e = {
|
||||
$_.DistinguishedName -replace '^.+?,(?=(OU|CN)=)'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'MemberOf'
|
||||
e = {
|
||||
($_.MemberOf | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
},
|
||||
@{
|
||||
n = 'msExchPoliciesExcluded'
|
||||
e = {
|
||||
($_.msExchPoliciesExcluded | Where-Object -FilterScript {
|
||||
$_ -ne $null
|
||||
}) -join ';'
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
if ($ADObjectFilter)
|
||||
{
|
||||
foreach ($CurADObjectFilter in $ADObjectFilter)
|
||||
{
|
||||
if (! $DetailedReport)
|
||||
{
|
||||
Get-ADObject -Filter $CurADObjectFilter -Properties $Props -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps)
|
||||
}
|
||||
else
|
||||
{
|
||||
Get-ADObject -Filter $CurADObjectFilter -Properties * -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps + $ExtensionAttribute)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! $DetailedReport)
|
||||
{
|
||||
Get-ADObject -Filter * -Properties $Props -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps)
|
||||
}
|
||||
else
|
||||
{
|
||||
Get-ADObject -Filter * -Properties * -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps + $ExtensionAttribute)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,178 @@
|
||||
function Get-enADServicePrincipalName
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves all Service Principal Names (SPNs)
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieves all Service Principal Names (SPNs) from Active Directory
|
||||
|
||||
.INPUTS
|
||||
NONE
|
||||
|
||||
.OUTPUTS
|
||||
PSObject
|
||||
|
||||
.EXAMPLE
|
||||
PS /> Get-enADServicePrincipalName
|
||||
|
||||
Retrieves all Service Principal Names (SPNs) from Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.ObjectClass -eq 'user' }
|
||||
|
||||
Retrieves all user class Service Principal Names (SPNs) from Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.DNSHostName -like 'server01.contoso.com' }
|
||||
|
||||
Retrieves all Service Principal Names (SPNs) for the Server 'server01.contoso.com' from Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.Name -like '*Krb*' }
|
||||
|
||||
Retrieves all Kerberos related Service Principal Names (SPNs) from Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.SPN -like '*Krb*' }
|
||||
|
||||
Retrieves all Kerberos related Service Principal Names (SPNs) from Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADServicePrincipalName | Export-Csv -Path C:\scripts\PowerShell\Reports\ADServicePrincipalNames.csv
|
||||
|
||||
Retrieves all Service Principal Names (SPNs) from Active Directory and export them to a CSV
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
Dependencies:
|
||||
Active Directory PowerShell Module
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
|
||||
.LINK
|
||||
Get-ADObject
|
||||
#>
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param ()
|
||||
|
||||
begin
|
||||
{
|
||||
# Create a new Object
|
||||
$AllObject = @()
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
try
|
||||
{
|
||||
# We use Get-ADObject because this seems to be fast enough
|
||||
$paramGetADObject = @{
|
||||
Filter = "(objectClass -eq 'user') -or (objectClass -eq 'computer') -and (servicePrincipalName -like '*')"
|
||||
Properties = 'Name', 'servicePrincipalName', 'DistinguishedName', 'ObjectClass', 'DNSHostName', 'whenCreated'
|
||||
}
|
||||
$AllServicePrincipalNames = (Get-ADObject @paramGetADObject)
|
||||
|
||||
# Loop over the List we got from Get-ADObject
|
||||
foreach ($SingleServicePrincipalName in $AllServicePrincipalNames)
|
||||
{
|
||||
# Get the values for the Service Principal Name
|
||||
$ObjectClass = $SingleServicePrincipalName.ObjectClass
|
||||
$DistinguishedName = $SingleServicePrincipalName.DistinguishedName
|
||||
$Name = $SingleServicePrincipalName.Name
|
||||
$whenCreated = $SingleServicePrincipalName.whenCreated
|
||||
$DNSHostName = $SingleServicePrincipalName.DNSHostName
|
||||
|
||||
# Loop over all Service Principal Names - Remeber, there could be more then one Service Principal Names value per record
|
||||
foreach ($ServicePrincipalName in $SingleServicePrincipalName.servicePrincipalName)
|
||||
{
|
||||
# Create a new Object
|
||||
$SingleObject = (New-Object -TypeName PSObject -Property @{
|
||||
Name = $Name
|
||||
SPN = $ServicePrincipalName
|
||||
ObjectClass = $ObjectClass
|
||||
DistinguishedName = $DistinguishedName
|
||||
WhenCreated = $whenCreated
|
||||
DNSHostName = $DNSHostName
|
||||
})
|
||||
|
||||
# Add the Values to the List
|
||||
$AllObject += $SingleObject
|
||||
|
||||
# Cleanup
|
||||
$SingleObject = $null
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
#region ErrorHandler
|
||||
# get error record
|
||||
[Management.Automation.ErrorRecord]$e = $_
|
||||
|
||||
# retrieve information about runtime error
|
||||
$info = [PSCustomObject]@{
|
||||
Exception = $e.Exception.Message
|
||||
Reason = $e.CategoryInfo.Reason
|
||||
Target = $e.CategoryInfo.TargetName
|
||||
Script = $e.InvocationInfo.ScriptName
|
||||
Line = $e.InvocationInfo.ScriptLineNumber
|
||||
Column = $e.InvocationInfo.OffsetInLine
|
||||
}
|
||||
|
||||
$info | Out-String | Write-Verbose
|
||||
|
||||
Write-Error -Message ($info.Exception) -ErrorAction Stop
|
||||
|
||||
# Only here to catch a global ErrorAction overwrite
|
||||
break
|
||||
#endregion ErrorHandler
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
# Dump
|
||||
$AllObject
|
||||
|
||||
# Cleanup
|
||||
$AllObject = $null
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,132 @@
|
||||
function Get-enADSiteAndSubnetInfo
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve Site names, subnets names and descriptions.
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieve Site names, subnets names and descriptions from the Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADSiteAndSubnetInfo
|
||||
|
||||
Retrieve Site names, subnets names and descriptions from the Active Directory
|
||||
|
||||
.EXAMPLE
|
||||
PS ~> Get-enADSiteAndSubnetInfo | Export-Csv -Path C:\scripts\PowerShell\Reports\ADSiteInventory.csv
|
||||
|
||||
Retrieve Site names, subnets names and descriptions from the Active Directory
|
||||
|
||||
.OUTPUTS
|
||||
PSObject
|
||||
|
||||
.NOTES
|
||||
Releasenotes:
|
||||
1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause
|
||||
1.0.0 2019-01-01 Initial Version
|
||||
|
||||
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
|
||||
|
||||
Dependencies:
|
||||
Active Directory PowerShell Module
|
||||
|
||||
.LINK
|
||||
https://www.enatec.io
|
||||
#>
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([psobject])]
|
||||
param ()
|
||||
|
||||
begin
|
||||
{
|
||||
Write-Verbose -Message '[BEGIN] Starting Script...'
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
try
|
||||
{
|
||||
# Domain and Sites Information
|
||||
$Forest = ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest())
|
||||
$SiteInfo = ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites)
|
||||
|
||||
# Forest Context
|
||||
$ForestType = ([DirectoryServices.ActiveDirectory.DirectoryContexttype]'forest')
|
||||
$ForestContext = (New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList $ForestType, $Forest)
|
||||
|
||||
# Distinguished Name of the Configuration Partition
|
||||
$Configuration = ([ADSI]'LDAP://RootDSE').configurationNamingContext
|
||||
|
||||
# Get the Subnet Container
|
||||
$SubnetsContainer = ([ADSI]('LDAP://CN=Subnets,CN=Sites,{0}' -f $Configuration))
|
||||
$SubnetsContainerchildren = ($SubnetsContainer.Children)
|
||||
|
||||
foreach ($item in $SiteInfo)
|
||||
{
|
||||
Write-Verbose -Message ('[PROCESS] SITE: {0}' -f $item.name)
|
||||
|
||||
$output = @{
|
||||
Name = $item.name
|
||||
}
|
||||
|
||||
foreach ($i in $item.Subnets.name)
|
||||
{
|
||||
Write-Verbose -Message ('[PROCESS] SUBNET: {0}' -f $i)
|
||||
|
||||
$output.Subnet = $i
|
||||
$SubnetAdditionalInfo = $SubnetsContainerchildren.Where( {
|
||||
$_.name -match $i
|
||||
})
|
||||
|
||||
Write-Verbose -Message ('[PROCESS] SUBNET: {0} - DESCRIPTION: {1}' -f $i, $SubnetAdditionalInfo.Description)
|
||||
|
||||
$output.Description = $($SubnetAdditionalInfo.Description)
|
||||
|
||||
Write-Verbose -Message '[PROCESS] OUTPUT INFO'
|
||||
|
||||
New-Object -TypeName PSObject -Property $output
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Warning -Message '[PROCESS] Something Wrong Happened'
|
||||
Write-Warning -Message $Error[0]
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
Write-Verbose -Message '[END] Script Completed!'
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,76 @@
|
||||
Function Get-enDomainInfo
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve domain information include site details
|
||||
|
||||
.EXAMPLE
|
||||
Get-enDomainInfo
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param ()
|
||||
|
||||
begin
|
||||
{
|
||||
$SelectProperties = 'Name', 'Forest', 'Parent', 'Children', 'DomainMode', 'DomainModeLevel', 'DomainControllers', 'PdcRoleOwner', 'RidRoleOwner', 'InfrastructureRoleOwner', 'Sites'
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
$CurrentDomain = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
|
||||
$null = ($CurrentDomain | Add-Member -MemberType NoteProperty -Name Sites -Value ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites))
|
||||
$Domain = ($CurrentDomain | Select-Object -Property $SelectProperties)
|
||||
|
||||
<#
|
||||
switch($domainModeLevel)
|
||||
{
|
||||
{$domainModeLevel -like "0"} {"2000 Mixed/Native"}
|
||||
{$domainModeLevel -like "1"} {"2003 Interim"}
|
||||
{$domainModeLevel -like "2"} {"2003"}
|
||||
{$domainModeLevel -like "3"} {"2008"}
|
||||
{$domainModeLevel -like "4"} {"2008 R2"}
|
||||
{$domainModeLevel -like "5"} {"2012"}
|
||||
{$domainModeLevel -like "6"} {"2012 R2"}
|
||||
{$domainModeLevel -like "7"} {"2016"}
|
||||
default {"Unknown"}
|
||||
}
|
||||
#>
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
$Domain
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
29
Powershell/PowerShell-collection/ActiveDirectory/LICENSE
Normal file
29
Powershell/PowerShell-collection/ActiveDirectory/LICENSE
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology <http://enatec.io>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Legacy Notice
|
||||
|
||||
I no longer run Exchange, Skype for Business, or any other Office Server on Premises.
|
||||
This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program.
|
||||
In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits.
|
||||
|
||||
I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily.
|
||||
@@ -0,0 +1,413 @@
|
||||
#requires -Version 3.0 -Modules ActiveDirectory
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tool that bulk imports or removes User pictures, based on AD Group Membership
|
||||
|
||||
.DESCRIPTION
|
||||
Tool that bulk imports or removes User pictures, based on AD Group Membership
|
||||
If a user is in both groups, the picture will be removed!
|
||||
Idea based on my old tool to import Active Directory pictures.
|
||||
They are a bit to tiny, so I use Exchange now to make them look better in Exchange and Skype.
|
||||
|
||||
.PARAMETER AddGroup
|
||||
Active Directory Group with users that would like to have a picture.
|
||||
For all Members of this group, the Tool will try to set an image.
|
||||
|
||||
.PARAMETER RemGroup
|
||||
Active Directory Group with users that would like have have the picture removed.
|
||||
For all Members of this group, the Tool will try to remove the existing image (If set).
|
||||
|
||||
.PARAMETER PictureDir
|
||||
Directory that contains the pictures
|
||||
|
||||
.PARAMETER Extension
|
||||
Extension of the pictures
|
||||
|
||||
.PARAMETER workaround
|
||||
Workaround for Exchange 2016 on Windows Server 2016
|
||||
|
||||
.PARAMETER UPNDomain
|
||||
The default Domain, to add to the UPN
|
||||
|
||||
.EXAMPLE
|
||||
# Use the Groups 'ADDPIXX' and 'NOPIXX' to Set/Remove the User Pictures
|
||||
# There was an Issue with the User joerg.hochwald (Possible Picture Problem!
|
||||
PS C:\> .\Set-ADAllUserPicture.ps1 -AddGroup 'ADDPIXX' -RemGroup 'NOPIXX' -PictureDir 'c:\upixx\' -workaround -UPNDomain 'jhochwald.com'
|
||||
|
||||
WARNING: Unable to set Image c:\upixx\joerg.hochwald.jpg for User joerg.hochwald
|
||||
|
||||
.EXAMPLE
|
||||
# Use the Groups 'ADDPIXX' and 'NOPIXX' to Set/Remove the User Pictures
|
||||
# There was an Issue with the User jane.doe - Check that this user has a provissioned Mailbox (on Prem or Cloud)
|
||||
PS C:\> .\Set-ADAllUserPicture.ps1 -AddGroup 'ADDPIXX' -RemGroup 'NOPIXX' -PictureDir 'c:\upixx\' -workaround -UPNDomain 'jhochwald.com'
|
||||
|
||||
WARNING: Unable to handle jane.doe - Check that this user has a valid Mailbox!
|
||||
|
||||
.EXAMPLE
|
||||
# Use the Groups 'ADDPIXX' and 'NOPIXX' to Set/Remove the User Pictures - Everything went well
|
||||
PS C:\> .\Set-ADAllUserPicture.ps1 -AddGroup 'ADDPIXX' -RemGroup 'NOPIXX' -PictureDir 'c:\upixx\' -workaround -UPNDomain 'jhochwald.com'
|
||||
|
||||
WARNING: Unable to handle jane.doe - Check that this user has a valid Mailbox!
|
||||
|
||||
.NOTES
|
||||
TODO: There is no logging! Only the Exchange RBAC logging is in use
|
||||
TODO: A few error handlers are still missing
|
||||
|
||||
If a user is in both groups, the picture will be removed!
|
||||
Verbose could be very verbose. This is due to the fact, that the complete Exchange logging will be shown!
|
||||
|
||||
There are a few possibilities for Warnings and Errors. (Mostly for missing things)
|
||||
|
||||
Disclaimer: The code is provided 'as is,' with all possible faults, defects or errors, and without warranty of any kind.
|
||||
#>
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 1,
|
||||
HelpMessage = 'Active Directory Group with users that would like to have a picture')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('positive')]
|
||||
[string]
|
||||
$AddGroup,
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 2,
|
||||
HelpMessage = 'Active Directory Group with users that would like have have the picture removed.')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$RemGroup,
|
||||
[Parameter(Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 3,
|
||||
HelpMessage = 'Directory that contains the picures')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('PixxDir')]
|
||||
[string]
|
||||
$PictureDir,
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 5)]
|
||||
[Alias('defaultDomain')]
|
||||
[string]
|
||||
$UPNDomain,
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 4)]
|
||||
[ValidateSet('png', 'jpg', 'gif', 'bmp')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$Extension = 'jpg',
|
||||
[switch]
|
||||
$workaround = $false
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
if ($workaround)
|
||||
{
|
||||
# Unsupported Workaround according to https://hochwald.net/workaround-for-get-help-issue-with-exchange-2016-on-windows-server-2016/
|
||||
$null = (Add-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.SnapIn)
|
||||
}
|
||||
|
||||
# Cleanup
|
||||
$AddUserPixx = $null
|
||||
$NoUserPixx = $null
|
||||
|
||||
# Check the source directory string and fix it if needed
|
||||
if (-not ($PictureDir).EndsWith('\'))
|
||||
{
|
||||
# Fix it
|
||||
$PictureDir = $PictureDir + '\'
|
||||
|
||||
$paramWriteVerbose = @{
|
||||
Message = 'Fixed the Source Directory String!'
|
||||
}
|
||||
Write-Verbose @paramWriteVerbose
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$paramGetADGroupMember = @{
|
||||
Identity = $AddGroup
|
||||
ErrorAction = 'Stop'
|
||||
WarningAction = 'SilentlyContinue'
|
||||
}
|
||||
$AddUserPixx = (Get-ADGroupMember @paramGetADGroupMember | Select-Object -ExpandProperty samaccountname)
|
||||
}
|
||||
catch
|
||||
{
|
||||
$paramWriteError = @{
|
||||
Message = ('Unable to find {0}' -f $AddGroup)
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @paramWriteError
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$paramGetADGroupMember = @{
|
||||
Identity = $RemGroup
|
||||
ErrorAction = 'Stop'
|
||||
WarningAction = 'SilentlyContinue'
|
||||
}
|
||||
$NoUserPixx = (Get-ADGroupMember @paramGetADGroupMember | Select-Object -ExpandProperty samaccountname)
|
||||
}
|
||||
catch
|
||||
{
|
||||
$paramWriteError = @{
|
||||
Message = ('Unable to find {0}' -f $AddGroup)
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @paramWriteError
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
function Test-ValidEmail
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Simple Function to check if a String is a valid Mail
|
||||
|
||||
.DESCRIPTION
|
||||
Simple Function to check if a String is a valid Mail and return a Bool
|
||||
|
||||
.PARAMETER address
|
||||
Address String to Check
|
||||
|
||||
.EXAMPLE
|
||||
# Not a valid String
|
||||
PS C:\> Test-ValidEmail -address 'Joerg.Hochwald'
|
||||
False
|
||||
|
||||
.EXAMPLE
|
||||
# Valid String
|
||||
PS C:\> Test-ValidEmail -address 'Joerg.Hochwald@outlook.com'
|
||||
True
|
||||
|
||||
.NOTES
|
||||
Disclaimer: The code is provided 'as is,' with all possible faults, defects or errors, and without warranty of any kind.
|
||||
|
||||
Author: Joerg Hochwald
|
||||
#>
|
||||
|
||||
[OutputType([bool])]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage = 'Address String to Check')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$address
|
||||
)
|
||||
|
||||
process
|
||||
{
|
||||
($address -as [mailaddress]).Address -eq $address -and $address -ne $null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
if (-not ($AddUserPixx.samaccountname))
|
||||
{
|
||||
$paramWriteVerbose = @{
|
||||
Message = ('The AD Group {0} has no members.' -f $AddGroup)
|
||||
}
|
||||
Write-Verbose @paramWriteVerbose
|
||||
}
|
||||
else
|
||||
{
|
||||
# Add a counter
|
||||
$AddUserPixxCount = (($AddUserPixx.samaccountname).count)
|
||||
|
||||
$paramWriteVerbose = @{
|
||||
Message = ('The AD Group {0} has {1} members.' -f $AddGroup, $AddUserPixxCount)
|
||||
}
|
||||
Write-Verbose @paramWriteVerbose
|
||||
|
||||
foreach ($AddUser in $AddUserPixx.samaccountname)
|
||||
{
|
||||
if (($NoUserPixx.samaccountname) -notcontains $AddUser)
|
||||
{
|
||||
# Check the UPN and Fix it, if possible
|
||||
if (-not (Test-ValidEmail -address ($AddUser)))
|
||||
{
|
||||
if (-not ($UPNDomain))
|
||||
{
|
||||
# Whoopsie
|
||||
$paramWriteError = @{
|
||||
Message = 'UPN Default Domain not set but needed!'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @paramWriteError
|
||||
}
|
||||
else
|
||||
{
|
||||
# Let us fix this
|
||||
$AddUserUPN = ($AddUser + '@' + $UPNDomain)
|
||||
}
|
||||
}
|
||||
|
||||
# Build the Full Image Path
|
||||
$SingleUserPicture = ($PictureDir + $AddUser + '.' + $Extension)
|
||||
|
||||
# Check if Picture exists
|
||||
$paramTestPath = @{
|
||||
Path = $SingleUserPicture
|
||||
ErrorAction = 'Stop'
|
||||
WarningAction = 'SilentlyContinue'
|
||||
}
|
||||
|
||||
if (Test-Path @paramTestPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
$paramSetUserPhoto = @{
|
||||
Identity = $AddUserUPN
|
||||
PictureData = ([IO.File]::ReadAllBytes($SingleUserPicture))
|
||||
Confirm = $false
|
||||
ErrorAction = 'Stop'
|
||||
WarningAction = 'SilentlyContinue'
|
||||
}
|
||||
|
||||
$null = (Set-UserPhoto @paramSetUserPhoto)
|
||||
}
|
||||
catch
|
||||
{
|
||||
$paramWriteWarning = @{
|
||||
Message = ('Unable to set Image {0} for User {1}' -f $SingleUserPicture, $AddUser)
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
Write-Warning @paramWriteWarning
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$paramWriteWarning = @{
|
||||
Message = ('The Image {0} for User {1} was not found' -f $SingleUserPicture, $AddUser)
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
Write-Warning @paramWriteWarning
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$paramWriteVerbose = @{
|
||||
Message = ('Sorry, User {0} is member of {1} and {2}' -f $AddUser, $AddGroup, $RemGroup)
|
||||
}
|
||||
Write-Verbose @paramWriteVerbose
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not ($NoUserPixx.samaccountname))
|
||||
{
|
||||
$paramWriteVerbose = @{
|
||||
Message = ('The AD Group {0} has no members.' -f $RemGroup)
|
||||
}
|
||||
Write-Verbose @paramWriteVerbose
|
||||
}
|
||||
else
|
||||
{
|
||||
# Add a counter
|
||||
$NoUserPixxCount = (($NoUserPixx.samaccountname).count)
|
||||
|
||||
$paramWriteVerbose = @{
|
||||
Message = ('The AD Group {0} has {1} members.' -f $RemGroup, $NoUserPixxCount)
|
||||
}
|
||||
Write-Verbose @paramWriteVerbose
|
||||
|
||||
foreach ($NoUser in $NoUserPixx.samaccountname)
|
||||
{
|
||||
# Check the UPN and Fix it, if possible
|
||||
if (-not (Test-ValidEmail -address ($NoUser)))
|
||||
{
|
||||
if (-not ($UPNDomain))
|
||||
{
|
||||
# Whoopsie
|
||||
$paramWriteError = @{
|
||||
Message = 'UPN Default Domain not set but needed!'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @paramWriteError
|
||||
}
|
||||
else
|
||||
{
|
||||
# Let us fix this
|
||||
$NoUserUPN = ($NoUser + '@' + $UPNDomain)
|
||||
}
|
||||
}
|
||||
|
||||
$paramSetUserPhoto = @{
|
||||
Identity = $NoUserUPN
|
||||
Confirm = $false
|
||||
ErrorAction = 'Stop'
|
||||
WarningAction = 'SilentlyContinue'
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$null = (Remove-UserPhoto @paramSetUserPhoto)
|
||||
}
|
||||
catch
|
||||
{
|
||||
$paramWriteWarning = @{
|
||||
Message = ('Unable to handle {0} - Check that this user has a valid Mailbox!' -f $NoUser)
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
Write-Warning @paramWriteWarning
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
{
|
||||
# Cleaniup
|
||||
$AddUserPixx = $null
|
||||
$NoUserPixx = $null
|
||||
$AddUserPixxCount = $null
|
||||
$NoUserPixxCount = $null
|
||||
|
||||
# Do a garbage collection: Call the .NET function to cleanup some stuff
|
||||
$null = ([GC]::Collect())
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
@@ -0,0 +1,118 @@
|
||||
#requires -Version 3.0 -Modules ActiveDirectory
|
||||
|
||||
function Set-ADServerUsage
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Set all Active Directory related commands to use a special kind of server
|
||||
|
||||
.DESCRIPTION
|
||||
By default the Active Directory related commands search for a DC. By default I want to make
|
||||
use of the closest one. When I make BULK operations, I would like to use the Server with
|
||||
the PDC role. This becomes handy often!
|
||||
|
||||
.PARAMETER pdc
|
||||
Use the Active Directory Server who holds the PDC role.
|
||||
|
||||
.EXAMPLE
|
||||
# Use the closest Server
|
||||
PS> Set-ADServerUsage
|
||||
|
||||
.EXAMPLE
|
||||
# Use the Server with the PDC role
|
||||
PS> Set-ADServerUsage -pdc
|
||||
|
||||
.EXAMPLE
|
||||
# When it comes to scripts that do bulk operations, especially bulk loads and manipulation,
|
||||
# I use the following within the Script:
|
||||
if (Get-Command Set-ADServerUsage -ErrorAction SilentlyContinue)
|
||||
{
|
||||
Set-ADServerUsage -pdc
|
||||
}
|
||||
|
||||
.NOTES
|
||||
I use this helper function in my PROFILE. Therefore, some things a bit special.
|
||||
Who want's an error message every time a window opens under normal circumstances?
|
||||
#>
|
||||
param
|
||||
(
|
||||
[Parameter(ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName,
|
||||
Position = 1)]
|
||||
[switch]
|
||||
$pdc
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
# Defaults
|
||||
$SC = 'SilentlyContinue'
|
||||
|
||||
# Cleanup
|
||||
$dc = $null
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
<#
|
||||
The following would do the trick:
|
||||
#requires -Modules ActiveDirectory
|
||||
But I don't want any error messages, so I decided to use this old-school way to figure
|
||||
out if we are capable do what I want.
|
||||
#>
|
||||
if ((Get-Command -Name Get-ADDomain -ErrorAction $SC) -and (Get-Command -Name Get-ADDomainController -ErrorAction $SC) )
|
||||
{
|
||||
if ($pdc)
|
||||
{
|
||||
# Use the PDC instead
|
||||
$dc = ((Get-ADDomain -ErrorAction $SC -WarningAction $SC).PDCEmulator)
|
||||
}
|
||||
else
|
||||
{
|
||||
# Use the closest DC
|
||||
$dc = (Get-ADDomainController -Discover -NextClosestSite -ErrorAction $SC -WarningAction $SC)
|
||||
}
|
||||
|
||||
# Skip everything if we do NOT have the proper information.
|
||||
<#
|
||||
Under normal circumstances this is pretty useless, but I use some virtual machines that have the RSAT tools installed, but they are not domain joined.
|
||||
The fore I make this check. If all the systems that have the RSAT installed are domain joined, this test is obsolete.
|
||||
#>
|
||||
if ($dc)
|
||||
{
|
||||
# Make use of the Server from above
|
||||
$PSDefaultParameterValues.add('*-AD*:Server', "$dc")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region LICENSE
|
||||
<#
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, enabling Technology
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#>
|
||||
#endregion LICENSE
|
||||
|
||||
#region DISCLAIMER
|
||||
<#
|
||||
DISCLAIMER:
|
||||
- Use at your own risk, etc.
|
||||
- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind
|
||||
- This is a third-party Software
|
||||
- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way
|
||||
- The Software is not supported by Microsoft Corp (MSFT)
|
||||
- By using the Software, you agree to the License, Terms, and any Conditions declared and described above
|
||||
- If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution
|
||||
#>
|
||||
#endregion DISCLAIMER
|
||||
Reference in New Issue
Block a user