From f6f606512b2d3ac79451786309fe6d357052167b Mon Sep 17 00:00:00 2001 From: Zack Mutchler <30831476+thezackm@users.noreply.github.com> Date: Thu, 15 Jun 2023 06:39:12 -0500 Subject: [PATCH 1/2] feat/ad examples (#435) * feat: add ad health checks and gpo scripts * Setting user email --- .../windows/windows-active-directory-gpos.ps1 | 59 ++++++++++++++++ .../windows/windows-active-directory-gpos.yml | 13 ++++ ...windows-active-directory-health-checks.ps1 | 67 +++++++++++++++++++ ...windows-active-directory-health-checks.yml | 23 +++++++ 4 files changed, 162 insertions(+) create mode 100644 examples/windows/windows-active-directory-gpos.ps1 create mode 100644 examples/windows/windows-active-directory-gpos.yml create mode 100644 examples/windows/windows-active-directory-health-checks.ps1 create mode 100644 examples/windows/windows-active-directory-health-checks.yml diff --git a/examples/windows/windows-active-directory-gpos.ps1 b/examples/windows/windows-active-directory-gpos.ps1 new file mode 100644 index 00000000..bc9603e1 --- /dev/null +++ b/examples/windows/windows-active-directory-gpos.ps1 @@ -0,0 +1,59 @@ + #region Top of Script + +#requires -version 4 +#requires -Module ActiveDirectory + +<# +.SYNOPSIS + Queries Active Directory for all GPOs +.DESCRIPTION + This script uses a static list of queries +.NOTES + Version: 1.0 + Author: Zack Mutchler + Creation Date: 9-May-2023 + Purpose/Change: Initial script development +#> + +#endregion Top of Script + +#####-----------------------------------------------------------------------------------------##### + +#region Execution + +$gpos = Get-GPO -All + +# Build an empty array to add our results to +$results = @() + +# Iterate through our GPO checks and grab the results +foreach( $g in $gpos ){ + + # Run a GPO Report to get the link status + $gpoReport = [xml](Get-GPOReport -Guid $g.id -ReportType xml) | Select-Object -ExpandProperty GPO + + # Build a custom object to pass into the results + $item = @( + + [ PSCustomObject ]@{ + + gpoName = $g.DisplayName + gpoDomain = $g.DomainName + gpoStatus = $g.GpoStatus.ToString() + gpoCreated = ( [DateTimeOffset ]$g.CreationTime ).ToUnixTimeSeconds() + gpoLastModified = ( [DateTimeOffset ]$g.ModificationTime ).ToUnixTimeSeconds() + gpoEnabled = if ( $gpoReport.LinksTo ) { $gpoReport | Select-Object -ExpandProperty LinksTo | Select-Object -ExpandProperty Enabled } else { "false" } + gpoLinkedFrom = if ( $gpoReport.LinksTo ) { $gpoReport | Select-Object -ExpandProperty LinksTo | Select-Object -ExpandProperty SOMPath } else { "none" } + + } + + ) + + $results += $item + +} + +# Print the results to STDOUT in JSON for Flex to pickup +$results | ConvertTo-Json + +#endregion Execution diff --git a/examples/windows/windows-active-directory-gpos.yml b/examples/windows/windows-active-directory-gpos.yml new file mode 100644 index 00000000..568270f4 --- /dev/null +++ b/examples/windows/windows-active-directory-gpos.yml @@ -0,0 +1,13 @@ +# This executes an external PowerShell script that inventories all Active Directory Group Policy Objects. +--- +integrations: + - name: nri-flex + interval: 300s + config: + name: activeDirectoryGPOStatus + apis: + - event_type: activeDirectoryGPOs + shell: powershell + timeout: 299000 + commands: + - run: "& \"C:/Program Files/New Relic/newrelic-infra/integrations.d/windows-active-directory-gpos.ps1\"" diff --git a/examples/windows/windows-active-directory-health-checks.ps1 b/examples/windows/windows-active-directory-health-checks.ps1 new file mode 100644 index 00000000..52f0e12e --- /dev/null +++ b/examples/windows/windows-active-directory-health-checks.ps1 @@ -0,0 +1,67 @@ + #region Top of Script + +#requires -version 4 +#requires -Module ActiveDirectory + +<# +.SYNOPSIS + Queries for target Active Directory health statistics +.DESCRIPTION + This script uses a static list of queries +.NOTES + Version: 1.0 + Author: Zack Mutchler + Creation Date: 13-Mar-2023 + Purpose/Change: Initial script development + + Version: 1.1 + Author: Zack Mutchler + Creation Date: 9-May-2023 + Purpose/Change: Remove GPO queries and setup for filtered AD OU search +#> + +#endregion Top of Script + +#####-----------------------------------------------------------------------------------------##### + +#region Script Parameters + +Param( + + [ Parameter( Mandatory = $true ) ] [ValidateNotNullOrEmpty() ] [ string ] $OU + +) + +#endregion Script Parameters + +#region Execution + +# Build an empty PSObject to add our results to +$results = New-Object -TypeName PSCustomObject + +# Iterate through our health checks, adding the results to our custom object + # Add the OU Distinguished Name + $results | Add-Member -MemberType NoteProperty -Name "ouDistinguishedName" -Value $OU + # Inactive Accounts + $results | Add-Member -MemberType NoteProperty -Name "adInactiveAccounts" -Value (Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 365 -SearchBase $OU | Where-Object {$_.enabled -eq $true -and $_.lockedOut -eq $false -and $_.distinguishedname -notlike "*Microsoft Exchange System Objects*"}).count + # Expired Accounts + $results | Add-Member -MemberType NoteProperty -Name "adExpiredAccounts" -Value (Search-ADAccount -UsersOnly -AccountExpired -SearchBase $OU | Where-Object {$_.distinguishedname -notlike "*Microsoft Exchange System Objects*"}).count + # Locked Accounts + $results | Add-Member -MemberType NoteProperty -Name "adLockedAccounts" -Value (Search-ADAccount -UsersOnly -LockedOut -SearchBase $OU | Where-Object {$_.distinguishedname -notlike "*Microsoft Exchange System Objects*"}).count + # Disabled Accounts + $results | Add-Member -MemberType NoteProperty -Name "adDisabledAccounts" -Value (Search-ADAccount -UsersOnly -AccountDisabled -SearchBase $OU | Where-Object{$_.distinguishedname -notlike "*Microsoft Exchange System Objects*"}).count + # Passwords have expired + $results | Add-Member -MemberType NoteProperty -Name "adExpiredPasswords" -Value (Search-ADAccount -UsersOnly -PasswordExpired -SearchBase $OU | Where-Object{$_.distinguishedname -notlike "*Microsoft Exchange System Objects*"}).count + # Passwords that never expire + $results | Add-Member -MemberType NoteProperty -Name "adPasswordsThatNeverExpire" -Value (Search-ADAccount -UsersOnly -PasswordNeverExpires -SearchBase $OU | Where-Object{$_.distinguishedname -notlike "*Microsoft Exchange System Objects*"}).count + # Disabled Computers + $results | Add-Member -MemberType NoteProperty -Name "adDisabledComputers" -Value (Search-ADAccount -ComputersOnly -AccountDisabled -SearchBase $OU).count + # Is this OU empty? true|false + $results | Add-Member -MemberType NoteProperty -Name "adEmptyOrganizationalUnit" -Value ((-not (Get-ADOrganizationalUnit -SearchBase $OU -Filter * -SearchScope OneLevel)) -or ((Get-ADOrganizationalUnit -SearchBase $OU -Filter * -SearchScope OneLevel).Count -eq 0)) + # Empty Groups + $results | Add-Member -MemberType NoteProperty -Name "adEmptyGroups" -Value (Get-ADGroup -Filter * -SearchBase $OU -Properties Members | Where-Object {-not $_.members -and $_.distinguishedname -notlike "*deploy*" -and $_.distinguishedname -notlike "*Builtin*" -and $_.distinguishedname -notlike "*CN=Users*"}).count + +# Print the results to STDOUT in JSON for Flex to pickup +$results | ConvertTo-Json + +#endregion Execution diff --git a/examples/windows/windows-active-directory-health-checks.yml b/examples/windows/windows-active-directory-health-checks.yml new file mode 100644 index 00000000..f62e4c96 --- /dev/null +++ b/examples/windows/windows-active-directory-health-checks.yml @@ -0,0 +1,23 @@ +# This executes an external PowerShell script that measures multiple Active Directory health metrics. +--- +integrations: + - name: nri-flex + interval: 300s + config: + name: activeDirectoryHealthChecks + apis: + - event_type: activeDirectoryOUSearch + ignore_output: true + shell: powershell + timeout: 119000 + commands: + # Edit this line to target specific OUs; you can use a variety of options like -Filter, -Identity, and -LDAPFilter + # https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-adorganizationalunit?view=windowsserver2022-ps + - run: Get-ADOrganizationalUnit -Filter 'Name -like "*_division*"' | Select-Object DistinguishedName | ConvertTo-Json + + - event_type: activeDirectoryHealthChecks + shell: powershell + timeout: 179000 + commands: + # This is using the results of the above command to loop through as parameters for the health check script + - run: "& \"C:/Program Files/New Relic/newrelic-infra/integrations.d/windows-active-directory-health-checks.ps1\" -OU \"${lookup.activeDirectoryOUSearch:DistinguishedName}\"" From 76a7e9847110c6e316fce2c2f160a41d00fa0ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Tue, 27 Jun 2023 09:27:29 +0100 Subject: [PATCH 2/2] chore: bump Go patch version (#438) --- docker-compose.yml | 2 +- scripts/docker-compose-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e77596d6..0ca43c29 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3" services: golang: - image: golang:1.19.8-bullseye + image: golang:1.19.10-bullseye volumes: - .:/go/src/github.com/newrelic/nri-flex working_dir: /go/src/github.com/newrelic/nri-flex diff --git a/scripts/docker-compose-build.yml b/scripts/docker-compose-build.yml index 3cd10878..718ace62 100644 --- a/scripts/docker-compose-build.yml +++ b/scripts/docker-compose-build.yml @@ -1,7 +1,7 @@ version: "3" services: golang: - image: golang:1.19.8-bullseye + image: golang:1.19.10-bullseye volumes: - ../:/go/src/github.com/newrelic/nri-flex working_dir: /go/src/github.com/newrelic/nri-flex