Git Product home page Git Product logo

asbuiltreport.microsoft.ad's People

Contributors

kennyparsons avatar rebelinux avatar tpcarman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asbuiltreport.microsoft.ad's Issues

Add Find Orphaned GPOs In SYSVOL health check

Adam Bertram

function Get-OrphanedGPO {
    
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$ForestName
    )
    try {
        ## Find all domains in the forest
        $domains = Get-AdForest -Identity $ForestName | Select-Object -ExpandProperty Domains
        $gpoGuids = @()
        $sysvolGuids = @()
        foreach ($domain in $Domains) {
            $gpoGuids += Get-GPO -All -Domain $domain | Select-Object @{ n='GUID'; e = {$_.Id.ToString()}} | Select-Object -ExpandProperty GUID
            foreach ($guid in $gpoGuids) {
                $polPath = "\\$domain\SYSVOL\$domain\Policies"
                $polFolders = Get-ChildItem $polPath -Exclude 'PolicyDefinitions' | Select-Object -ExpandProperty name
                foreach ($folder in $polFolders) {
                    $sysvolGuids += $folder -replace '{|}'
                }
            }
        }
        Compare-Object -ReferenceObject $sysvolGuids -DifferenceObject $gpoGuids | Select-Object -ExpandProperty InputObject
    } catch {
        $PSCmdlet.ThrowTerminatingError($_)
    }
}

Errors running report "Invalid object passed in, ':' or '}' expected. (1152): {"


< As Built Report Configuration >


Would you like to save the As Built Report configuration file? (y/n): n

VERBOSE: As Built Report configuration file not saved.

VERBOSE: Config.Report.Author = XXXXX

VERBOSE: Config.UserFolder.Path = C:\Users\XXXXX\AsBuiltReport

VERBOSE: Config.Company.FullName =

VERBOSE: Config.Company.Contact =

VERBOSE: Config.Company.Phone =

VERBOSE: Config.Company.Email =

VERBOSE: Config.Company.ShortName =

VERBOSE: Config.Company.Address =

VERBOSE: Config.Email.Port =

VERBOSE: Config.Email.Credentials =

VERBOSE: Config.Email.Server =

VERBOSE: Config.Email.To =

VERBOSE: Config.Email.From =

VERBOSE: Config.Email.UseSSL =

VERBOSE: Config.Email.Body =

VERBOSE: Populating RepositorySourceLocation property for module AsBuiltReport.Microsoft.AD.

VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\AsBuiltReport.Microsoft.AD\0.6.0\AsBuiltReport.Microsoft.AD.psm1'.

VERBOSE: Loading report configuration file from path 'C:\Program Files\WindowsPowerShell\Modules\AsBuiltReport.Microsoft.AD\0.6.0\AsBuiltReport.Microsoft.AD.json'.

New-AsBuiltReport : Invalid object passed in, ':' or '}' expected. (1152): {

"Report": {

    "Name": "Microsoft AD As Built Report",

    "Version": "1.0",

    "Status": "Released",

    "ShowCoverPageImage": true,

    "ShowTableOfContents": true,

    "ShowHeaderFooter": true,

    "ShowTableCaptions": true

},

"Options": {

    "ShowDefinitionInfo": false

},

"InfoLevel": {

    "_comment_": "0 = Disabled, 1 = Enabled, 2 = Adv Summary, 3 = Detailed",

    "Forest": 1,

    "Domain": 1,

    "DHCP": 1,

    "DNS": 1,

    "CA": 2

},

"HealthCheck": {

    "Domain": {

        "GMSA": true,

        "GPO": true

    },

    "DomainController": {

        "Diagnostic": true,

        "Services": true,

        "Software": true

    },

    "Site": {

        "Replication": true

    },

    "DNS": {

        "Aging": true,

        "DP": true

    },

    "DHCP": {

        "Summary": true,

        "Credential": true,

        "Statistics": true,

        "BP": true

    },

    "CA": {

        "Status": true

        "Statistics": true

    }

}

}

At line:1 char:1

  • New-AsBuiltReport -Report Microsoft.AD -Target 'XXXXXXXXXXX' ...

  • 
      + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,New-AsBuiltReport
    
    
    

No GMSA exists in AD ... error

Describe the bug
No GMSA exists in AD ... error

To Reproduce
Steps to reproduce the behavior:

  1. Go to ''Get-ABrADDomain.ps1" file
  2. Seach line 167
  3. Get-ADServiceAccount -Filter * -Server $using:DC -Properties *
  4. See error
    VERBOSE: [ 14:33:37:649 ] [ Document ] - Collecting the Active Directory Group Managed Service Accounts from DC .
    Cannot validate argument on parameter 'Server'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command
    again.
    • CategoryInfo : InvalidData: (:) [Get-ADServiceAccount], ParameterBindingValidationException
    • FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADServiceAccount
    • PSComputerName : xxxx.xxxx.xxx

Expected behavior
I'm thinking there is a missing parameter : -ErrorAction SilentlyContinu

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Group report for well-known groups without support for international domains

I'm always frustrated when group reports für e.g. german active directories, contain no table values for well known groups
german: Administratoren = Administrators

Is it poosibel to get these names in the report?

possible solution:
access well known groups via SID to include international names and expand them to localized group names
e.g. in Get-AbrADDomainObject.ps1 Line 219

$DomainSID = (get-addomain).domainsid.Value
$ForestSID
#$Groups = 'Domain Admins','Enterprise Admins','Administrators','Server Operators','DnsAdmins','Remote Desktop Users','Incoming Forest Trust Builders','Key Admins','Backup Operators','Cert Publishers','Print Operators','Account Operators','Schema Admins'

$GroupsSID = "$DomainSID-512","$DomainSID-519",'S-1-5-32-544','S-1-5-32-549',"$DomainSID-1104",'S-1-5-32-555','S-1-5-32-557',"$DomainSID-526",'S-1-5-32-551',"$DomainSID-517",'S-1-5-32-550','S-1-5-32-548',"$DomainSID-518"
$Groups = $GroupsSID | Get-ADGroup | select -ExpandProperty name

Thank you for this awesome reports
Bert

Add Domain Controller SYSVOL State Data healthcheck

Get-CIMInstance -CIMSession $DCName -Namespace "root/microsoftdfs" -Class "dfsrreplicatedfolderinfo" -Filter "ReplicatedFolderName = 'SYSVOL Share'" -EA 0 -Verbose:$False | Select-Object State

			Switch($Result.State)
			{
				0		{$SysvolState  = "0 = Uninitialized"; Break}
				1		{$SysvolState  = "1 = Initialized"; Break}
				2		{$SysvolState  = "2 = Initial Sync"; Break}
				3		{$SysvolState  = "3 = Auto Recovery"; Break}
				4		{$SysvolState  = "4 = Normal"; Break}
				5		{$SysvolState  = "5 = In Error"; Break}
				Default {$SysvolState  = "Unable to determine the SYSVOL State: $($Result.State)"; Break}
			}

Add LAPS passwords section

Is your feature request related to a problem? Please describe.
Add support for collecting LAPS information

Fix Naming Context Last Backup section

Describe the bug

Naming Context Last Backup section only works if report is runned on a Domain Controller server

To Reproduce
Steps to reproduce the behavior:

  1. Run the report on a device other than a DC
  2. The report show a error saying is unable to connect to the domain.

Add Active Directory Recycle Bin is Not Enabled health check

Accidental deletion of Active Directory objects is common for Active Directory Domain Services (AD DS) users. With the Recycle Bin Feature, one could recover accidentally deleted objects in Active Directory.

Enable the AD Recycle Bin for the forest.

On a domain controller in the customer.com parent domain, from an elevated PowerShell prompt, enter the following command as one line:

$RootDomain = (Get-ADForest).Name
$ADForestconfigurationNamingContext = (Get-ADRootDSE).configurationNamingContext
Enable-ADOptionalFeature -Identity "CN=Recycle Bin Feature,CN=Optional Features,CN=Directory Service,CN=Windows NT,CN=Services, $ADForestconfigurationNamingContext" -Scope ForestOrConfigurationSet -Target $RootDomain

Improve Domain Controller DNS IP Configuration Health Check

Improve DNS IP configuration to better detect 127.0.0.1 position.

Example:

DC IP Preferred DNS Alternate DNS DNS3 DNS4 Best Practice
10.10.10.20 10.10.10.25 127.0.0.1 10.10.10.28 10.10.10.29 Yes
10.10.10.20 10.10.10.20 10.10.10.25 10.10.10.28 127.0.0.1 NOOO
10.10.10.20 127.0.0.1 10.10.10.20 10.10.10.28 10.10.10.25 Hell NO

if there are 4 IPs configured as DNS, the IP 127.0.0.1 can never be the first one.

Error on DomainController module

Describe the bug
Error on Report
New-AsBuiltReport : The property 'Count' cannot be found on this object. Verify that the property exists.

To Reproduce
Steps to reproduce the behavior:

  1. run report with EnableHealthCheck option

Expected behavior
Allow the report to finish without errors

Error while running the script

Bug description

While running any cmdlet to generate the AD report I get the error: the server has returned the following error invalid enumeration context while running Get-Aduser

Command-line input

New-AsBuiltReport -Report Microsoft.AD -Target 'admin-dc-01v.contoso.local' -Username '[email protected]' -Password 'P@ssw0rd' -Format Html,Word -OutputFolderPath 'C:\Users\Jon\Documents' -Timestamp

Steps to reproduce

The error occurs after running New-AsBuiltReport -Report Microsoft.AD -Target 'admin-dc-01v.contoso.local' -Username '[email protected]' -Password 'P@ssw0rd' -Format Html,Word -OutputFolderPath 'C:\Users\Jon\Documents' -Timestamp

Expected behaviour

Script should run to completion with no errors.

Screenshots

No response

Operating System

Windows Server 2019

PowerShell Version

5.1.22621.963

PowerShell Modules


Name                       Version
----                       -------
AsBuiltReport.Core         1.3.0  
AsBuiltReport.Microsoft.AD 0.7.12 
PScribo                    0.10.0 
PScriboCharts              0.9.0  
PSPKI                      3.7.2 

Additional Context

The script does complete after the error occurs. i believe it is caused by the number of users theGet-ADUsercmdlet has to parse
which is roughly 265000 users. I ran another script to validate the user object count and found that the difference in the value was neglible but very close.

Before submitting

Improve DomainController DCDiag section

Is your feature request related to a problem? Please describe.

Improve DomainController DCDiag section

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

DNS Section issues with try/catch statements

Currently on the pre 0.4.0 version there is a problem with the DNS section when some of the elements of the report have problems with the retrieved content. Example: DNS service stopped, etc...

Static Entry remaining in a ps1 file

Describe the bug
Static var in a .ps1 file

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'Get-AbrADDomain.ps1' file
  2. Seach line 159'
  3. Select $Domain = "Pharmax.local"
  4. Replace by $Domain
  5. Error Message
    Cannot find an object with identity: 'pharmax.local' under: 'DC=xxx,DC=xx'.
    • CategoryInfo : ObjectNotFound: (pharmax.local:ADDomain) [Get-ADDomain], ADIdentityNotFoundException
    • FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.
      Commands.GetADDomain
    • PSComputerName : xxxx1.xxxxx.xxx

Expected behavior

Regards
Olivier

HealthCheck - Restrict Anonymous Access

Restrict Anonymous LDAP access by limiting the "Pre-Windows 2000 Compatible Access" group and
confirm the dsHeuristic value is not set to 0000002.

When the Pre-Windows 2000 Compatible Access group contains “Everyone” or “Anonymous Logon”
unauthenticated users can perform LDAP queries on Active Directory. This enables attackers to perform
domain reconnaissance.

<#PSScriptInfo
    .VERSION 1.0.1
    .GUID cd46c714-bb58-4416-947b-1691b8185859
    .AUTHOR florian.burnel
    .TAGS ActiveDirectory
    .LICENSEURI
    .PROJECTURI https://github.com/florianburnel/PowerShell/tree/master/AD-Get-ADAnonymousAccessStatus
    .ICONURI
    .EXTERNALMODULEDEPENDENCIES
    .REQUIREDSCRIPTS 
    .EXTERNALSCRIPTDEPENDENCIES 
    .RELEASENOTES
    .DESCRIPTION This script query the Active Directory to check the unicode value "dsHeuristics". The 7th value of this settings determine if anonymous access is authorized or not in your environment. So, if the value if "not defined", it's OK because equal 0. But if the value is 2, it's bad !
#>

<#
.DESCRIPTION
        
         This script query the Active Directory to check the unicode value "dsHeuristics".
         The 7th value of this settings determine if anonymous access is authorized or not in your environment.
         So, if the value if "not defined", it's OK because equal 0. But if the value is 2, it's bad !
        
        .NOTES
	     NAME:	Get-ADAnonymousAccessStatus.ps1
	     AUTHOR:	Florian Burnel
	     EMAIL:	[email protected]
         URL : www.it-connect.fr
	     TWITTER: @FlorianBurnel
        
        .EXAMPLE        
         PS> .\Get-ADAnonymousAccessStatus.ps1
   
        .PARAMETER
         NO PARAMETER.


	    VERSION HISTORY:
	        
        1.0.0 	2018.01.25
	            Initial Version
				
		1.0.1   2018.01.25
				Add block "PSScriptInfo" for PowerShell Gallery
#>

$TargetDN = ("CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration," + (Get-ADDomain).DistinguishedName)
$ValuedsHeuristics = (Get-ADObject -Identity $TargetDN -Properties dsHeuristics).dsHeuristics

if(($ValuedsHeuristics -eq "") -or ($ValuedsHeuristics.Length -lt 7)){
    
    Write-Output "Good ! Anonymous access is already disable !"

}elseif(($ValuedsHeuristics.Length -ge 7) -and ($ValuedsHeuristics[6] -eq "2")){

    Write-Output "Warning ! Anonymous access is enable and authorized on your Active Directory ! Value = $ValuedsHeuristics"

}

GetCurrentDomain Error

Describe the bug
I receive the following error when executing the as-built script:

New-AsBuiltReport : Exception calling "GetCurrentDomain" with "0" argument(s): "Current security context is not
associated with an Active Directory domain or forest."
At line:1 char:1

  • New-AsBuiltReport -report Microsoft.AD -target domain2.domain2.priv - ...
  •   + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,New-AsBuiltReport
    
    

To Reproduce
Windows 10 21H2 domain joined VM named desktop1. I'm running the script from this VM.
Windows 2016 domain controller (domain2 is the servername and domain2.priv is the domain) in a 2-way trust with a second 2016 domain controller (domain1 is the servername and domain1.priv is the domain)
Used a user account (user1) that has been added to the enterprise admin security group (and removed domain user permissions) or using the domain administrator account

Expected behavior
I would expect it to generate a word and html report. I have run this same script on the domain controller itself and it has had no problems generating the report.

Screenshots

< As Built Report Configuration >
---------------------------------------------- Would you like to save the As Built Report configuration file? (y/n): n Please wait while the Microsoft AD As Built Report is being generated. WARNING: [ 10:47:09:748 ] [ Document ] - Please refer to the AsBuiltReport.Microsoft.AD github website for more detailed information about this project. WARNING: [ 10:47:09:748 ] [ Document ] - Do not forget to update your report configuration file after each new release.
WARNING: [ 10:47:09:764 ] [ Document ] - Documentation: https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD
WARNING: [ 10:47:09:764 ] [ Document ] - Issues or bug reporting:
https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD/issues
WARNING: [ 10:47:09:779 ] [ Document ] - AsBuiltReport.Microsoft.AD 0.7.10 is currently installed.
WARNING: [ 10:47:32:373 ] [ Document ] - Cannot index into a null array.
WARNING: [ 10:47:32:391 ] [ Document ] - Cannot index into a null array.
WARNING: [ 10:47:32:391 ] [ Document ] - Cannot index into a null array.
New-AsBuiltReport : Exception calling "GetCurrentDomain" with "0" argument(s): "Current security context is not
associated with an Active Directory domain or forest."

At line:1 char:1

  • New-AsBuiltReport -report Microsoft.AD -target domain2.domain2.priv - ...
  •   + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,New-AsBuiltReport
    
    
    

Additional context
This is the full script that I am running to execute the report. I have run just the AD-Asbuilt command and it generates the same error, so I don't believe my other lines of code are affecting it. The script is writtento install all the required modules and the end generates some excel output files. This is for a project I am working on to setup a trust between 2 domains. A feature request I might suggest would be for the As-Built to dump out a list of users, groups, computers and what users/computers belong to what groups into the report. These options might be better off as a flag as there could be a lot of information and some people may not be interested in such a large report. In our case, we have to be mindful of user overlap between two non-joined domains. If at some point in the future the end user decides to join them and migrate users, conflicts can occur, so having that information is crucial. I have included my full script below for your info.


Write-Host "This script will perform an inventory of an active directory domain for you."
Write-Host "It must be run from the domain controller or a domain joined Windows 10 machine."
Write-Host "The user account used will need to be an Enterprise Admin for the full collection to work"
Write-Host ""
Write-Host ""
Write-Host "What type of machine are you running this from?"
Write-Host "(1) Windows 10 domain attached"
Write-Host "(2) A domain controller in the domain"
$system = Read-Host "Enter Number: "
Write-Host ""
Write-Host ""
$domain = Read-Host "Enter the domain controller FQDN: "
$username = Read-Host "Enter username to access the domain controller: "
$password = Read-Host "Enter password for the account: "
$Foldername ="c:\temp"

Create c:\temp directory

if (Test-Path $foldername) {
Write-Host "Folder c:\temp exists, continuing..."
}
else {
New-Item $Foldername -ItemType Directory
Write-Host "Folder c:\temp created successfully, continuing..."
}

if ($system -eq 1) {

Windows 10 Host

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLs12
Install-Module -Name PSPKI -Force
Install-Module -Name PScriboCharts -Force
Install-Module -Name AsBuiltReport.Microsoft.AD -Force
Install-Module -Name ImportExcel -Force
Add-WindowsCapability -online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'
Add-WindowsCapability -Online -Name 'Rsat.CertificateServices.Tools~~~~0.0.1.0'
Add-WindowsCapability -online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
Add-WindowsCapability –online –Name 'Rsat.Dns.Tools~~~~0.0.1.0'
Add-WindowsCapability -online -Name 'Rsat.DHCP.Tools~~~~0.0.1.0'

}
if ($system -eq 2) {

Domain Controller Host

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[Net.ServicePointManager]::SecurityProtocol
Install-PackageProvider -Name Nuget -MinimumVersion 2.8.5.201 -Force
Install-Module -Name ImportExcel -Force
Install-Module -Name PSPKI -Force
Install-Module -Name PScriboCharts -Force
Install-Module -Name AsBuiltReport.Microsoft.AD -Force
Install-WindowsFeature -Name RSAT-ADCS
Enable-WindowsOptionalFeature -FeatureName RSAT-AD-PowerShell
Enable-WindowsOptionalFeature -FeatureName RSAT-ADCS,RSAT-ADCS-mgmt
Enable-WindowsOptionalFeature -FeatureName RSAT-DNS-Server
Enable-WindowsOptionalFeature -FeatureName RSAT-DHCP
Enable-WindowsOptionalFeature -FeatureName GPMC

}

As-Built Script Execution

New-AsBuiltReport -Report Microsoft.AD -Target $domain -Username $username -Password $password -Format Html,Word -OutputFolderPath $foldername -Timestamp -EnableHealthCheck

Get Domain Attached Computer List

get-adcomputer -filter * -Properties * | export-excel -path $foldername\computerexport.xlsx

Get Domain User List

get-aduser -filter * -Properties * | Select-Object Name, Surname, GivenName, SamAccountName, CanonicalName, DistinguishedName | export-excel -path $foldername\userexport.xlsx

Get Domain Group Info

get-adgroup -filter * -Properties * | export-excel -path $foldername\groupexport.xlsx

Get Group Name

get-adgroup -filter * | select-object Name | export-csv -path $foldername\grouplist.csv

Get group membership

import-csv $foldername\grouplist.csv | Foreach-object {
Get-ADGroupMember -Identity $($.Name) | Select-Object Name, ObjectClass, SAMaccountName | export-excel -path $foldername"Group.xlsx" -Append -Worksheet $($.Name)
}

A referral was returned from the server

Describe the bug

The following error is displayed on the console:

A referral was returned from the server
    + CategoryInfo          : NotSpecified: (Administrators:ADGroup) [Get-ADGroupMember], ADException
    + FullyQualifiedErrorId : ActiveDirectoryServer:8235,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
    + PSComputerName        : server-dc-01v.pharmax.local

Unable to run report

Hi,
I'm trying to run the current module with the command using powershell7 & PowerShell 5.1 from a client machine to the AD server without any success:
Script:
New-AsBuiltReport -Report Microsoft.AD -Target 'FQDN Name' -username 'username@domainName' -Password 'xxxxxx' -Format Html -OutputFolderPath 'C:\Users\Administrator\Documents' -Timestamp
PS 7 error:
Get-ADDomain: Cannot validate argument on parameter 'Identity'. The Identity property on the argument is null or empty.
Get-ADDomain: Cannot validate argument on parameter 'Identity'. The Identity property on the argument is null or empty.
Get-DhcpServerInDC: Cannot process argument transformation on parameter 'CimSession'. Cannot convert the "CimSession: xx.xx.xx" value of type "Deserialized.Microsoft.Management.Infrastructure.CimSession" to type "Microsoft.Management.Infrastructure.CimSession[]".
New-AsBuiltReport: The term 'Get-CertificationAuthority' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.If applicable, add screenshots to help explain your problem.

Client OS: Win10 x64-based PC ,EnterpriseEdition, 10.0.19043, VMware Virtual Platform
Server OS: Windows Server 2019

PS x86:
Cannot validate argument on parameter 'Identity'. The Identity property on the argument is null or empty.
+ CategoryInfo : InvalidData: (:) [Get-ADDomain], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADDoma
in
+ PSComputerName : xx.xx.xx
*The FQDN is the right one
*The required modules are installed on the server
*I do success while running the module locally on the AD server.
Can you assist in debugging, please?
Warm regards,
XXXX XXXX,
Cybersecurity Architect & Consultant
XXX Technologies | Services

Some improvements

Hi Jonathan
I've done a list of improvments possible :

Function Get-AbrADDomain
Gathering Actually / could be added
- Global Catalog
- Computers (count) / Servers : Get-ADComputer -Filter { OperatingSystem -like "Windows Ser*"} -Property OperatingSystem -Server $using:GlobalCatalog -Searchbase (Get-ADDomain -Identity $using:Item).distinguishedName) | Measure-Object
I'm suggest to use -Filter on OperatingSystem Property. The filter must be "Windows Serv*". Why ? In En language, it Windows Server, in Fr it's Windows Serveur. I'm thinking this could be match with other language
/ Domain Controllers : (Get-ADDomainController -filter * | Select-Object name | Measure-Object).count
- Users (count) / Privileged Account : ((Get-ADUser -Filter {AdminCount -eq "1"} -Property AdminCount -Server $using:GlobalCatalog -Searchbase (Get-ADDomain -Identity $using:Item).distinguishedName) | Measure-Object).count
I'm suggest to use the property AdminCount
- Groups (count) / Privileged Groups
<# Privileged Group Membership for the following groups:
- Enterprise Admins - SID: S-1-5-21root domain-519
- Schema Admins - SID: S-1-5-21root domain-518
- Domain Admins - SID: S-1-5-21domain-512
- Cert Publishers - SID: S-1-5-21domain-517
- Administrators - SID: S-1-5-32-544
- Account Operators - SID: S-1-5-32-548
- Server Operators - SID: S-1-5-32-549
- Backup Operators - SID: S-1-5-32-551
- Print Operators - SID: S-1-5-32-550
Reference: http://support.microsoft.com/kb/243330
#>
$PrivilegedGroupsRef = @("S-1-5-32-544";"S-1-5-32-548";"S-1-5-32-549";"S-1-5-32-551";"S-1-5-32-550";"$rootDomainSid-519";"$rootDomainSid-518")
$AllGroups = Get-ADGroup -Filter *
$PrivilegedGroups = @()
$PrivilegedGroups = foreach ($Group in $AllGroups)
{
If ($PrivilegedGroupsRef -contains $Group.sid.Value)
{
# Group is a privileged Group, Addin to a var
$Group
}
}
($PrivilegedGroups | Measure-Object).Count
I'm suggest to use the SID because the name or the DisplayName of the privileged groups is depending of the current language.
You could be inspired by the previous code.
- Password Policy / FineGrained Password Policy
You could use : Get-ADFineGrainedPasswordPolicy -Filter {Name -like "*"}
The properties Names between ADDefaultPasswordPolicy and ADFineGrainedPasswordPolicy seem to be the same.
- GMSA / it seems you're filtering on Enabled -eq Yes. It could be useful to have All GMSAs and GMSA Enabled/disabled

Function Get-AbrADGPO
Gathering Actually / could be added
- All GPOs Array with few properties : DisplayName, Status, Created, Modified.
/ You could add more info. Here some samples
$AllGpos = Get-GPO -All
#Gathering all GPOs Info
$AllGpoInfo = foreach ($Item in $Allgpos)
{
[xml]$Gpoxml = Get-GPOReport -ReportType Xml -Guid $Item.Id
[PSCustomObject]@{
"Name" = $Gpoxml.GPO.Name
"Description" = $Item.Description
"CreationTime" = $Gpoxml.GPO.CreatedTime
"ModifedTime" = $Gpoxml.GPO.ModifiedTime
"Owner" = $item.Owner
"ComputerEnabled" = $gpoxml.GPO.Computer.Enabled
"User.Enabled" = $gpoxml.GPO.User.Enabled
"LinksTo" = $Gpoxml.GPO.LinksTo.SOMPath
"FilterName" = $Gpoxml.GPO.FilterName
"FilterDescription" = $Gpoxml.GPO.FilterDescription
}
}
# Gathering All GPOs withe AllSettings Disabled
$AllSettingsDisabledGpos = Get-GPO -All | Where-Object { $_.GpoStatus -eq 'AllSettingsDisabled' }

# Gathering	All GPOs unlinked
$AllGposUnlinked = foreach ($item in $AllGpos)
	{
	[xml]$Gpoxml = Get-GPOReport -ReportType Xml -Guid $Item.Id
	if (-not ($Gpoxml.GPO.LinksTo.SOMPath))
		{
		# GPO unlinked to any OU
		[PSCustomObject]@{
			"Name"                           = $Gpoxml.GPO.Name
			"CreationTime"                   = $Gpoxml.GPO.CreatedTime
			"ModifiedTime"                   = $Gpoxml.GPO.ModifiedTime
			"ComputerEnabled"                = $gpoxml.GPO.Computer.Enabled
			"UserEnabled"                    = $gpoxml.GPO.User.Enabled
			"LinkTo"                         = $Gpoxml.GPO.LinksTo.SOMPath
			"FilteName"                      = $Gpoxml.GPO.FilterName
			"FilterDescription"              = $Gpoxml.GPO.FilterDescription
			"Corrective Action"              = "GPO to remove"
			}
		}
	}

# Gathering GPO empty 
$AllGposEmpty = foreach ($item in $AllGpos)
	{
	[xml]$Gpoxml = Get-GPOReport -ReportType Xml -Guid $Item.Id
	if ( ($null -eq ($Gpoxml.GPO.Computer.ExtensionData)) -and ($null -eq ($Gpoxml.GPO.User.extensionData)) )
		{
		# GPO with no User and COmputer Settings
		[PSCustomObject]@{
			"Name"             = $Gpoxml.GPO.Name
			"CreationTime"     = $Gpoxml.GPO.CreatedTime
			"ModifedTime"      = $Gpoxml.GPO.ModifiedTime
			"ComputerParameters"  = if ($gpoxml.GPO.computer.ExtensionData -like "")
			{
				"No parametrer"
			}
			else
			{
				"Existing Computer Parameters"
			}
			"UserParameters"      = if ($gpoxml.GPO.User.ExtensionData -like "")
			{
				"No parametrer"
			}
			else
			{
				"Existing User Parameters"
			}
			"Corrective Action"    = "No User and Computer parameters are set : GPO to remove"
			}
		}
	}

$AllGposEmpty

Gathering GPO without owner (tombstone)

$AllGposTombstone = foreach ($item in $AllGpos)
{
[xml]$Gpoxml = Get-GPOReport -ReportType Xml -Guid $Item.Id
if ($Null -eq $Gpoxml.GPO.SecurityDescriptor.Owner.Name.'#text')
{
# GPO with no existing Creator-Owner
[PSCustomObject]@{
"Name" = $Gpoxml.GPO.Name
"CreationTime" = $Gpoxml.GPO.CreatedTime
"ModifedTime" = $Gpoxml.GPO.ModifiedTime
"Owner" = $Gpoxml.GPO.SecurityDescriptor.Owner.Name.'#text'
"Corrective Action" = "GPO without owner. correct or delete"
}
}
}
$AllGposTombstone

#Gathering GPOs "Enforced"
$OU = Get-ADOrganizationalUnit -Filter * | Select-Object -Property DistinguishedName
$AllGposEnforced = @() #initialization
foreach ($item in $OU)
{
$AllGposEnforced += Get-GPInheritance -Target $item.DistinguishedName | Select-Object -ExpandProperty GpoLinks
}
$AllGposEnforced

Gathering OUs with GPO inheritance blocked

$OUs = Get-ADOrganizationalUnit -Filter * | Select-Object -Property DistinguishedName
$AllInheritanceOU = foreach ($ou in $ous)
{
Get-GPInheritance -Target $OU.DistinguishedName |
Where-Object { $.GPOInheritanceBlocked } |
Select-Object -Property @{ Label = "GpoInheritanceBlocked" ; Expression = { $
.GpoInheritanceBlocked } },
@{ Label = "OUName" ; Expression = { $.Name } },
@{ Label = "ContainerType" ; Expression = { $
.ContainerType } }
}
$AllInheritanceOU

#rGatheringg GPOs with LogonScript
try
{
$Allgpos = @(Get-GPO -All)
$i = 0
$userlogon = @() # initialization
$Computerlogon = @() # initialization
ForEach ($gpo in $Allgpos)
{
#Start-Sleep -Seconds 5
$i++
$xml = [xml]($gpo | Get-GPOReport -ReportType XML)
#User logon script
$userScripts = @($xml.GPO.User.ExtensionData | Where-Object { $.Name -eq 'Scripts' })
If ($userScripts.count -gt 0)
{
$userScripts.extension.Script | ForEach-Object {
$objUser = [PSCustomObject] @{
GPOName = $gpo.DisplayName
ID = $gpo.ID
GPOState = $gpo.GpoStatus
GPOType = 'User'
Type = $
.Type
Script = $.command
ScriptType = $
.command -replace '..(.)', '$1'
}
$userlogon += $objUser
}# end foreach
} # end if user

    #Computer logon script
    $computerScripts = @($xml.GPO.Computer.ExtensionData | Where-Object { $_.Name -eq 'Scripts' })
    If ($computerScripts.count -gt 0)
    {
        $computerScripts.extension.Script | ForEach-Object {
            $objcomputer = [PSCustomObject] @{
                GPOName    = $gpo.DisplayName
                ID         = $gpo.ID
                GPOState   = $gpo.GpoStatus
                GPOType    = 'Computer'
                Type       = $_.Type
                Script     = $_.command
                ScriptType = $_.command -replace '.*\.(.*)', '$1'
            }
            $Computerlogon += $objcomputer
        } # end foreach
    } # end if computer
} # end foreach gpo
$AllGposWittLogonScript = $userlogon + $Computerlogon
$AllGposWittLogonScript

}

Catch
{
Write-Warning ("{0}" -f $_.exception.message)
}

I hope this help to improve future version of this fantastic module
Regards
Olivier

Sort "Organizational Unit" by path

Is it possible to configure the output of "Active Directory Organizational Unit" to be sorted by the path instead of the name?
Many OU's may have the same name but in different structures.
Sorting by the structure would improve the readability.
Thanks!

Issues Running Windows.AD

Get the following Error when i run the AsbuiltReport.Windows.AD

Please wait while the Microsoft AD As Built Report is being generated.
New-AsBuiltReport : The 'Invoke-AsBuiltReport.Microsoft.AD' command was found in the module
'AsBuiltReport.Microsoft.AD', but the module could not be loaded. For more information, run 'Import-Module
AsBuiltReport.Microsoft.AD'.
At line:1 char:1

  • New-AsBuiltReport -Report Microsoft.AD -Target DC ...
  •   + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,New-AsBuiltReport
    

Issues on Certificate Authority section

Describe the bug

The Certificate Authority section does not run if run on a PC that is not a member of the domain under test.

To Reproduce
Steps to reproduce the behavior:

  1. Run report on a PC not member of the Domain in Target
  2. An error is displayed in the CA cmdlet that queries the domain of the PC instead of the domain specified in the target.

Expected behavior

The report must find out the current domain of the PC and compare it with the list of domains in the forest to find out if the PC used to run the report is in the list of domains to be analyzed.

Fix Duplicate Objects section

Describe the bug

Duplicate Objects section only works if report is runned on a Domain Controller server

To Reproduce
Steps to reproduce the behavior:

  1. Run the report on a device other than a DC
  2. The report show a error saying is unable to connect to the domain.

minor improvments

Hi great job to document AD infrastructure. Could i Suggest some minor improvments ?

  • Adding Fined Grained Password Policies
  • Adding Log Path and Sysvol Pth in 1.3.6.2
  • For DCDiag test (1.3.6.3), are you sure that the custom function Invoke-dcdiag runs fine different languages ? I'm not sure of that.
  • Adding Conditional forwarders in DNS Section

I'll try to test this module more deeply when I should.

Regards

Find Group Policies with Missing Permissions

The following PowerShell function can help you identify GPOs with missing permissions (missing both ‘Authenticated Users’ and ‘Domain Computers’ groups):

Function Get-GPMissingPermissionsGPOs
{
   $MissingPermissionsGPOArray = New-Object System.Collections.ArrayList
   $GPOs = Get-GPO -all
   foreach ($GPO in $GPOs) {
        If ($GPO.User.Enabled) {
            $GPOPermissionForAuthUsers = Get-GPPermission -Guid $GPO.Id -All | select -ExpandProperty Trustee | ? {$_.Name -eq "Authenticated Users"}
            $GPOPermissionForDomainComputers = Get-GPPermission -Guid $GPO.Id -All | select -ExpandProperty Trustee | ? {$_.Name -eq "Domain Computers"}
            If (!$GPOPermissionForAuthUsers -and !$GPOPermissionForDomainComputers) {
                $MissingPermissionsGPOArray.Add($GPO)| Out-Null
            }
        }
    }
    If ($MissingPermissionsGPOArray.Count -ne 0) {
        Write-Warning  "The following Group Policy Objects do not grant any permissions to the 'Authenticated Users' or 'Domain Computers' groups:"
        foreach ($GPOWithMissingPermissions in $MissingPermissionsGPOArray) {
            Write-Host "'$($GPOWithMissingPermissions.DisplayName)'"
        }
    }
    Else {
        Write-Host "All Group Policy Objects grant required permissions. No issues were found." -ForegroundColor Green
    }
}

Fix Duplicate SPN section

Describe the bug

Duplicate SPN section only works if report is runned on a Domain Controller server

To Reproduce
Steps to reproduce the behavior:

  1. Run the report on a device other than a DC
  2. The report show a error saying is unable to connect to the domain.

DHCP Report without domain controller / domain admin access.

Description

It would be useful to have an option to run a report for only DHCP.

In this scenario, DHCP is on a separate server (not installed on a DC)
User running report has Administrator access on DHCP server, but no domain admin credentials.

I've been able to test this by:
-commenting out all sections other than DHCP
-configure CIMSession to run on local system
-remove any references to remote PSSession
-retaining $ADSystem section, but not run against remote session.

Additional Context

No response

Before submitting

  • I have read the documentation, and referred to the known issues before submitting this feature request.
  • I have checked for previously opened & closed issues before submitting this feature request.

HealthCheck - Remove Inactive AD Admin Accounts

Unused or underutilized accounts in highly privileged groups, outside of any break-glass emergency
accounts like the default Administrator account, should have their AD Admin privileges removed.

Get-ADGroupMember 'Administrators' -Recursive | Get-ADUser -property
SAMAccountName,DisplayName,LastLogonDate,PasswordLastSet,Description,Created,
UserPrincipalName | Where-Object {($.LastLogonDate -le (Get-Date).AddDays(-
30)) -AND ($
.PasswordLastSet -le (Get-Date).AddDays(-365))}

Error running report if multiple version are installed together

Describe the bug

I just updated to the latest version(0.5.5), on a server that used to run 0.5.4.
When I try to run it now, i'm getting a failure:

WARNING: [ 12:30:06:171 ] [ Document ] - Installed AsBuiltReport.Microsoft.AD Version: System.Object[]
New-AsBuiltReport : Could not compare "0.7.9" to "0.7.7 0.7.8". Error: "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Version"."
At line:1 char:2
+  New-AsBuiltReport -Report Microsoft.AD -Target X.X.X.X -Username XXX ...
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,New-AsBuiltReport

System.Collections.ArrayList message are displayed in DNS Root Hints section

Root Hints Table

Name IP Address
a.root-servers.net. 2001:503:ba3e::2:30, System.Collections.ArrayList
a.root-servers.net. 2001:503:ba3e::2:30, System.Collections.ArrayList
b.root-servers.net. 2001:500:200::b, System.Collections.ArrayList
b.root-servers.net. 2001:500:200::b, System.Collections.ArrayList
c.root-servers.net. 2001:500:2::c, System.Collections.ArrayList
c.root-servers.net. 2001:500:2::c, System.Collections.ArrayList
d.root-servers.net. 2001:500:2d::d, System.Collections.ArrayList
d.root-servers.net. 2001:500:2d::d, System.Collections.ArrayList
e.root-servers.net. 2001:500:a8::e, System.Collections.ArrayList
e.root-servers.net. 2001:500:a8::e, System.Collections.ArrayList
f.root-servers.net. 2001:500:2f::f, System.Collections.ArrayList
f.root-servers.net. 2001:500:2f::f, System.Collections.ArrayList
g.root-servers.net. 2001:500:12::d0d, System.Collections.ArrayList
g.root-servers.net. 2001:500:12::d0d, System.Collections.ArrayList
h.root-servers.net. 2001:500:1::53, System.Collections.ArrayList
h.root-servers.net. 2001:500:1::53, System.Collections.ArrayList
i.root-servers.net. 2001:7fe::53, System.Collections.ArrayList
i.root-servers.net. 2001:7fe::53, System.Collections.ArrayList
j.root-servers.net. 2001:503:c27::2:30, System.Collections.ArrayList
j.root-servers.net. 2001:503:c27::2:30, System.Collections.ArrayList
k.root-servers.net. 2001:7fd::1, System.Collections.ArrayList
k.root-servers.net. 2001:7fd::1, System.Collections.ArrayList
l.root-servers.net. 2001:500:9f::42, System.Collections.ArrayList
l.root-servers.net. 2001:500:9f::42, System.Collections.ArrayList
m.root-servers.net. 2001:dc3::35, System.Collections.ArrayList
m.root-servers.net. 2001:dc3::35, System.Collections.ArrayList

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.