tacticalrmm/scripts/Win_AD_Hudu_ADDS_Documentat...

328 lines
12 KiB
PowerShell

<#
.Synopsis
Automatically document ADDS configuration
.DESCRIPTION
Automatically document ADDS configuration. Submits generated documentation to your Hudu instance and associates it with the Company provided by ClientName. Requires Global Keystore variables for HuduBaseDomain and HuduApiKey.
.INPUTS
-ClientName {{client.name}}
-HuduBaseDomain {{global.HuduBaseDomain}}
-HuduApiKey {{global.HuduApiKey}}
.NOTES
v1.0
Based on https://github.com/lwhitelock/HuduAutomation/blob/main/CyberdrainRewrite/Hudu-ADDS-Documentation.ps1
.COMPONENT
Hudu Documentation
.ROLE
Documentation
#>
param (
[string] $ClientName,
[string] $HuduBaseDomain,
[string] $HuduApiKey
)
if (!$ClientName) {
write-output "Must provide -ClientName with a valid value that is identical to the name of a Company that exists in your Hudu instance. This should be the {{client.name}} value. `n"
$ErrorCount += 1
}
if (!$HuduBaseDomain) {
write-output "Must provide -HuduBaseUrl and it must a FQDN that maps to your Hudu instance without a trailing slash. `n"
$ErrorCount += 1
}
if (!$HuduApiKey) {
write-output "Must provide -HuduApiKey with a valid value from your Hudu instance. `n"
$ErrorCount += 1
}
if (!$ErrorCount -eq 0) {
exit 1
}
#####################################################################
#
# Active Directory Details to Hudu
#
# Get a Hudu API Key from https://yourhududomain.com/admin/api_keys
# Set the base domain of your Hudu instance without a trailing /
# Client Name as it appears in Hudu
$HuduAssetLayoutName = "Active Directory - AutoDoc"
#####################################################################
Write-Host "Connecting to $HuduBaseDomain"
#Get the Hudu API Module if not installed
if (Get-Module -ListAvailable -Name HuduAPI) {
Import-Module HuduAPI
} else {
Install-Module HuduAPI -Force
Import-Module HuduAPI
}
#Set Hudu logon information
New-HuduAPIKey $HuduAPIKey
New-HuduBaseUrl $HuduBaseDomain
function Get-WinADForestInformation {
$Data = @{ }
$ForestInformation = $(Get-ADForest)
$Data.Forest = $ForestInformation
$Data.RootDSE = $(Get-ADRootDSE -Properties *)
$Data.ForestName = $ForestInformation.Name
$Data.ForestNameDN = $Data.RootDSE.defaultNamingContext
$Data.Domains = $ForestInformation.Domains
$Data.ForestInformation = @{
'Name' = $ForestInformation.Name
'Root Domain' = $ForestInformation.RootDomain
'Forest Functional Level' = $ForestInformation.ForestMode
'Domains Count' = ($ForestInformation.Domains).Count
'Sites Count' = ($ForestInformation.Sites).Count
'Domains' = ($ForestInformation.Domains) -join ", "
'Sites' = ($ForestInformation.Sites) -join ", "
}
$Data.UPNSuffixes = Invoke-Command -ScriptBlock {
$UPNSuffixList = [PSCustomObject] @{
"Primary UPN" = $ForestInformation.RootDomain
"UPN Suffixes" = $ForestInformation.UPNSuffixes -join ","
}
return $UPNSuffixList
}
$Data.GlobalCatalogs = $ForestInformation.GlobalCatalogs
$Data.SPNSuffixes = $ForestInformation.SPNSuffixes
$Data.Sites = Invoke-Command -ScriptBlock {
$Sites = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites
$SiteData = foreach ($Site in $Sites) {
[PSCustomObject] @{
"Site Name" = $site.Name
"Subnets" = ($site.Subnets) -join ", "
"Servers" = ($Site.Servers) -join ", "
}
}
Return $SiteData
}
$Data.FSMO = Invoke-Command -ScriptBlock {
[PSCustomObject] @{
"Domain" = $ForestInformation.RootDomain
"Role" = 'Domain Naming Master'
"Holder" = $ForestInformation.DomainNamingMaster
}
[PSCustomObject] @{
"Domain" = $ForestInformation.RootDomain
"Role" = 'Schema Master'
"Holder" = $ForestInformation.SchemaMaster
}
foreach ($Domain in $ForestInformation.Domains) {
$DomainFSMO = Get-ADDomain $Domain | Select-Object PDCEmulator, RIDMaster, InfrastructureMaster
[PSCustomObject] @{
"Domain" = $Domain
"Role" = 'PDC Emulator'
"Holder" = $DomainFSMO.PDCEmulator
}
[PSCustomObject] @{
"Domain" = $Domain
"Role" = 'Infrastructure Master'
"Holder" = $DomainFSMO.InfrastructureMaster
}
[PSCustomObject] @{
"Domain" = $Domain
"Role" = 'RID Master'
"Holder" = $DomainFSMO.RIDMaster
}
}
Return $FSMO
}
$Data.OptionalFeatures = Invoke-Command -ScriptBlock {
$OptionalFeatures = $(Get-ADOptionalFeature -Filter * )
$Optional = @{
'Recycle Bin Enabled' = ''
'Privileged Access Management Feature Enabled' = ''
}
### Fix Optional Features
foreach ($Feature in $OptionalFeatures) {
if ($Feature.Name -eq 'Recycle Bin Feature') {
if ("$($Feature.EnabledScopes)" -eq '') {
$Optional.'Recycle Bin Enabled' = $False
}
else {
$Optional.'Recycle Bin Enabled' = $True
}
}
if ($Feature.Name -eq 'Privileged Access Management Feature') {
if ("$($Feature.EnabledScopes)" -eq '') {
$Optional.'Privileged Access Management Feature Enabled' = $False
}
else {
$Optional.'Privileged Access Management Feature Enabled' = $True
}
}
}
return $Optional
### Fix optional features
}
return $Data
}
$TableHeader = "<table style=`"width: 100%; border-collapse: collapse; border: 1px solid black;`">"
$Whitespace = "<br/>"
$TableStyling = "<th>", "<th style=`"background-color:#00adef; border: 1px solid black;`">"
$RawAD = Get-WinADForestInformation
$ForestRawInfo = new-object PSCustomObject -property $RawAD.ForestInformation | convertto-html -Fragment | Select-Object -Skip 1
$ForestNice = $TableHeader + ($ForestRawInfo -replace $TableStyling) + $Whitespace
$SiteRawInfo = $RawAD.Sites | Select-Object 'Site Name', Servers, Subnets | ConvertTo-Html -Fragment | Select-Object -Skip 1
$SiteNice = $TableHeader + ($SiteRawInfo -replace $TableStyling) + $Whitespace
$OptionalRawFeatures = new-object PSCustomObject -property $RawAD.OptionalFeatures | convertto-html -Fragment | Select-Object -Skip 1
$OptionalNice = $TableHeader + ($OptionalRawFeatures -replace $TableStyling) + $Whitespace
$UPNRawFeatures = $RawAD.UPNSuffixes | convertto-html -Fragment -as list| Select-Object -Skip 1
$UPNNice = $TableHeader + ($UPNRawFeatures -replace $TableStyling) + $Whitespace
$DCRawFeatures = $RawAD.GlobalCatalogs | ForEach-Object { Add-Member -InputObject $_ -Type NoteProperty -Name "Domain Controller" -Value $_; $_ } | convertto-html -Fragment | Select-Object -Skip 1
$DCNice = $TableHeader + ($DCRawFeatures -replace $TableStyling) + $Whitespace
$FSMORawFeatures = $RawAD.FSMO | convertto-html -Fragment | Select-Object -Skip 1
$FSMONice = $TableHeader + ($FSMORawFeatures -replace $TableStyling) + $Whitespace
$ForestFunctionalLevel = $RawAD.RootDSE.forestFunctionality
$DomainFunctionalLevel = $RawAD.RootDSE.domainFunctionality
$domaincontrollerMaxLevel = $RawAD.RootDSE.domainControllerFunctionality
$passwordpolicyraw = Get-ADDefaultDomainPasswordPolicy | Select-Object ComplexityEnabled, PasswordHistoryCount, LockoutDuration, LockoutThreshold, MaxPasswordAge, MinPasswordAge | convertto-html -Fragment -As List | Select-Object -skip 1
$passwordpolicyheader = "<tr><th><b>Policy</b></th><th><b>Setting</b></th></tr>"
$passwordpolicyNice = $TableHeader + ($passwordpolicyheader -replace $TableStyling) + ($passwordpolicyraw -replace $TableStyling) + $Whitespace
$adminsraw = Get-ADGroupMember "Domain Admins" | Select-Object SamAccountName, Name | convertto-html -Fragment | Select-Object -Skip 1
$adminsnice = $TableHeader + ($adminsraw -replace $TableStyling) + $Whitespace
$EnabledUsers = (Get-AdUser -filter * | Where-Object { $_.enabled -eq $true }).count
$DisabledUSers = (Get-AdUser -filter * | Where-Object { $_.enabled -eq $false }).count
$AdminUsers = (Get-ADGroupMember -Identity "Domain Admins").count
$Users = @"
There are <b> $EnabledUsers </b> users Enabled<br>
There are <b> $DisabledUSers </b> users Disabled<br>
There are <b> $AdminUsers </b> Domain Administrator users<br>
"@
# Setup the fields for the Asset
$AssetFields = @{
'domain_name' = $RawAD.ForestName
'forest_summary' = $ForestNice
'site_summary' = $SiteNice
'domain_controllers' = $DCNice
'fsmo_roles' = $FSMONice
'optional_features' = $OptionalNice
'upn_suffixes' = $UPNNice
'default_password_policies' = $passwordpolicyNice
'domain_admins' = $adminsnice
'user_count' = $Users
}
# Checking if the FlexibleAsset exists. If not, create a new one.
$Layout = Get-HuduAssetLayouts -name $HuduAssetLayoutName
if (!$Layout) {
$AssetLayoutFields = @(
@{
label = 'Domain Name'
field_type = 'Text'
show_in_list = 'true'
position = 1
},
@{
label = 'Forest Summary'
field_type = 'RichText'
show_in_list = 'false'
position = 2
},
@{
label = 'Site Summary'
field_type = 'RichText'
show_in_list = 'false'
position = 3
},
@{
label = 'Domain Controllers'
field_type = 'RichText'
show_in_list = 'false'
position = 4
},
@{
label = 'FSMO Roles'
field_type = 'RichText'
show_in_list = 'false'
position = 5
},
@{
label = 'Optional Features'
field_type = 'RichText'
show_in_list = 'false'
position = 6
},
@{
label = 'UPN Suffixes'
field_type = 'RichText'
show_in_list = 'false'
position = 7
},
@{
label = 'Default Password Policies'
field_type = 'RichText'
show_in_list = 'false'
position = 8
},
@{
label = 'Domain Admins'
field_type = 'RichText'
show_in_list = 'false'
position = 9
},
@{
label = 'User Count'
field_type = 'RichText'
show_in_list = 'false'
position = 10
}
)
Write-Host "Creating New Asset Layout"
$NewLayout = New-HuduAssetLayout -name $HuduAssetLayoutName -icon "fas fa-sitemap" -color "#00adef" -icon_color "#000000" -include_passwords $false -include_photos $false -include_comments $false -include_files $false -fields $AssetLayoutFields
$Layout = Get-HuduAssetLayouts -name $HuduAssetLayoutName
}
$Company = Get-HuduCompanies -name $ClientName
if ($company) {
#Upload data to Hudu
$Asset = Get-HuduAssets -name $RawAD.ForestName -companyid $company.id -assetlayoutid $layout.id
#If the Asset does not exist, we edit the body to be in the form of a new asset, if not, we just upload.
if (!$Asset) {
Write-Host "New Asset Created"
$Asset = New-HuduAsset -name $RawAD.ForestName -company_id $company.id -asset_layout_id $layout.id -fields $AssetFields
}
else {
Write-Host "Asset has been Updated"
$Asset = Set-HuduAsset -asset_id $Asset.id -name $RawAD.ForestName -company_id $company.id -asset_layout_id $layout.id -fields $AssetFields
}
} else {
Write-Host "$ClientName was not found in Hudu"
}