Compare commits

...

109 Commits

Author SHA1 Message Date
Przemyslaw Klys ebecd56dff Bump version 2021-11-02 11:52:00 +01:00
Przemyslaw Klys d5700d873a Update changelog 2021-11-02 11:51:26 +01:00
Przemyslaw Klys 89c216bb55 Should be 7 days 2021-11-02 11:50:52 +01:00
Przemyslaw Klys fe2ff87120 Version bump 2021-11-02 11:12:33 +01:00
Przemyslaw Klys 0c756b6f0d Update changelog 2021-11-02 11:12:22 +01:00
Przemyslaw Klys 3dc5dc7be4 File rename, fix of condition 2021-11-02 11:11:02 +01:00
Przemyslaw Klys d75172e6b1 Version bump 2021-10-24 16:10:56 +02:00
Przemyslaw Klys ee12a4f619 Update readme 2021-10-24 16:08:02 +02:00
Przemyslaw Klys c96c8285bf Added example 2021-10-24 16:01:47 +02:00
Przemyslaw Klys 8c3ed61142 added new date ranges 2021-10-24 16:01:19 +02:00
Przemyslaw Klys 2934acafeb Improved report 2021-10-24 16:01:07 +02:00
Przemyslaw Klys 7203b7f544 Added additional dates 2021-10-24 16:00:59 +02:00
Przemyslaw Klys d22e79b657 Added date filtering 2021-10-24 16:00:50 +02:00
Przemyslaw Klys e07c2dae9a Update readme 2021-10-24 16:00:20 +02:00
Przemyslaw Klys 8b1b225ce1 Updated changelog/moved out of readme 2021-10-24 16:00:12 +02:00
Przemyslaw Klys 1a54d62b2e Fix example 2021-10-24 15:46:20 +02:00
Przemyslaw Klys 352ddc18f3 added report 2021-10-24 15:32:36 +02:00
Przemyslaw Klys 017007d8c9 Added gpozaurr updates report 2021-10-24 15:32:20 +02:00
Przemyslaw Klys 4803d3e183 Improvements 2021-10-24 14:51:19 +02:00
Przemyslaw Klys 92fcb80005 Update example 2021-10-22 12:17:16 +02:00
Przemyslaw Klys 4985a114dc Added example 2021-10-22 12:16:39 +02:00
Przemyslaw Klys 3ad4a92c66 Small improvement to prevent detection of domain errors 2021-10-22 12:15:42 +02:00
Przemyslaw Klys e78db61695 Version bump 2021-10-19 17:09:41 +02:00
Przemyslaw Klys 781e95d042 Adding verbose messages 2021-10-19 17:07:36 +02:00
Przemyslaw Klys 4e1f35f433 Version bump 2021-10-18 08:34:47 +02:00
Przemyslaw Klys 74eb14753e Fix when GPO is not linked 2021-10-18 08:33:42 +02:00
Przemyslaw Klys 1a7bb0273f Update changelog 2021-10-17 17:59:29 +02:00
Przemyslaw Klys 65eea07b6f Version bump 2021-10-17 15:08:48 +02:00
Przemyslaw Klys fe917d70b0 Support for new version of ADEssentials 2021-10-17 15:08:25 +02:00
Przemyslaw Klys 9786186a59 Added new function 2021-10-17 14:56:08 +02:00
Przemyslaw Klys b6fc7a676b Internal function 2021-10-17 14:55:59 +02:00
Przemyslaw Klys 46e6815314 internal function to find dates 2021-10-17 14:55:38 +02:00
Przemyslaw Klys b3e9ddeb64 New function, for now internal use 2021-10-17 14:55:27 +02:00
Przemyslaw Klys e5f67d8f2e Update changelog 2021-10-17 14:55:14 +02:00
Przemyslaw Klys 24f81647fa Version bump 2021-10-17 14:55:06 +02:00
Przemyslaw Klys cdeb2b4a2d Added search by dates 2021-10-17 14:54:54 +02:00
Przemyslaw Klys f7cf18500d Version bump 2021-08-24 18:32:48 +02:00
Przemyslaw Klys 1becfbca60 Added changelog entry 2021-08-24 18:32:11 +02:00
Przemysław Kłys 82c21edcc2 Merge pull request #24 from PatrickOnGit/FolderRedirectionType
Added folder redirection type
2021-08-24 18:30:23 +02:00
Przemyslaw Klys e56cf3bde3 Moved ID, added ID to SingleObject 2021-08-24 18:29:11 +02:00
patrick-sczepanski 996139ab4a Added folder redirection type 2021-08-23 11:12:56 +02:00
Przemyslaw Klys 5590e3bf31 Version bump 2021-08-19 11:25:19 +02:00
Przemyslaw Klys 9db54b338b Changelog update 2021-08-19 11:25:12 +02:00
Przemyslaw Klys e79d95c0fd Added root level 2021-08-19 11:24:22 +02:00
Przemyslaw Klys 8c1f95b1b8 Version bump 2021-08-18 19:44:21 +02:00
Przemyslaw Klys 4d9f1e7fba Changelog update 2021-08-18 19:44:13 +02:00
Przemyslaw Klys 88fb1651a9 Fix for exclusions using GUID with brackets 2021-08-18 19:42:57 +02:00
Przemyslaw Klys 9696fb0cab Update example 2021-08-17 10:20:50 +02:00
Przemyslaw Klys bb77785ea8 Update example 2021-08-17 10:20:30 +02:00
Przemyslaw Klys 168919d7d9 BUmp new version 2021-08-17 10:20:06 +02:00
Przemyslaw Klys 5effe5face Make delete OU non-mandatatory 2021-08-17 10:19:57 +02:00
Przemyslaw Klys 6d15363caa bump version 2021-08-17 10:14:22 +02:00
Przemyslaw Klys 6c62a11767 Updated wording 2021-08-17 10:13:46 +02:00
Przemyslaw Klys 61bfe5bd4d Bump version, new release 2021-08-17 08:51:22 +02:00
Przemyslaw Klys 5043767e8d Small adjustment of texts 2021-08-17 08:50:42 +02:00
Przemyslaw Klys e4ecafaea5 Improvements to GPOList to not trigger require changes when excluding GPOs 2021-08-17 08:50:28 +02:00
Przemyslaw Klys 154e3428e6 More changes 2021-08-16 16:39:41 +02:00
Przemyslaw Klys a6c2ac1226 Version bump 2021-08-16 16:21:12 +02:00
Przemyslaw Klys 2b0a395abc Small improvement 2021-08-16 16:20:35 +02:00
Przemyslaw Klys 04b7242bde Version bump 2021-08-16 12:02:24 +02:00
Przemyslaw Klys 48af562bfd Changelog update 2021-08-16 12:01:57 +02:00
Przemyslaw Klys a5d447b28c Improvements to exclusions 2021-08-16 12:01:39 +02:00
Przemyslaw Klys e649a489bc Updated changelog 2021-08-16 09:49:42 +02:00
Przemyslaw Klys bf3cfb8d21 Version bump 2021-08-16 09:49:08 +02:00
Przemyslaw Klys f250453536 Improved exclusions for email use 2021-08-16 09:48:45 +02:00
Przemyslaw Klys 34902ab6d8 Removed dead code 2021-08-16 09:48:03 +02:00
Przemyslaw Klys ddaadf56a3 Version bump 2021-08-13 12:32:07 +02:00
Przemyslaw Klys 25805e5199 Example improvement 2021-08-13 12:31:29 +02:00
Przemyslaw Klys e0fe437e1e Small exclusion improvement 2021-08-13 12:25:38 +02:00
Przemyslaw Klys c282fcc784 Exclusions improvement 2021-08-13 12:25:28 +02:00
Przemyslaw Klys a8f496190d support for guid exclusion 2021-08-13 12:25:14 +02:00
Przemyslaw Klys 4f41a98e89 changelog update 2021-08-13 12:25:01 +02:00
Przemyslaw Klys 010c4dc8e0 Handling of scriptblock added 2021-08-13 12:24:51 +02:00
Przemyslaw Klys db57b9ee22 Update readme changelog 2021-08-12 09:37:02 +02:00
Przemyslaw Klys b7315b0fa5 Changelog update 2021-08-10 21:05:20 +02:00
Przemyslaw Klys 8b9c9e66b8 Removed SearchBuilder option 2021-08-10 21:05:13 +02:00
Przemyslaw Klys 5a2f789321 Update example showing exclusions 2021-08-10 20:57:38 +02:00
Przemyslaw Klys b3023051f3 display additional column in example 2021-08-10 20:57:27 +02:00
Przemyslaw Klys 9538facc13 Update example showing exclusions 2021-08-10 20:57:02 +02:00
Przemyslaw Klys 7c914d8134 Version bump 2021-08-10 20:56:37 +02:00
Przemyslaw Klys 90f951d995 Update example showing exclusions 2021-08-10 20:56:30 +02:00
Przemyslaw Klys b2db6d5662 Update changelog 2021-08-10 20:56:01 +02:00
Przemyslaw Klys cafd3f7938 Added exclusions/approved owners 2021-08-10 20:50:22 +02:00
Przemyslaw Klys ba81950eed Added exclusions/approved owners 2021-08-10 20:50:18 +02:00
Przemyslaw Klys 810ef18baa Adds ability for exclusions/approved Owners 2021-08-10 20:49:47 +02:00
Przemyslaw Klys dbf99debee Added help information 2021-08-10 16:12:20 +02:00
Przemyslaw Klys 4cd644d1b4 Added exclusions 2021-08-10 16:12:10 +02:00
Przemyslaw Klys e2aa7af83d Added exclusions 2021-08-10 16:12:02 +02:00
Przemyslaw Klys ff1668c60d Function that generates exclusions 2021-08-10 16:11:51 +02:00
Przemyslaw Klys 5f82bbaea4 Added exclusions to report 2021-08-10 16:11:41 +02:00
Przemyslaw Klys 75cee65b65 Added exclusions to report 2021-08-10 16:11:35 +02:00
Przemyslaw Klys 0dc56d314e Example improvement 2021-08-10 16:11:17 +02:00
Przemyslaw Klys 9c689708ba Report improvement 2021-08-06 11:36:30 +02:00
Przemyslaw Klys bb18d488b4 Example improvements 2021-08-06 11:36:22 +02:00
Przemyslaw Klys e72d81aee3 Example update 2021-08-05 23:56:35 +02:00
Przemyslaw Klys 70ed52cdf9 Improvement to report 2021-08-05 23:56:27 +02:00
Przemyslaw Klys 3b414e712c Example update 2021-08-05 23:33:35 +02:00
Przemyslaw Klys 7ed1410fd9 Parameter sets update 2021-08-05 23:26:07 +02:00
Przemyslaw Klys 6d2e476916 Changelog update 2021-08-05 23:26:00 +02:00
Przemyslaw Klys b7ed5e0c5a Added examples for new functions 2021-08-05 22:13:56 +02:00
Przemyslaw Klys 72bd69d0e6 Update changelog 2021-08-05 22:09:28 +02:00
Przemyslaw Klys b5c1f3dcd5 Improved Get-GPOZaurrOrganizationalUnit 2021-08-05 22:09:09 +02:00
Przemyslaw Klys bc773e2e83 Added Remove-GPOZaurrLinkEmptyOU 2021-08-05 22:08:56 +02:00
Przemyslaw Klys 8db961cba6 Improve report 2021-08-05 22:08:46 +02:00
Przemyslaw Klys 227639d0f6 New functions added in psd1 2021-08-05 22:08:22 +02:00
Przemyslaw Klys e03f819461 Update PSD1 2021-08-03 19:41:38 +02:00
Przemyslaw Klys fb955f645b Add changelog 2021-08-03 19:41:30 +02:00
Przemyslaw Klys 3fc3b74798 Added Get-GPOZaurrOrganizationalUnit 2021-08-03 19:40:41 +02:00
Przemyslaw Klys 695f4dbe6a Twitter complainer 2021-07-08 20:16:01 +02:00
51 changed files with 2100 additions and 594 deletions
+485
View File
@@ -0,0 +1,485 @@
# GPOZaurr Release History
## 0.0.146 - 2021.11.02
- Improves `GPOUpdates` report from `Invoke-GPOZaurr` - should be 7 days, not 14 days
## 0.0.145 - 2021.11.02
- Improves `GPOUpdates` report from `Invoke-GPOZaurr` by fixing conditional formatting
## 0.0.144 - 2021.10.24
- Improves `Get-GPOZaurrUpdates`
- Adds `GPOUpdates` report to `Invoke-GPOZaurr`
## 0.0.143 - 2021.10.19
- Improves `Get-GPOZaurrUpdates` with more verbose messages
## 0.0.142 - 2021.10.18
- Fixes `Get-GPOZaurrUpdates` when GPO is not linked
## 0.0.141 - 2021.10.17
- Removed property from `Get-GPOZaurrAD` - `FunctionalityVersion`
- Added property to `Get-GPOZaurrAD` - `Owner`
- Added ability to choose date ranges for `Get-GPOZaurrAD`
- Added `Get-GPOZaurrUpdates` which shows last gpos added to forest
## 0.0.140 - 2021.08.24
- ☑ Improved `Invoke-GPOZaurr` - type `GPOAnalysis` - added folder redirection type - [tnx PatrickOnGit](https://github.com/EvotecIT/GPOZaurr/pull/24)
## 0.0.139 - 2021.08.19
- ☑ Improved `Invoke-GPOZaurr` - type `GPOOrganizationalUnit` - adding RootLevel information
## 0.0.138 - 2021.08.18
- 🐛 Fix for exclusions using GUID with brackets for Invoke-GPOZaurr `GPOList` and related options
## 0.0.137 - 2021.08.17
- ☑ Improved `Invoke-GPOZaurr` - type `GPOOrganizationalUnit` - moving delete of OU as non-mandatory option
## 0.0.136 - 2021.08.17
- ☑ Improved wording
## 0.0.135 - 2021.08.17
- ☑ Improved exclusions
## 0.0.134 - 2021.08.16
- ☑ Improved exclusions for email use
## 0.0.133 - 2021.08.16
- ☑ Improved exclusions for email use
## 0.0.132 - 2021.08.16
- ☑ Improved exclusions for email use
## 0.0.131 - 2021.08.16
- ☑ Improved exclusions for email use
## 0.0.130 - 2021.08.13
- 💡 Updated HTML to new version of `PSWriteHTML` that fixes complains about `SearchBuilder` option
- ☑ Improved `Invoke-GPOZaurr` - type `GPOOrganizationalUnit` with exclusions
```powershell
Invoke-GPOZaurr -Type GPOOrganizationalUnit -Online -FilePath $PSScriptRoot\Reports\GPOZaurrOU.html -Exclusions @(
'*OU=Production,DC=ad,DC=evotec,DC=pl'
'*OU=Production,DC=ad,DC=evotec,DC=pl'
'*DC=ad,DC=evotec,DC=pl'
)
```
- ☑ Improved `Get-GPOZaurrOrganizationalUnit` with exclusions
```powershell
Get-GPOZaurrOrganizationalUnit -Verbose -ExcludeOrganizationalUnit @(
'*,OU=Production,DC=ad,DC=evotec,DC=pl'
) | Format-Table
```
- ☑ Improved `Remove-GPOZaurrLinkEmptyOU` with exclusions
```powershell
$Exclude = @(
"OU=Groups,OU=Production,DC=ad,DC=evotec,DC=pl"
"OU=Test \, OU,OU=ITR02,DC=ad,DC=evotec,DC=xyz"
)
Remove-GPOZaurrLinkEmptyOU -Verbose -LimitProcessing 3 -WhatIf -ExcludeOrganizationalUnit $Exclude
```
- ☑ Improved `Invoke-GPOZaurr` - type `GPOOwners` with exclusions
```powershell
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurrGPOOwners.html -Type GPOOwners -Online -Exclusions @(
'EVOTEC\przemyslaw.klys'
)
```
- ☑ Improved `Set-GPOZaurrOwner` with exclusions/approved owners
```powershell
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -WhatIf -IncludeDomains 'ad.evotec.xyz' -ApprovedOwner @(
'EVOTEC\przemyslaw.klys'
)
```
- ☑ Improved `Get-GPOZaurrOwner` with exclusions/approved owners
```powershell
$T = Get-GPOZaurrOwner -Verbose -IncludeSysvol -ApprovedOwner @('EVOTEC\przemyslaw.klys')
$T | Format-Table *
```
- ☑ Improved `Get-GPOZaurr` with exclusions and support for GUID, strings
```powershell
$GPOS = Get-GPOZaurr -ExcludeGroupPolicies {
Skip-GroupPolicy -Name 'de14_usr_std'
Skip-GroupPolicy -Name 'de14_usr_std' -DomaiName 'ad.evotec.xyz'
Skip-GroupPolicy -Name 'All | Trusted Websites' #-DomaiName 'ad.evotec.xyz'
'{D39BF08A-87BF-4662-BFA0-E56240EBD5A2}'
'COMPUTERS | Enable Sets'
}
$GPOS | Format-Table -AutoSize *
```
- ☑ Improved `Invoke-GPOZaurr` with exclusions and support for GUID, strings
```powershell
Invoke-GPOZaurr -Type GPOList -Exclusions {
Skip-GroupPolicy -Name 'All | Trusted Websites' -DomaiName 'ad.evotec.xyz'
'{D39BF08A-87BF-4662-BFA0-E56240EBD5A2}'
'COMPUTERS | Enable Sets'
}
```
## 0.0.129 - 2021.08.06
- Added `Get-GPOZaurrOrganizationalUnit` and added `GPOOrganizationalUnit` in `Invoke-GPOZaurr` (preview)
- Added `Remove-GPOZaurrLinkEmptyOU` which allows removing links from Empty OUs (preview)
- Small update to parameter sets for `Set-GPOZaurrOwner`
## 0.0.128 - 2021.05.26
- ☑ Improved `Invoke-GPOZaurrContent` - type `PublicKeyPoliciesCertificates` - added more certificate information
- ☑ Improved `Invoke-GPOZaurr` - type `GPOAnalysis` - added more certificate information
## 0.0.128 Alpha 1 - 2021.05.17
- 🐛 Fixes errors when normalizing properties [#17](https://github.com/EvotecIT/GPOZaurr/issues/17)
## 0.0.127 - 2021.04.15
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOList` - moved description closer to statuses
- ☑ Improved `Get-GPOZaurr` - moved description closer to statuses
## 0.0.126 - 2021.04.12
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOBlockedInheritance` - hidden DistinguishedName, fixed some small typos
## 0.0.125 - 2021.04.11
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOBlockedInheritance` - small fixes
## 0.0.124 - 2021.04.11
- ☑ Added `SearchBuilder` to all tables
- ☑ Automatically joins arrays in tables in `Invoke-GPOZaurr`
- ☑ Improved `Get-GPOZaurrInheritance` with Exclusions and some help information
- ☑ Improved `Invoke-GPOZaurr` with some Exclusions
- ☑ Improved `Invoke-GPOZaurr`
- 🔥 Report `GPOBlockedInheritance` - heavily improved functionality and data
## 0.0.123 - 2021.03.21
- ☑ Fixes `Get-GPOZaurrLinkSummary`
## 0.0.122 - 2021.02.11
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOAnalysis` - added `WindowsFirewallRules`,`WindowsFirewallProfiles`,`WindowsFirewallConnectionSecurityAuthentication`,`WindowsFirewallConnectionSecurityRules`
- ☑ Improved `Invoke-GPOZaurrContent` as mentioned above for `GPOAnalysis`
## 0.0.121 - 2021.02.10
- ☑ Improvement to `Get-GPOZaurr` - added description [#13](https://github.com/EvotecIT/GPOZaurr/issues/13)
- ☑ Improvement to `Invoke-GPOZaurr -Type GPOList` - added description [#13](https://github.com/EvotecIT/GPOZaurr/issues/13)
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report GPOAnalysis - added `FolderRedirection`
- ☑ Report GPOAnalysis - renamed `FolderRedirection` to `FolderRedirectionPolicy`
- ☑ Improved `Invoke-GPOZaurrContent` as mentioned above for `GPOAnalysis`
## 0.0.120 - 2021.02.10
- ☑ Improvement to `Get-GPOZaurr` to warn if there is potential issue with EMPTY (which can happen on non-english system)
- ☑ In such case GPOZaurr will asses EMPTY or not using old method which doesn't detect all EMPTY cases but shouldn't provide false positives
## 0.0.119
- Broken release - weird
## 0.0.118 - 2021.02.09
- ☑ Added information where the report is saved
- ☑ Small improvement to `Get-GPOZaurr` to exlicitly define variable types
## 0.0.117 - 2021.02.09
- ☑ Small fix to `Get-GPOZaurr` to exclude GPOList.xml which is used in offline mode by `Save-GPOZaurrFiles`
## 0.0.116 - 2021.02.08
- ☑ Improved `Remove-GPOZaurrBroken` to handle ObjectClass problem, and removed reduntant check
## 0.0.115 - 2021.02.07
- ☑ Improved `Invoke-GPOZaurr`
- ☑ `GPOList` - clarified some texts, changed 7 days to 30 days as default
- ☑ `NetLogonPermissions` - fixed missing text
- ☑ Fixes `Get-GPOZaurrNetLogon` error on empty Owner - [#9](https://github.com/EvotecIT/GPOZaurr/issues/9)
## 0.0.114 - 2021.01.27
- ☑ Improved `Invoke-GPOZaurr`
- ☑ HTML now uses offline mode by default (no CDN) - increase in size of HTML up to 3MB
- ☑ Using Online switch forces use of CDN - smaller files. For example `Invoke-GPOZaurr -Type GPOList -Online`
- [ ] Improved `Invoke-GPOZaurrSupport`
- ☑ HTML now uses offline mode by default (no CDN) - increase in size of HTML up to 3MB
- ☑ Using Online switch forces use of CDN - smaller files. For example `Invoke-GPOZaurrSupport -Online`
- ☑ Removed parameter Offline, added parameter Online
- ☑ The cmdlet is not really production ready. It's work in progress
## 0.0.113 - 2021.01.25
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report GPOAnalysis - added WindowsTimeService
- ☑ Improved `Invoke-GPOZaurrContent`
- ☑ Added `WindowsTimeService` type
## 0.0.112 - 2021.01.25
- ☑ Improved `Invoke-GPOZaurr`
## 0.0.111 - 2021.01.24
- ☑ Improved `Invoke-GPOZaurr`
## 0.0.110 - 2021.01.22
- ☑ Improved `Invoke-GPOZaurr`
## 0.0.109 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurr`
## 0.0.108 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Improved `GPOConsistency`
## 0.0.107 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurr`
## 0.0.106 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurrContent`
## 0.0.105 - 2021.01.05
- ☑ Improved `Get-GPOZaurr`
- ☑ Improved report `GPOBrokenLink`
## 0.0.104 - 2021.01.04
- ☑ Improved `Get-GPOZaurrBrokenLink`
- ☑ Improved `Repair-GPOZaurrBrokenLink`
- ☑ Improved `Get-GPOZaurr`
- ☑ Improved report `GPOBrokenLink`
## 0.0.103 - 2021.01.04
- ☑ Improved `Get-GPOZaurr`
- ☑ Added new report `GPOBrokenLink`
- ☑ Added `Get-GPOZaurrBrokenLink`
- ☑ Added `Repair-GPOZaurrBrokenLink`
## 0.0.102 - 2021.01.02
- ☑ Improved `Get-GPOZaurrLink`
- ☑ Supports all links across forest
- ☑ Renamed Linked validate set from `Other` to `OrganizationalUnit`
- ☑ Improved `Get-GPOZaurrLinkSummary`
- ☑ Improved/BugFix `Get-GPOZaurr` to properly detect linked GPOs in sites/cross-domain
- ☑ Improved `Invoke-GPOZaurrPermission`
- ☑ Renamed Linked validate set from `Other` to `OrganizationalUnit`
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Added `GPOLinks` basic list
## 0.0.101 - 23.12.2020
- ☑ Improved `Get-GPOZaurrBroken`
- ☑ It now detects `ObjectClass Issue`
- ☑ Heavily improved performance
- ☑ Removed some useless properties for this particular cmdlet
- ☑ All states: `Not available on SYSVOL`, `Not available in AD`, `Exists`, `Permissions Issue`, `ObjectClass Issue`
- ☑ Improved help
- ☑ Improved `Remove-GPOZaurrBroken`
- ☑ It now deals with `ObjectClass Issue`
- ☑ Heavily improved performance
- ☑ Removed some useless properties for this particular cmdlet
- ☑ Now requires manual type insert AD, SYSVOL or ObjectClass (or all of them). Before it was auto using AD/SYSVOL.
- ☑ Improved help
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList`
- ☑ Renamed `GPOOrphans` to `GPOBroken`
- ☑ Improved `GPOBroken` with `ObjectClass issue`
## 0.0.100 - 21.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOPermissionsRead`
- ☑ Type `GPOPermissions`
## 0.0.99 - 13.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - require GPO to be 7 days old for deletion to be proposed
- ☑ Type `GPOPermissions` - one stop for permissions
- ☑ Allows Steps to be chosen via their menu and out-of-order
- ☑ Improved `Remove-GPOZaurr` - added `RequireDays` parameter to prevent deletion of just modified GPOs
- ☑ Added `Get-GPOZaurrPermissionAnalysis`
- ☑ Added `Repair-GPOZaurrPermission`
## 0.0.98 - 10.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - fixed unexpected ending of cmdlet when error occurs (for example deleted GPO while script is running) which could impact results
- ☑ Other types - small color adjustment
- ☑ Fixed/Improved `Get-GPOZaurr` - fixed unexpected ending of cmdlet when error occurs (for example deleted GPO while script is running), improved code base
- ☑ Improved `Invoke-GPOZaurrSupport`
## 0.0.97 - 07.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - added more data, did small reorganization
## 0.0.96 - 07.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - added more data, added Optimization Step
- ☑ Added `Set-GPOZaurrStatus`
- ☑ Added `Optimize-GPOZaurr`
- ☑ Fixed `Invoke-GPOZaurrPermission` which would not remove permission due to internal changes earlier on
- ☑ Small change to `Backup-GPOZaurr`
- ☑ Added support for `Disabled`. It's now possbile to backup `All` (default), `Empty`,`Unlinked`,`Disabled` or a mix of them
- ☑ Removed useless `GPOPath` parameter
## 0.0.95 - 04.12.2020
- ☑ Fix for too big int - [#4](https://github.com/EvotecIT/GPOZaurr/issues/4) - tnx neztach
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - added ability for Exclusions
- ☑ All other types, small improvements
- ☑ Added HideSteps, ShowError, ShowWarning -> Disabled Warnings/Errors by default as they tend to show too much information
- ☑ Improved `Remove-GPOZaurr` - added Exclusions
## 0.0.93 - 03.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` reverted charts colors for entries to match colors
- [ ] Added `Skip-GroupPolicy` to use within `Invoke-GPOZaurr`
- ☑ Improved `Invoke-GPOZaurr` with basic support for Exclusions
- ☑ Improved `Get-GPOZaurr` with basic support for Exclusions
- ☑ Improved `Remove-GPOZaurrPermission` error handling
## 0.0.92 - 01.12.2020
- ☑ Improved `Invoke-GPOZaurrSupport`
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` improved with more data, more problems and clearer information
- ☑ Improved `Remove-GPOZaurr`
- ☑ Added ability do remove disabed GPO
- ☑ Improved `Get-GPOZaurr` detecting more issues, delivering more data
## 0.0.91 - 24.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Improve Type `GPOPermissionsUnknown`
## 0.0.90 - 23.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Improves Type `GPODuplicates`
- ☑ Fix for chart color to be RED
- ☑ Add Type `GPOPermissionsUnknown`
- ☑ Improves logic for Data with 0/1 element
- ☑ Improves `Remove-GPOZaurrDuplicateObject` - removed `Confirm` requirement
- ☑ Improves `Get-GPOZaurrNetLogon` with more verbose
- ☑ Improves `Repair-GPOZaurrNetLogonOwner` with more verbose and fix for `LimitProcessing`
## 0.0.89 - 22.11.2020
- ☑ Small update `Add-GPOZaurrPermission`
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Added Type `GPOPermissionsAdministrative`
## 0.0.88 - 18.11.2020
- ☑ Fix for `Add-GPOZaurrPermission`
## 0.0.87 - 18.11.2020
- ☑ Improve error handling `Remove-GPOZaurrBroken`
## 0.0.86 - 18.11.2020
- ☑ Improve error handling `Remove-GPOZaurrBroken`
## 0.0.85 - 17.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Split `NetLogonPermissions` into `NetLogonPermissions` and `NetLogonOwners`
- ☑ Improved type `NetLogonPermissions`
- ☑ Improved type `NetLogonOwners`
- ☑ Improves `Get-GPOZaurrFiles`
- ☑ Improves `Get-GPOZaurrNetLogon`
- ☑ Fix for `Get-GPOZaurrNetLogon`
## 0.0.84 - 16.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `NetLogonPermissions`
- ☑ Fix for `Get-GPOZaurrNetLogon`
## 0.0.83 - 14.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Fix for wrong ActionRequired count
## 0.0.82 - 14.11.2020
- ☑ Added `Get-GPOZaurrPermissionIssue` to detect permission issue with no rights
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `GPOPermissionsRead` improved detection of problems with low permissions
## 0.0.81 - 12.11.2020
- ☑ Fix for `Set-GPOZaurrOwner` in case of missing permissions to not throw errors
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `GPOPermissionsRead` added
## 0.0.80 - 12.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `GPOOrphans` clearer options, updated texts, split per domain
- ☑ Type `GPOOwners` clearer options, updated texts, split per domain
- ☑ Improves `Add-GPOZaurrPermission`
- ☑ Fixes LimitProcessing to work correctly
- ☑ Added `All` to process all GPOs
- ☑ Fixes `Remove-GPOZaurrPermission`
- ☑ Improves `Set-GPOZaurrOwner`
- ☑ Added `Force` to force `GPO Owner` to any principal (normally only Domain Admins)
## 0.0.79 - 10.11.2020
- Improved `Invoke-GPOZaurr` - type `GPOOrphans`
## 0.0.78 - 10.11.2020
- Improved `Remove-GPOZaurrBroken` more verbose
- Improved `Get-GPOZaurrBroken` more verbose
- Improved `Invoke-GPOZaurr` - type `GPOOrphans`
- Improved `Invoke-GPOZaurr` - type `GPOList` - needs more work
- Improved `Get-GPOZaurr` with better detection of Empty Policies (needs testing)
## 0.0.77 - 9.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
## 0.0.76 - 8.11.2020
- Improved `Get-GPOZaurrNetLogon` to better handle errors
## 0.0.75 - 8.11.2020
- Improved `Get-GPOZaurrPermissionConsistency` to stop checking consistency if path doesn't exists
## 0.0.74 - 8.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
## 0.0.73 - 7.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- Improved `Get-GPOZaurr`
## 0.0.72 - 6.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
## 0.0.71 - 3.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
## 0.0.70 - 29.10.2020
- Added `Get-GPOZaurrDuplicateObject`
- Added `Remove-GPOZaurrDuplicateObject`
## 0.0.69 - 29.10.2020
- Improved `Invoke-GPOZaurr` (WIP)
- Improved `Get-GPOZaurrNetLogon`
- Improved `Get-GPOZaurrOwner`
- Improved `Set-GPOZaurrOwner`
- Added `Repair-GPOZaurrNetLogonOwner`
- Improved `Invoke-GPOZaurr` (WIP)
## 0.0.68 - 28.10.2020
- Renamed `Show-GPOZaurr` to `Invoke-GPOZaurr`
- Renamed `Invoke-GPOZaurr` to `Invoke-GPOZaurrContent`
- Improvements to `Get-GPOZaurrPermissionConsistency` - don't check for inherited permissions if top level ones are inconsistent
- Improved `Invoke-GPOZaurr` (WIP)
## 0.0.67 - 22.10.2020
- Improved `Show-GPOZaurr` (WIP)
## 0.0.66 - 22.10.2020
- Improved `Show-GPOZaurr` (WIP)
## 0.0.65 - 22.10.2020
- Improved `Show-GPOZaurr` (WIP)
## 0.0.64 - 21.10.2020
- Renamed `Remove-GPOZaurrOrphaned` to `Remove-GPOZaurrBroken` keeping it as an alias
- Renamed `Get-GPOZaurrSysvol` to `Get-GPOZaurrBroken` keeping it as an alias
- Improved `Show-GPOZaurr` (WIP)
## 0.0.63 - 19.10.2020
- Renamed `Invoke-GPOZaurrContent` back to `Invoke-GPOZaurr`
- Added `Show-GPOZaurr` (WIP)
- Added `OutputType`,`OutputType`,`Open`,`Online` parameters to `Invoke-GPOZaurr`
- Added `Get-GPOZaurrNetLogon`
- Improved `Get-GPOZaurrOwner`
- Fixes `Get-GPOZaurrSysvol`
## 0.0.62 - 14.10.2020
- Renamed `Invoke-GPOZaurr` to `Invoke-GPOZaurrContent` - I want to use `Invoke-GPOZaurr` for something else
- Improvements to `Get-GPOZaurrPermissionConsistency` for GPOs without SYSVOL to be reported properly
- Added `Get-GPOZaurrPermissionRoot`
- Renamed `Remove-GPOZaurrOrphanedSysvolFolders` to `Remove-GPOZaurrOrphaned`
- Improved `Remove-GPOZaurrOrphaned` to deal with orphaned folders but also orphaned AD GPO (No sysvol data)
- Improved `Get-GPOZaurrSysVol` to detect orphaned SYSVOL or AD GPO objects
- Improved `Get-GPOZaurrSysVol` to detect permissions issue when reading AD GPO objects
- Added `Get-GPOZaurrPermissionRoot` to show which users/groups have control over all GPOs (allowed to create/modify)
- Improved `Get-GPOZaurrPermissionSummary` to include `Get-GPOZaurrPermissionRoot` custom permissions
- Updated `Remove-GPOZaurrPermission`
- Updated `Get-GpoZaurrPermission`
- Updated `Get-GPOZaurrFiles` to better handle access issue
- Reversed parameters `Get-GPOZaurrFiles` from `Limited` to `ExtendedMetaData` and fixed missing columns
## 0.0.61 - 31.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
- Fixes to `ConvertFrom-CSExtension`
- Fixes to `Find-CSExtension`
## 0.0.59 - 26.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
## 0.0.58 - 26.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
## 0.0.57 - 26.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
## 0.0.56 - 26.08.2020
- Added `Get-GPOZaurrPermissionSummary`
## 0.0.55 - 17.08.2020
- Improved `Get-GPOZaurrInheritance`
## 0.0.54 - 16.08.2020
- Added `Invoke-GPOZaurrSupport` (WIP)
- Added `ConvertFrom-CSExtension`
- Added `Find-CSExtension`
- Added `Get-GPOZaurrInheritance`
## 0.0.53 - 16.08.2020
- Bad release
## 0.0.52 - 16.08.2020
- Bad release
## 0.0.51 - 2.08.2020
- Updates to `Invoke-GPOZaurr` - still work in progress
- Added `Get-GPOZaurrSysvolDFSR`
- Added `Clear-GPOZaurrSysvolDFSR` (requires testing)
## 0.0.50 - 29.07.2020
- Updates to couple of commands
## 0.0.49 - 23.07.2020
- Hidden files were skipped - and people do crazy things with them
## 0.0.48 - 21.07.2020
- Added `Get-GPOZaurrFilesPolicyDefinition`
- Updates to `Invoke-GPOZaurr` - still work in progress
- Updates to `Get-GPOZaurrFiles` - still work in progress
- Updates to `Remove-GPOZaurrOrphanedSysvolFolders` with backup and support for domains
- Module will now be signed
## 0.0.47 - 29.06.2020
- Update to `Get-GPOZaurrAD` for better error reporting
- Updates to `Invoke-GPOZaurr` - still work in progress
## 0.0.46 - 28.06.2020
- Additional protection for `Get-GPOZaurrAD` for CNF duplicates
- Update to `Save-GPOZaurrFiles`
- Added `Invoke-GPOZaurr` (alias: `Find-GPO`) (heavy work in progress)
## 0.0.45 - 26.06.2020
- During publishing ADEssentials required functions are now merged to prevent cyclic dependency bug [Using ModuleSpec syntax in RequiredModules causes incorrect "cyclic dependency" failures](https://github.com/PowerShell/PowerShell/issues/2607)
## 0.0.44 - 24.06.2020
- Improvement to `Get-GPOZaurrLinkSummary`
## 0.0.43 - 21.06.2020
- Added `Get-GPOZaurrFiles` to list files on NETLOGON/SYSVOL shares with a lot of details
## 0.0.42 - 19.06.2020
- Fix for `Get-GPOZaurrLink` and `SearchBase` parameter
- Fix for `Get-GPOZaurrLink` - canonical link Trim() throwing errors if empty
## 0.0.41 - 18.06.2020
- Added paramerter `SkipDuplicates` to `Invoke-GPOZaurrPermission` which prevents applying permissions over and over again if 1 GPO is linked to a multiple OU's within another OU
## 0.0.40 - 18.06.2020
- Fix for error `Get-GPOZaurrLink` - same issue as described on my [earlier blog - Get-ADObject : The server has returned the following error: invalid enumeration context.](https://evotec.xyz/get-adobject-the-server-has-returned-the-following-error-invalid-enumeration-context/).
- `WARNING: Get-GPOZaurrLink - Processing error The server has returned the following error: invalid enumeration context.`
- `WARNING: Get-GPOZaurrLink - Processing error A referral was returned from the server`
- Added `SkipDuplicates` for `Get-GPOZaurrLink`
## 0.0.39 - 17.06.2020
- Updates to `Invoke-GPOZaurrPermission` with new parameter `LimitAdministrativeGroupsToDomain`
- This will get administrative based on IncludeDomains if given. It means that if GPO has Domain admins added from multiple domains it will only find one, and remove all other Domain Admins (if working with Domain Admins that is)
## 0.0.38 - 17.06.2020
- Update to Get-PrivGPOZaurrLink which would cause problems to `Invoke-GPOZaurrPermission` if it would be run without Administrative permission and GPO wouldn't be accessible for that user
## 0.0.37 - 16.06.2020
- Updates to `Invoke-GPOZaurrPermission` with new parameterset `Level`
- Updates to `Get-GPOZaurrLinkSummary`
## 0.0.36 - 15.06.2020
- Initial release
@@ -5,7 +5,7 @@
# regardless if current user is still Domain Admin or not
$GPOs = Get-GPOZaurrOwner -IncludeSysvol
$GPOs | Format-Table DisplayName, Owner, OwnerSID, OwnerType, SysvolOwner, SysvolSID, SysvolType
$GPOs | Format-Table DisplayName, Status, Owner, OwnerSID, OwnerType, SysvolOwner, SysvolSID, SysvolType
Set-GPOZaurrOwner -Type Unknown -Verbose -WhatIf #-LimitProcessing 2
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -WhatIf -IncludeDomains 'ad.evotec.pl'
@@ -0,0 +1,10 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$GPOs = Get-GPOZaurrOwner -IncludeSysvol -Verbose
$GPOs | Format-Table DisplayName, Status, Owner, OwnerSID, OwnerType, SysvolOwner, SysvolSID, SysvolType
#Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -WhatIf -IncludeDomains 'ad.evotec.xyz'
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -WhatIf -IncludeDomains 'ad.evotec.xyz' -ApprovedOwner @(
'EVOTEC\przemyslaw.klys'
)
+3 -1
View File
@@ -2,7 +2,9 @@
$T = Get-GPOZaurrOwner -Verbose -IncludeSysvol
$T | Format-Table *
#$T | Out-HtmlView -ScrollX
$T = Get-GPOZaurrOwner -Verbose -IncludeSysvol -ApprovedOwner @('EVOTEC\Domain Admins')
$T | Format-Table *
$T = Get-GPOZaurrOwner -Verbose -IncludeSysvol -GPOName 'Default Domain Policy'
$T | Format-Table *
+6
View File
@@ -0,0 +1,6 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurrGPOOwners.html -Type GPOOwners -Online -Exclusions @(
'EVOTEC\Domain Admins'
'EVOTEC\przemyslaw.klys'
)
+4 -1
View File
@@ -7,4 +7,7 @@ Add-GPOZaurrPermission -GPOName 'New Group Policy Object' -Type AuthenticatedUse
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -WhatIf -Verbose
# Add Domain Admins/Enterprise Admins to all that need it
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose
# Add ranom name to all that need it
Add-GPOZaurrPermission -All -Principal SVC_AGPM -PrincipalType Name -PermissionType GpoEditDeleteModifySecurity -Verbose -LimitProcessing 2 -WhatIf
+7 -4
View File
@@ -1,16 +1,19 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
#$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -PassThru -Type GPOConsistency, GPOList, GPODuplicates, GPOBroken, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative,GPOPermissionsUnknown
Invoke-GPOZaurr -Type GPOOrganizationalUnit -Online -FilePath $PSScriptRoot\Reports\GPOZaurr.html
# Shows how to use exclusions (supported only in GPOBlockedInheritance)
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOBlockedInheritance -Online -Exclusions @(
'OU=Test,OU=ITR02,DC=ad,DC=evotec,DC=xyz'
)
<#
# different approach to query multiple reports or just one
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -PassThru -Type GPOConsistency, GPOList, GPODuplicates, GPOBroken, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative,GPOPermissionsUnknown
Invoke-GPOZaurr -Type GPOOwners -Online -FilePath $PSScriptRoot\Reports\GPOZaurr.html
# Shows how to use exclusions for GPOList (different way)
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOList -Online -Exclusions {
Skip-GroupPolicy -Name 'de14_usr_std'
Skip-GroupPolicy -Name 'ALL | Enable RDP' -DomaiName 'ad.evotec.xyz'
}
#>
}
+17 -2
View File
@@ -1,7 +1,22 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$GPOS = Get-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\Empty' -ExcludeGroupPolicies {
$GPOS = Get-GPOZaurr -ExcludeGroupPolicies {
Skip-GroupPolicy -Name 'de14_usr_std'
Skip-GroupPolicy -Name 'de14_usr_std' -DomaiName 'ad.evotec.xyz'
Skip-GroupPolicy -Name 'All | Trusted Websites' #-DomaiName 'ad.evotec.xyz'
'{D39BF08A-87BF-4662-BFA0-E56240EBD5A2}'
'COMPUTERS | Enable Sets'
}
$GPOS | Format-Table -AutoSize *
$GPOS | Format-Table -AutoSize *
$Output = Invoke-GPOZaurr -Type GPOList -Exclusions {
Skip-GroupPolicy -Name 'All | Trusted Websites' -DomaiName 'ad.evotec.xyz'
'{D39BF08A-87BF-4662-BFA0-E56240EBD5A2}'
"104da6a7-c7d2-48da-b24b-8fa584f7b0b6"
"{087b4f69-c541-429f-8dfd-0eb3ed133910}"
'COMPUTERS | Enable Sets'
'24194523-bb82-439c-a533-abf4f30fa2c4'
'{31b2f340-016d-11d2-945f-00c04fb984f9 } '
} -PassThru
$Output.GPOList
+3
View File
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Invoke-GPOZaurr -Type GPOUpdates -Online -Verbose #-IncludeDomains 'ad.evotec.pl'
@@ -0,0 +1,10 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Remove-GPOZaurrLinkEmptyOU -Verbose -LimitProcessing 3 -WhatIf
$Exclude = @(
"OU=Groups,OU=Production,DC=ad,DC=evotec,DC=pl"
"OU=Test \, OU,OU=ITR02,DC=ad,DC=evotec,DC=xyz"
)
Remove-GPOZaurrLinkEmptyOU -Verbose -LimitProcessing 3 -WhatIf -ExcludeOrganizationalUnit $Exclude
@@ -0,0 +1,17 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$OUs = Get-GPOZaurrOrganizationalUnit
$Ous | Format-Table
Get-GPOZaurrOrganizationalUnit -Verbose -Option Unlink -Exclusions @(
'OU=Groups,OU=Production,DC=ad,DC=evotec,DC=pl'
) | Format-Table
Get-GPOZaurrOrganizationalUnit -Verbose -ExcludeOrganizationalUnit @(
'*,OU=Production,DC=ad,DC=evotec,DC=pl'
) | Format-Table
Invoke-GPOZaurr -Type GPOOrganizationalUnit -Online -FilePath $PSScriptRoot\Reports\GPOZaurrOU.html -Exclusions @(
#'*OU=Production,DC=ad,DC=evotec,DC=pl'
)
+4
View File
@@ -0,0 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-GPOZaurrUpdates -DateRange Last14Days -DateProperty WhenCreated, WhenChanged -Verbose -IncludeDomains 'ad.evotec.pl' | Format-List
Get-GPOZaurrUpdates -DateRange Last14Days -DateProperty WhenCreated -Verbose | Format-Table
+5 -5
View File
@@ -6,9 +6,9 @@
CompatiblePSEditions = @('Desktop')
Copyright = '(c) 2011 - 2021 Przemyslaw Klys @ Evotec. All rights reserved.'
Description = 'Group Policy Eater is a PowerShell module that aims to gather information about Group Policies but also allows fixing issues that you may find in them.'
FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrBrokenLink', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionAnalysis', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionIssue', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrContent', 'Invoke-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', 'Optimize-GPOZaurr', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrBroken', 'Remove-GPOZaurrDuplicateObject', 'Remove-GPOZaurrFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrBrokenLink', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermission', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Set-GPOZaurrStatus', 'Skip-GroupPolicy')
FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrBrokenLink', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOrganizationalUnit', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionAnalysis', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionIssue', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrUpdates', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrContent', 'Invoke-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', 'Optimize-GPOZaurr', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrBroken', 'Remove-GPOZaurrDuplicateObject', 'Remove-GPOZaurrFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrLinkEmptyOU', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrBrokenLink', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermission', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Set-GPOZaurrStatus', 'Skip-GroupPolicy')
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
ModuleVersion = '0.0.128'
ModuleVersion = '0.0.146'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
@@ -18,15 +18,15 @@
}
}
RequiredModules = @(@{
ModuleVersion = '0.0.201'
ModuleVersion = '0.0.214'
ModuleName = 'PSSharedGoods'
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
}, @{
ModuleVersion = '0.0.128'
ModuleVersion = '0.0.135'
ModuleName = 'ADEssentials'
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
}, @{
ModuleVersion = '0.0.148'
ModuleVersion = '0.0.158'
ModuleName = 'PSWriteHTML'
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
@@ -4,6 +4,22 @@
[PSCustomObject] $GPO,
[switch] $SingleObject
)
# Redirection types a stored as GUID in GPOs. This hash is used to translate into readable text.
$FolderID = @{
"{1777F761-68AD-4D8A-87BD-30B759FA33DD}" = "Favorites"
"{FDD39AD0-238F-46AF-ADB4-6C85480369C7}" = "Documents"
"{33E28130-4E1E-4676-835A-98395C3BC3BB}" = "Pictures"
"{4BD8D571-6D19-48D3-BE97-422220080E43}" = "Music"
"{18989B1D-99B5-455B-841C-AB7C74E4DDFC}" = "Videos"
"{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}" = "AppDataRoaming"
"{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}" = "Desktop"
"{625B53C3-AB48-4EC1-BA1F-A1EF4146FC19}" = "StartMenu"
"{374DE290-123F-4565-9164-39C4925E467B}" = "Downloads"
"{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}" = "Saved Games"
"{56784854-C6CB-462B-8169-88E350ACB882}" = "Contacts"
"{7D1D3A04-DEBB-4115-95CF-2F29DA2920DA}" = "Searches"
"{BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968}" = "Links"
}
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
@@ -18,6 +34,8 @@
[Array] $CreateGPO['Settings'] = foreach ($Folder in $GPO.DataSet) {
foreach ($Location in $Folder.Location) {
[PSCustomObject] @{
ID = $Folder.ID
FolderType = $FolderID[$Folder.Id]
DestinationPath = $Location.DestinationPath
SecuritySID = $Location.SecurityGroup.SID.'#text'
SecurityName = $Location.SecurityGroup.Name.'#text'
@@ -47,6 +65,7 @@
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Id = $Folder.Id
FolderType = $FolderID[$Folder.Id]
DestinationPath = $Location.DestinationPath
SecuritySID = $Location.SecurityGroup.SID.'#text'
SecurityName = $Location.SecurityGroup.Name.'#text'
+220
View File
@@ -0,0 +1,220 @@
function Get-ADOrganizationalUnitObject {
<#
.SYNOPSIS
Gets number of objects in a given OU/OUs with ability to find only those being affected by GPOs.
.DESCRIPTION
Gets number of objects in a given OU/OUs with ability to find only those being affected by GPOs.
.PARAMETER OrganizationalUnit
One or more organizational units to get the number of objects in.
.PARAMETER Extended
Adds all objects affected for better understanding
.PARAMETER Summary
Returns only summary for given OU/OUs
.PARAMETER IncludeAffectedOnly
Ignores any object types that are not Users or Computers
.PARAMETER Forest
Target different Forest, by default current forest is used
.PARAMETER ExcludeDomains
Exclude domain from search, by default whole forest is scanned
.PARAMETER IncludeDomains
Include only specific domains, by default whole forest is scanned
.PARAMETER AsHashTable
Returns results in form of hashtable
.PARAMETER ExtendedForestInformation
Ability to provide Forest Information from another command to speed up processing
.EXAMPLE
$OUs = @(
'OU=SE,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=US,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=Users,OU=User,OU=SE1,OU=SE,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
)
Get-ADOrganizationalUnitObject -OrganizationalUnit $OUs -IncludeAffectedOnly | Format-Table
.EXAMPLE
$OUs = @(
'OU=SE,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=US,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=Users,OU=User,OU=SE1,OU=SE,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
)
Get-ADOrganizationalUnitObject -OrganizationalUnit $OUs | Format-Table
.EXAMPLE
$OUs = @(
#'OU=SE,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
#'OU=US,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=Users,OU=User,OU=SE1,OU=SE,OU=ITR01,DC=ad,DC=evotec,DC=xyz'
'OU=ITR01,DC=ad,DC=evotec,DC=xyz'
)
Get-ADOrganizationalUnitObject -OrganizationalUnit $OUs -Summary -IncludeAffectedOnly | Format-List
.NOTES
General notes
#>
[cmdletBinding()]
param(
[parameter(Mandatory)][Array] $OrganizationalUnit,
[switch] $Extended,
[switch] $Summary,
[switch] $IncludeAffectedOnly,
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[switch] $AsHashTable,
[System.Collections.IDictionary] $ExtendedForestInformation
)
$CachedOu = [ordered] @{}
$ListOU = @(
foreach ($OU in $OrganizationalUnit) {
if ($OU.DistinguishedName) {
$OU.DistinguishedName
} else {
$OU
}
}
)
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
$OUCache = Get-GPOBlockedInheritance -AsHashTable -ExtendedForestInformation $ForestInformation
if ($Summary) {
$SummaryData = [ordered] @{
ObjectsClasses = [ordered] @{}
ObjectsTotalCount = 0
ObjectsBlockedInheritanceCount = 0
ObjectsTotal = [ordered] @{}
ObjectsBlockedInheritance = [ordered] @{}
DistinguishedName = [System.Collections.Generic.List[string]]::new()
}
}
foreach ($OU in $ListOU) {
$Domain = ConvertFrom-DistinguishedName -ToDomainCN -DistinguishedName $OU
$ObjectsInOu = Get-ADObject -LDAPFilter "(|(ObjectClass=user)(ObjectClass=contact)(ObjectClass=computer)(ObjectClass=group)(objectClass=inetOrgPerson))" -SearchBase $OU -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0]
#Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)], found $($ObjectsInOu.Count) objects to process."
if (-not $CachedOu[$OU]) {
$CachedOu[$OU] = [ordered] @{
DistinguishedName = $OU
Domain = $Domain
'ObjectsClasses' = [ordered] @{} # only direct, indirect, but not with blocked inheritance
'ObjectsDirectCount' = 0
'ObjectsIndirectCount' = 0
'ObjectsTotalCount' = 0
'ObjectsTotalIncludingBlockedCount' = 0
'ObjectsBlockedInheritanceCount' = 0
}
if ($Extended) {
$CachedOu[$OU]['ObjectsDirect'] = [ordered] @{}
$CachedOu[$OU]['ObjectsIndirect'] = [ordered] @{}
$CachedOu[$OU]['ObjectsTotal'] = [ordered] @{}
$CachedOu[$OU]['ObjectsTotalIncludingBlocked'] = [ordered] @{}
$CachedOu[$OU]['ObjectsBlockedInheritance'] = [ordered] @{}
}
}
foreach ($Object in $ObjectsInOu) {
if ($IncludeAffectedOnly) {
if ($Object.ObjectClass -notin 'User', 'computer') {
continue
}
}
$Place = ConvertFrom-DistinguishedName -ToOrganizationalUnit -DistinguishedName $Object.DistinguishedName
if (-not $Place) {
# Write-Verbose -Message "Get-OrganizationalUnitObject - Processing object in container/root $($Object.DistinguishedName)"
}
if ($Place -and $OUCache[$Place]) {
$BlockedInheritance = $OUCache[$Place].BlockedInheritance
} else {
$BlockedInheritance = $false
}
if ($Summary) {
$SummaryData['DistinguishedName'].Add($OU)
$SummaryData['ObjectsClasses'][$Object.ObjectClass] = ''
if (-not $Place -or $Place -eq $OU) {
$SummaryData['ObjectsTotal'][$Object.DistinguishedName] = $Object
} else {
if ($BlockedInheritance) {
$SummaryData['ObjectsBlockedInheritance'][$Object.DistinguishedName] = $Object
} else {
$SummaryData['ObjectsTotal'][$Object.DistinguishedName] = $Object
}
}
} else {
# This is standard way of finding OU's
if (-not $Place -or $Place -eq $OU) {
$CachedOu[$OU]['ObjectsDirectCount']++
$CachedOu[$OU]['ObjectsTotalCount']++
# using hashtable to avoid duplicates
$CachedOu[$OU]['ObjectsClasses'][$Object.ObjectClass] = ''
# adding all objects to the list, excluding blocked inheritance
if ($Extended) {
$CachedOu[$OU]['ObjectsTotal'][$Object.DistinguishedName] = $Object
$CachedOu[$OU]['ObjectsDirect'][$Object.DistinguishedName] = $Object
}
} else {
if ($BlockedInheritance) {
# We only check for blocked inheritance if the object is not in the same OU
$CachedOu[$OU]['ObjectsBlockedInheritanceCount']++
if ($Extended) {
$CachedOu[$OU]['ObjectsBlockedInheritance'][$Object.DistinguishedName] = $Object
}
} else {
$CachedOu[$OU]['ObjectsIndirectCount']++
$CachedOu[$OU]['ObjectsTotalCount']++
# using hashtable to avoid duplicates
$CachedOu[$OU]['ObjectsClasses'][$Object.ObjectClass] = ''
# adding all objects to the list excluding blocked inheritance
if ($Extended) {
$CachedOu[$OU]['ObjectsTotal'][$Object.DistinguishedName] = $Object
$CachedOu[$OU]['ObjectsIndirect'][$Object.DistinguishedName] = $Object
}
}
}
$CachedOu[$OU]['ObjectsTotalIncludingBlockedCount']++
if ($Extended) {
$CachedOu[$OU]['ObjectsTotalIncludingBlocked'][$Object.DistinguishedName] = $Object
}
}
}
}
if ($Summary) {
foreach ($ObjectDistinguishedName in [string[]] $SummaryData['ObjectsBlockedInheritance'].Keys) {
if ($SummaryData['ObjectsTotal'][$ObjectDistinguishedName]) {
$SummaryData['ObjectsBlockedInheritance'].Remove($ObjectDistinguishedName)
}
}
$SummaryData['ObjectsTotalCount'] = $SummaryData['ObjectsTotal'].Count
$SummaryData['ObjectsBlockedInheritanceCount'] = $SummaryData['ObjectsBlockedInheritance'].Count
if (-not $Extended) {
$SummaryData.Remove('ObjectsTotal')
$SummaryData.Remove('ObjectsBlockedInheritance')
}
[PSCustomObject] $SummaryData
} else {
if ($AsHashTable) {
$CachedOu
} else {
$CachedOu.Values | ForEach-Object { [PSCustomObject] $_ }
}
}
}
+103
View File
@@ -0,0 +1,103 @@
function Get-ChoosenDates {
[CmdletBinding()]
param(
[ValidateSet('Everything', 'PastHour', 'CurrentHour', 'PastDay', 'CurrentDay', 'PastMonth', 'CurrentMonth', 'PastQuarter', 'CurrentQuarter', 'Last14Days', 'Last21Days', 'Last30Days' , 'Last7Days', 'Last3Days', 'Last1Days')][string] $DateRange
)
# Report Per Hour
if ($DateRange -eq 'PastHour') {
$DatesPastHour = Find-DatesPastHour
if ($DatesPastHour) {
$DatesPastHour
}
}
if ($DateRange -eq 'CurrentHour') {
$DatesCurrentHour = Find-DatesCurrentHour
if ($DatesCurrentHour) {
$DatesCurrentHour
}
}
# Report Per Day
if ($DateRange -eq 'PastDay') {
$DatesDayPrevious = Find-DatesDayPrevious
if ($DatesDayPrevious) {
$DatesDayPrevious
}
}
if ($DateRange -eq 'CurrentDay') {
$DatesDayToday = Find-DatesDayToday
if ($DatesDayToday) {
$DatesDayToday
}
}
# Report Per Month
if ($DateRange -eq 'PastMonth') {
# Find-DatesMonthPast runs only on 1st of the month unless -Force is used
$DatesMonthPrevious = Find-DatesMonthPast -Force $true
if ($DatesMonthPrevious) {
$DatesMonthPrevious
}
}
if ($DateRange -eq 'CurrentMonth') {
$DatesMonthCurrent = Find-DatesMonthCurrent
if ($DatesMonthCurrent) {
$DatesMonthCurrent
}
}
# Report Per Quarter
if ($DateRange -eq 'PastQuarter') {
# Find-DatesMonthPast runs only on 1st of the quarter unless -Force is used
$DatesQuarterLast = Find-DatesQuarterLast -Force $true
if ($DatesQuarterLast) {
$DatesQuarterLast
}
}
if ($DateRange -eq 'CurrentQuarter') {
$DatesQuarterCurrent = Find-DatesQuarterCurrent
if ($DatesQuarterCurrent) {
$DatesQuarterCurrent
}
}
if ($DateRange -eq 'Everything') {
$DatesEverything = @{
DateFrom = Get-Date -Year 1900 -Month 1 -Day 1
DateTo = Get-Date -Year 2300 -Month 1 -Day 1
}
$DatesEverything
}
if ($DateRange -eq 'Last1days') {
$DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 1
if ($DatesCurrentDayMinusDaysX) {
$DatesCurrentDayMinusDaysX
}
}
if ($DateRange -eq 'Last3days') {
$DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 3
if ($DatesCurrentDayMinusDaysX) {
$DatesCurrentDayMinusDaysX
}
}
if ($DateRange -eq 'Last7days') {
$DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 7
if ($DatesCurrentDayMinusDaysX) {
$DatesCurrentDayMinusDaysX
}
}
if ($DateRange -eq 'Last14days') {
$DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 14
if ($DatesCurrentDayMinusDaysX) {
$DatesCurrentDayMinusDaysX
}
}
if ($DateRange -eq 'Last21days') {
$DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 21
if ($DatesCurrentDayMinusDaysX) {
$DatesCurrentDayMinusDaysX
}
}
if ($DateRange -eq 'Last30Days') {
$DatesCurrentDayMinusDaysX = Find-DatesCurrentDayMinuxDaysX -days 30
if ($DatesCurrentDayMinusDaysX) {
$DatesCurrentDayMinusDaysX
}
}
}
+30
View File
@@ -0,0 +1,30 @@
function Get-GPOBlockedInheritance {
[cmdletBinding()]
param(
[string] $Filter = '*',
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[switch] $AsHashTable,
[System.Collections.IDictionary] $ExtendedForestInformation
)
$OUCache = [ordered] @{}
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
foreach ($Domain in $ForestInformation.Domains) {
$OrganizationalUnits = Get-ADOrganizationalUnit -Filter $Filter -Properties gpOptions, canonicalName -Server $ForestInformation['QueryServers'][$Domain]['HostName'][0] #-SearchScope Subtree
foreach ($OU in $OrganizationalUnits) {
$OUCache[$OU.DistinguishedName] = [PSCustomObject] @{
DistinguishedName = $OU.DistinguishedName
BlockedInheritance = if ($OU.gpOptions -eq 1) { $true } else { $false } # blocked inheritance
}
}
}
if ($AsHashTable) {
$OUCache
} else {
$OUCache.Values
}
}
+10 -6
View File
@@ -31,13 +31,13 @@ function Get-GPOZaurrLinkInheritance {
Parameter description
.PARAMETER Forest
Parameter description
Target different Forest, by default current forest is used
.PARAMETER ExcludeDomains
Parameter description
Exclude domain from search, by default whole forest is scanned
.PARAMETER IncludeDomains
Parameter description
Include only specific domains, by default whole forest is scanned
.PARAMETER ExtendedForestInformation
Parameter description
@@ -123,9 +123,13 @@ function Get-GPOZaurrLinkInheritance {
# While initially we used $ForestInformation.Domains but the thing is GPOs can be linked to other domains so we need to get them all so we can use cache of it later on even if we're processing just one domain
# That's why we use $ForestInformation.Forest.Domains instead
foreach ($Domain in $ForestInformation.Forest.Domains) {
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
$GPOCache["$Domain$($_.ID.Guid)"] = $_
if ($ForestInformation['QueryServers'][$Domain]) {
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
$GPOCache["$Domain$($_.ID.Guid)"] = $_
}
} else {
Write-Warning -Message "Get-GPOZaurrLinkInheritance - Couldn't get query server for $Domain. Skipped."
}
}
}
+11 -1
View File
@@ -230,8 +230,18 @@
# Mark GPO as excluded
$Exclude = $false
if ($ExcludeGroupPolicies) {
$GUID = $XMLContent.GPO.Identifier.Identifier.'#text'
$GUIDWithOutBrackets = $GUID.Replace('{', '').Replace('}', '')
$PolicyWithDomain = -join ($XMLContent.GPO.Identifier.Domain.'#text', $XMLContent.GPO.Name)
if ($ExcludeGroupPolicies[$XMLContent.GPO.Name] -or $ExcludeGroupPolicies[$PolicyWithDomain]) {
$PolicyWithDomainID = -join ($XMLContent.GPO.Identifier.Domain.'#text', $GUID)
$PolicyWithDomainIDWithoutBrackets = -join ($XMLContent.GPO.Identifier.Domain.'#text', $GUIDWithOutBrackets)
if ($ExcludeGroupPolicies[$XMLContent.GPO.Name] -or
$ExcludeGroupPolicies[$PolicyWithDomain] -or
$ExcludeGroupPolicies[$PolicyWithDomainID] -or
$ExcludeGroupPolicies[$GUID] -or
$ExcludeGroupPolicies[$GUIDWithOutBrackets] -or
$ExcludeGroupPolicies[$PolicyWithDomainIDWithoutBrackets]
) {
$Exclude = $true
}
}
+1 -1
View File
@@ -26,7 +26,7 @@
New-HTMLTable -DataTable $Script:Reporting['GPOAnalysis']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -SearchBuilder
}
}
}
}
+32 -3
View File
@@ -110,6 +110,22 @@
} -FontSize 10pt
}
New-HTMLText -FontSize 10pt -Text "Please review output in table and follow the steps below table to get Active Directory Group Policies in healthy state."
if ($Script:Reporting['GPOBlockedInheritance']['Exclusions']) {
New-HTMLText -LineBreak
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
) -FontSize 10pt -FontWeight bold, normal -Color Red, None -LineBreak
New-HTMLText -Text "Code to use for exclusions: " -FontSize 10pt -FontWeight bold -LineBreak
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOBlockedInheritance']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
Solution = {
New-HTMLSection -Invisible {
@@ -138,14 +154,14 @@
New-TableCondition -Name 'ComputersCount' -Value 0
} -BackgroundColor Salmon -FailBackgroundColor Amber -HighlightHeaders 'UsersCount', 'ComputersCount'
New-TableColumnOption -Hidden $true -ColumnIndex 8
} -PagingOptions 5, 10, 20, 30, 40, 50 -SearchBuilder -ExcludeProperty GroupPolicies
} -PagingOptions 5, 10, 20, 30, 40, 50 -ExcludeProperty GroupPolicies
}
New-HTMLSection -Name 'Group Policies affecting objects in Organizational Units with Blocked Inheritance' {
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['Data'].GroupPolicies -Filtering {
New-TableCondition -Name 'Enabled' -Value $true -BackgroundColor SpringGreen -FailBackgroundColor Salmon
New-TableCondition -Name 'Enforced' -Value $true -BackgroundColor Amber -FailBackgroundColor AirForceBlue
New-TableCondition -Name 'LinkedDirectly' -Value $true -BackgroundColor Amber -FailBackgroundColor AirForceBlue
} -PagingOptions 5, 10, 20, 30, 40, 50 -SearchBuilder -DataTableID 'TableWithGroupPoliciesBlockedInheritance'
} -PagingOptions 5, 10, 20, 30, 40, 50 -DataTableID 'TableWithGroupPoliciesBlockedInheritance'
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix - Organizational Units with Group Policy Blocked Inheritance' {
@@ -160,6 +176,19 @@
} -Style powershell
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
}
if ($Script:Reporting['GPOBlockedInheritance']['Exclusions']) {
New-HTMLWizardStep -Name 'Required exclusions' {
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
)
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOBlockedInheritance']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
New-HTMLWizardStep -Name 'Prepare report' {
New-HTMLText -Text @(
"Depending when this report was run you may want to prepare new report before proceeding removing Group Policy Inheritance Blocks. "
@@ -205,7 +234,7 @@
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -SearchBuilder
}
}
}
}
+1 -1
View File
@@ -76,7 +76,7 @@ $GPOZaurrBrokenLink = [ordered] @{
New-HTMLSection -Name 'Group Policy Broken Links' {
New-HTMLTable -DataTable $Script:Reporting['GPOBrokenLink']['Data'] -Filtering {
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to remove Broken Links' {
+1 -1
View File
@@ -91,7 +91,7 @@
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value $true -BackgroundColor PaleGreen -TextTransform capitalize -ComparisonType string
New-HTMLTableCondition -Name 'ACLConsistent' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix - Permissions Consistency' {
+1 -1
View File
@@ -48,7 +48,7 @@
New-HTMLSection -Name 'Group Policy CNF (Duplicate) Objects' {
New-HTMLTable -DataTable $Script:Reporting['GPODuplicates']['Data'] -Filtering {
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix - Remove duplicate (CNF) objects' {
+1 -1
View File
@@ -22,7 +22,7 @@
New-HTMLTable -DataTable $Script:Reporting['GPOFiles']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -SearchBuilder
}
}
}
}
+82
View File
@@ -0,0 +1,82 @@
$GPOZaurrGPOUpdates = [ordered] @{
Name = 'Group Policies added last 7 days'
Enabled = $false
Action = $null
Data = $null
Execute = {
Get-GPOZaurrUpdates -DateRange Last7Days -DateProperty WhenCreated -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
Processing = {
foreach ($GPO in $Script:Reporting['GPOUpdates']['Data']) {
$Script:Reporting['GPOUpdates']['Variables']['GPOTotal']++
if ($GPO.LinksEnabledCount -eq 0) {
$Script:Reporting['GPOUpdates']['Variables']['GPOWithoutEnabledLinks']++
} else {
$Script:Reporting['GPOUpdates']['Variables']['GPOWithEnabledLinks']++
}
if ($GPO.AffectedCount -eq 0) {
$Script:Reporting['GPOUpdates']['Variables']['GPOWithoutAffectedObjects']++
}
}
}
Variables = @{
GPOTotal = 0
GPOWithoutEnabledLinks = 0
GPOWithEnabledLinks = 0
GPOWithoutAffectedObjects = 0
}
Overview = {
}
Summary = {
New-HTMLText -TextBlock {
"Group Policies are important part of Active Directory. Knowing when those are created and what they affect is important part of admins work."
"This report shows which GPOs were created in last 7 days and how many objects those are affecting."
} -FontSize 10pt -LineBreak
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies added in last 7 days: ', $Script:Reporting['GPOUpdates']['Variables']['GPOTotal'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies without enabled links: ', $Script:Reporting['GPOUpdates']['Variables']['GPOWithoutEnabledLinks'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies with enabled links: ', $Script:Reporting['GPOUpdates']['Variables']['GPOWithEnabledLinks'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies without affected objects: ', $Script:Reporting['GPOUpdates']['Variables']['GPOWithoutAffectedObjects'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -TextBlock {
"If you notice any GPO that is not working or against best practices please reach out to your collegues to confirm whether this is as expected."
} -FontSize 10pt -LineBreak
}
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOUpdates']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'No enabled links', 'Enabled links' -Color Crimson, MediumOrchid
New-ChartBar -Name 'Links enabled' -Value $Script:Reporting['GPOUpdates']['Variables']['GPOWithoutEnabledLinks'], $Script:Reporting['GPOUpdates']['Variables']['GPOWithEnabledLinks']
} -Title 'Group Policies created last 7 days' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policies added in last 7 days' {
New-HTMLTable -DataTable $Script:Reporting['GPOUpdates']['Data'] -Filtering {
#New-HTMLTableCondition -Name 'LinksCount' -Value 0 -BackgroundColor Salmon -ComparisonType number
#New-HTMLTableCondition -Name 'LinksEnabledCount' -Value 0 -BackgroundColor Salmon -ComparisonType number
New-HTMLTableCondition -Name 'AffectedCount' -Value 0 -BackgroundColor Salmon -ComparisonType number -FailBackgroundColor Goldenrod
New-HTMLTableConditionGroup {
New-HTMLTableCondition -Name 'LinksCount' -Value 0 -ComparisonType number
New-HTMLTableCondition -Name 'LinksEnabledCount' -Value 0 -ComparisonType number
} -BackgroundColor Salmon -FailBackgroundColor Goldenrod -Logic OR -HighlightHeaders 'LinksCount', 'LinksEnabledCount', 'DisplayName', 'DomainName'
}
}
if ($Script:Reporting['GPOUpdates']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOUpdates']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ $GPOZaurrLinks = [ordered] @{
New-HTMLTable -DataTable $Script:Reporting['GPOLinks']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -SearchBuilder
}
}
}
}
+96 -49
View File
@@ -4,9 +4,8 @@
Action = $null
Data = $null
Execute = {
if ($Script:Reporting['GPOList']['ExclusionsCode']) {
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeGroupPolicies $Script:Reporting['GPOList']['ExclusionsCode']
if ($Script:Reporting['GPOList']['Exclusions']) {
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeGroupPolicies $Script:Reporting['GPOList']['Exclusions']
} else {
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
@@ -52,9 +51,17 @@
# Skip GPOS that are younger than 30 days
$Script:Reporting['GPOList']['Variables']['GPOSkip']++
}
if (($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) -and $GPO.Days -le $Script:Reporting['GPOList']['Variables']['GPOOlderThan']) {
if ($GPO.Exclude -eq $true) {
# Skip GPOS that are excluded
$Script:Reporting['GPOList']['Variables']['GPOSkipExcluded']++
}
if (($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) -and $GPO.Exclude -eq $true) {
$Script:Reporting['GPOList']['Variables']['GPONotValidButExcluded']++
$Script:Reporting['GPOList']['Variables']['GPONotValidButSkippedOrExcluded']++
} elseif (($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) -and $GPO.Days -le $Script:Reporting['GPOList']['Variables']['GPOOlderThan']) {
# Skip GPOS that are younger than 30 days
$Script:Reporting['GPOList']['Variables']['GPONotValidButSkip']++
$Script:Reporting['GPOList']['Variables']['GPONotValidButSkippedOrExcluded']++
}
if (($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) -and $GPO.Days) {
$Script:Reporting['GPOList']['Variables']['GPONotValid']++
@@ -142,52 +149,55 @@
}
}
$Script:Reporting['GPOList']['Variables']['GPOTotal'] = $Script:Reporting['GPOList']['Data'].Count
if ($Script:Reporting['GPOList']['Variables']['GPONotValid'] -gt 0 -and $Script:Reporting['GPOList']['Variables']['GPONotValidButSkip'] -ne $Script:Reporting['GPOList']['Variables']['GPONotValid']) {
if ($Script:Reporting['GPOList']['Variables']['GPONotValid'] -gt 0 -and $Script:Reporting['GPOList']['Variables']['GPONotValidButSkippedOrExcluded'] -ne $Script:Reporting['GPOList']['Variables']['GPONotValid']) {
$Script:Reporting['GPOList']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOList']['ActionRequired'] = $false
}
}
Variables = @{
GPOOlderThan = 30
GPONotValidPerDomain = $null
GPOValidPerDomain = $null
GPONotOptimizedPerDomain = $null
GPOOptimizedPerDomain = $null
GPOProblemPerDomain = $null
GPONoProblemPerDomain = $null
GPOApplyPermissionYesPerDomain = $null
GPOApplyPermissionNoPerDomain = $null
GPOWithProblems = 0
ComputerOptimizedYes = 0
ComputerOptimizedNo = 0
ComputerProblemYes = 0
ComputerProblemNo = 0
UserOptimizedYes = 0
UserOptimizedNo = 0
UserProblemYes = 0
UserProblemNo = 0
GPOOptimized = 0
GPONotOptimized = 0
GPOProblem = 0
GPONoProblem = 0
GPONotLinked = 0
GPOLinked = 0
GPOEmpty = 0
GPONotEmpty = 0
GPOEmptyAndUnlinked = 0
GPOEmptyOrUnlinked = 0
GPOLinkedButEmpty = 0
GPOEnabled = 0
GPODisabled = 0
GPOSkip = 0
GPOValid = 0
GPONotValid = 0
GPONotValidButSkip = 0
GPOLinkedButLinkDisabled = 0
GPOTotal = 0
ApplyPermissionYes = 0
ApplyPermissionNo = 0
GPOOlderThan = 30
GPONotValidPerDomain = $null
GPOValidPerDomain = $null
GPONotOptimizedPerDomain = $null
GPOOptimizedPerDomain = $null
GPOProblemPerDomain = $null
GPONoProblemPerDomain = $null
GPOApplyPermissionYesPerDomain = $null
GPOApplyPermissionNoPerDomain = $null
GPOWithProblems = 0
ComputerOptimizedYes = 0
ComputerOptimizedNo = 0
ComputerProblemYes = 0
ComputerProblemNo = 0
UserOptimizedYes = 0
UserOptimizedNo = 0
UserProblemYes = 0
UserProblemNo = 0
GPOOptimized = 0
GPONotOptimized = 0
GPOProblem = 0
GPONoProblem = 0
GPONotLinked = 0
GPOLinked = 0
GPOEmpty = 0
GPONotEmpty = 0
GPOEmptyAndUnlinked = 0
GPOEmptyOrUnlinked = 0
GPOLinkedButEmpty = 0
GPOEnabled = 0
GPODisabled = 0
GPOSkip = 0
GPOSkipExcluded = 0
GPOValid = 0
GPONotValid = 0
GPONotValidButSkip = 0
GPONotValidButExcluded = 0
GPONotValidButSkippedOrExcluded = 0
GPOLinkedButLinkDisabled = 0
GPOTotal = 0
ApplyPermissionYes = 0
ApplyPermissionNo = 0
}
Overview = {
@@ -203,6 +213,7 @@
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies total: ', $Script:Reporting['GPOList']['Variables']['GPOTotal'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies valid: ", $Script:Reporting['GPOList']['Variables']['GPOValid'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies exclusions defined: ", $Script:Reporting['GPOList']['Variables']['GPOSkipExcluded'] -FontWeight normal, bold -Color None, DeepSkyBlue
New-HTMLListItem -Text "Group Policies ", "NOT", " valid: ", $Script:Reporting['GPOList']['Variables']['GPONotValid'] -FontWeight normal, bold, normal, bold {
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies that are unlinked (are not doing anything currently): ', $Script:Reporting['GPOList']['Variables']['GPONotLinked'] -FontWeight normal, bold
@@ -214,7 +225,10 @@
}
} -Color Black, Red, Black, Red, Black
New-HTMLListItem -Text @(
"Group Policies ", "NOT", " valid, to skip: ", $Script:Reporting['GPOList']['Variables']['GPONotValidButSkip'], " (modified less than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days ago)"
"Group Policies ", "NOT", " valid, to skip (because of age): ", $Script:Reporting['GPOList']['Variables']['GPONotValidButSkip'], " (modified less than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days ago)"
) -FontWeight 'normal', 'bold', 'normal', 'bold', 'normal' -Color 'Black', 'Red', 'Black', 'Red', 'Black'
New-HTMLListItem -Text @(
"Group Policies ", "NOT", " valid, to skip (because of exclusions): ", $Script:Reporting['GPOList']['Variables']['GPONotValidButExcluded']
) -FontWeight 'normal', 'bold', 'normal', 'bold', 'normal' -Color 'Black', 'Red', 'Black', 'Red', 'Black'
New-HTMLListItem -Text "Group Policies recently modified: ", $Script:Reporting['GPOList']['Variables']['GPOSkip'], " (modified less than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days ago)" -FontWeight normal, bold
} -FontSize 10pt
@@ -299,6 +313,22 @@
New-HTMLListItem -Text 'Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPListBefore.html -Verbose -Type GPOList' -Color RoyalBlue
} -FontSize 10pt
New-HTMLText -FontSize 10pt -Text 'Steps above will generate above summary with more details allowing you to get up to date report and steps on how to fix it.'
if ($Script:Reporting['GPOList']['Exclusions']) {
New-HTMLText -LineBreak
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
) -FontSize 10pt -FontWeight bold, normal -Color Red, None -LineBreak
New-HTMLText -Text "Code to use for exclusions: " -FontSize 10pt -FontWeight bold -LineBreak
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOList']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
Solution = {
New-HTMLSection -Invisible {
@@ -358,7 +388,7 @@
New-HTMLTableCondition -Name 'UserProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'UserOptimized' -Value $true -BackgroundColor SpringGreen -TextTransform capitalize -ComparisonType string
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
} -PagingOptions 10, 20, 30, 40, 50
}
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
@@ -375,6 +405,18 @@
} -Style powershell
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
}
if ($Script:Reporting['GPOList']['Exclusions']) {
New-HTMLWizardStep -Name 'Required exclusions' {
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
)
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOList']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
New-HTMLWizardStep -Name 'Prepare report' {
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with removal. To generate new report please use:"
New-HTMLCodeBlock -Code {
@@ -415,11 +457,14 @@
"You would do so using following approach "
) -FontSize 10pt -FontWeight bold, normal
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -RequireDays 30 -Type Empty, Unlinked, Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor' {
$Exclusions = {
Skip-GroupPolicy -Name 'TEST | Drive Mapping'
Skip-GroupPolicy -Name 'Default Domain Policy'
Skip-GroupPolicy -Name 'Default Domain Controllers Policy' -DomaiName 'JustOneDomain'
} -WhatIf
'{D39BF08A-87BF-4662-BFA0-E56240EBD5A2}'
'COMPUTERS | Enable Sets'
}
Remove-GPOZaurr -RequireDays 30 -Type Empty, Unlinked, Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor' -WhatIf -ExcludeGroupPolicies $Exclusions
}
New-HTMLText -Text @(
"Code above when executed will scan YourDomainYouHavePermissionsFor, find all empty, unlinked, disabled group policies, backup any GPO just before it's to be deleted to `$Env:UserProfile\Desktop\GPO. "
@@ -646,6 +691,7 @@
}
}
}
<#
if ($Script:Reporting['GPOList']['Exclusions']) {
New-HTMLSection -Invisible {
New-HTMLSection -Name 'Group Policies Exclusions' {
@@ -656,11 +702,12 @@
New-HTMLSection -Name 'Group Policies Exclusions Code' {
New-HTMLContainer {
New-HTMLText -Text 'Please make sure to use following exclusions when executing removal' -FontSize 10pt
New-HTMLCodeBlock -Code $Script:Reporting['GPOList']['ExclusionsCode']
New-HTMLCodeBlock -Code $Script:Reporting['GPOList']['Exclusions']
}
}
}
}
#>
}
if ($Script:Reporting['GPOList']['WarningsAndErrors']) {
New-HTMLSection -Name 'Errors to Review' {
+1 -1
View File
@@ -135,7 +135,7 @@
New-HTMLTableCondition -Name 'OwnerType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor Salmon -ComparisonType string -Operator ne
} -SearchBuilder
}
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix NetLogon Owners ' {
+1 -92
View File
@@ -125,97 +125,6 @@
New-HTMLText -Text "Please review output in table and follow the steps below table to get NetLogon permissions in order." -FontSize 10pt
}
Solution = {
# New-HTMLTab -Name 'NetLogon Owners' {
# New-HTMLSection -Invisible {
# New-HTMLPanel {
# & $Script:GPOConfiguration['NetLogonPermissions']['Summary']
# }
# New-HTMLPanel {
# New-HTMLChart {
# New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
# New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -Color Crimson
# } -Title 'NetLogon Owners' -TitleAlignment center
# }
# }
# New-HTMLSection -Name 'NetLogon File Owners' {
# New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Variables']['Owner'] -Filtering {
# New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor LightGreen -ComparisonType string
# New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor Salmon -ComparisonType string -Operator ne
# New-HTMLTableCondition -Name 'PrincipalType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
# New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
# New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor Salmon -ComparisonType string -Operator ne
# }
# }
# New-HTMLSection -Name 'Steps to fix NetLogon Owners ' {
# New-HTMLContainer {
# New-HTMLSpanStyle -FontSize 10pt {
# New-HTMLText -Text 'Following steps will guide you how to fix NetLogon Owners and make them compliant.'
# New-HTMLWizard {
# New-HTMLWizardStep -Name 'Prepare environment' {
# New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
# New-HTMLCodeBlock -Code {
# Install-Module GPOZaurr -Force
# Import-Module GPOZaurr -Force
# } -Style powershell
# New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
# }
# New-HTMLWizardStep -Name 'Prepare report' {
# New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with removal. To generate new report please use:"
# New-HTMLCodeBlock -Code {
# Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonBefore.html -Verbose -Type NetLogon
# }
# New-HTMLText -TextBlock {
# "When executed it will take a while to generate all data and provide you with new report depending on size of environment."
# "Once confirmed that data is still showing issues and requires fixing please proceed with next step."
# }
# New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
# New-HTMLCodeBlock -Code {
# $NetLogonOutput = Get-GPOZaurrNetLogon -OwnerOnly -Verbose
# $NetLogonOutput | Format-Table
# }
# New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
# }
# New-HTMLWizardStep -Name 'Set non-compliant file owners to BUILTIN\Administrators' {
# New-HTMLText -Text "Following command when executed runs internally command that lists all file owners and if it doesn't match changes it BUILTIN\Administrators. It doesn't change compliant owners."
# New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
# New-HTMLCodeBlock -Code {
# Repair-GPOZaurrNetLogonOwner -Verbose -WhatIf
# }
# New-HTMLText -TextBlock {
# "After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data. Once happy with results please follow with command: "
# }
# New-HTMLCodeBlock -Code {
# Repair-GPOZaurrNetLogonOwner -Verbose -LimitProcessing 2
# }
# New-HTMLText -TextBlock {
# "This command when executed sets new owner only on first X non-compliant NetLogon files. Use LimitProcessing parameter to prevent mass change and increase the counter when no errors occur."
# "Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
# }
# }
# New-HTMLWizardStep -Name 'Verification report' {
# New-HTMLText -TextBlock {
# "Once cleanup task was executed properly, we need to verify that report now shows no problems."
# }
# New-HTMLCodeBlock -Code {
# Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonAfter.html -Verbose -Type NetLogon
# }
# New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
# }
# } -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
# }
# }
# }
# if ($Script:Reporting['NetLogonPermissions']['WarningsAndErrors']) {
# New-HTMLSection -Name 'Warnings & Errors to Review' {
# New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['WarningsAndErrors'] -Filtering {
# New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
# New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
# }
# }
# }
# }
#New-HTMLTab -Name 'NetLogon Permissions' {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['NetLogonPermissions']['Summary']
@@ -237,7 +146,7 @@
New-HTMLTableCondition -Name 'Status' -Value "Review permission required" -BackgroundColor PaleGoldenrod -ComparisonType string -Operator eq
New-HTMLTableCondition -Name 'Status' -Value "Removal permission required" -BackgroundColor Salmon -ComparisonType string -Operator eq -Row
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
} -SearchBuilder
}
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix NetLogon Permissions ' {
@@ -0,0 +1,262 @@
$GPOZaurrOrganizationalUnit = [ordered] @{
Name = 'Group Policy Organizational Units'
Enabled = $true
ActionRequired = $null
Data = $null
Execute = {
if ($Script:Reporting['GPOOrganizationalUnit']['Exclusions']) {
Get-GPOZaurrOrganizationalUnit -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeOrganizationalUnit $Script:Reporting['GPOOrganizationalUnit']['Exclusions']
} else {
Get-GPOZaurrOrganizationalUnit -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
}
Processing = {
# Create Per Domain Variables
$Script:Reporting['GPOOrganizationalUnit']['Variables']['RequiresDiffFixPerDomain'] = @{}
$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'] = @{}
foreach ($OU in $Script:Reporting['GPOOrganizationalUnit']['Data']) {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['TotalOU']++
# Create Per Domain Variables
if (-not $Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$OU.DomainName]) {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$OU.DomainName] = 0
}
if ($OU.Status -contains 'Unlink GPO' -and $OU.Status -contains 'Delete OU') {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPOEmpty']++
$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFix']++
$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$OU.DomainName]++
} elseif ($OU.Status -contains 'Unlink GPO') {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPO']++
$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFix']++
$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$OU.DomainName]++
} elseif ($OU.Status -contains 'Delete OU') {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['DeleteOU']++
#$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFix']++
#$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$OU.DomainName]++
} elseif ($OU.Status -contains 'Excluded') {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['Excluded']++
$Script:Reporting['GPOOrganizationalUnit']['Variables']['ExcludedOU'].Add($OU.Organizationalunit)
} else {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['Legitimate']++
}
}
if ($Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFix'] -gt 0) {
$Script:Reporting['GPOOrganizationalUnit']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOOrganizationalUnit']['ActionRequired'] = $false
}
}
Variables = @{
TotalOU = 0
UnlinkGPO = 0
UnlinkGPOEmpty = 0
DeleteOU = 0
Legitimate = 0
Excluded = 0
ExcludedOU = [System.Collections.Generic.List[string]]::new()
WillFix = 0
WillFixPerDomain = $null
}
Overview = {
}
Summary = {
New-HTMLText -FontSize 10pt -Text @(
"In most Active Directories there are a lot of Organizational Units that have different use cases to store different type of objects. "
"As Active Directories change over time you can often find Organizational Units with linked GPOs and no objects inside. "
"In some cases thats's expected, but in some cases it's totally unnessecary, and for very large AD can be a problem. "
"Additionally only User and Computer objects can have GPO applied to them, so having GPO applied to a any other object type won't really work. "
)
New-HTMLText -FontSize 10pt -Text "Following can happen: " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Organizational Units that can have Group Policies unlinked (objects exists): ', $Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPO'] -FontWeight normal, bold
New-HTMLListItem -Text 'Organizational Units that can have Group Policies unlinked (no applicable objects): ', $Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPOEmpty'] -FontWeight normal, bold
New-HTMLListItem -Text "Organizational Units that can be deleted (no objects/no gpos) - ", "optional", ": ", $Script:Reporting['GPOOrganizationalUnit']['Variables']['DeleteOU'] -FontWeight normal, bold, normal, bold -Color None, red, None, None
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
if ($Script:Reporting['GPOOrganizationalUnit']['Variables']['ExcludedOU'].Count -gt 0) {
New-HTMLText -Text @(
'There are ',
$Script:Reporting['GPOOrganizationalUnit']['Variables']['ExcludedOU'].Count,
" Organizational Units that are excluded.",
" Please make sure to exclude those when executing unlinking/removal procedures. "
) -FontSize 10pt -FontWeight normal, bold, normal, bold -Color None, Red, None, Red
<#
New-HTMLList -Type Unordered {
foreach ($OU in $Script:Reporting['GPOOrganizationalUnit']['Variables']['ExcludedOU']) {
New-HTMLListItem -Text $OU -FontWeight normal, bold, normal
}
} -FontSize 10pt
#>
}
New-HTMLText -Text @(
"Please make sure that you really want to unlink GPO or delete Organizational Unit before executing changes. Sometimes it's completly valid to keep one or the other. "
"Unlinking GPO from OU that has no Computer or User objects is fairly safe exercise. Removing OU requires a bit more dive in, and should only be executed if you know what you're doing. "
) -FontWeight normal, bold -Color None, Red -FontSize 10pt
if ($Script:Reporting['GPOOrganizationalUnit']['Exclusions']) {
New-HTMLText -LineBreak
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
) -FontSize 10pt -FontWeight bold, normal -Color Red, None -LineBreak
New-HTMLText -Text "Code to use for exclusions: " -FontSize 10pt -FontWeight bold -LineBreak
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOOrganizationalUnit']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOOrganizationalUnit']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type bar -Distributed
New-ChartAxisY -LabelMaxWidth 200 -LabelAlign left -Show
New-ChartBar -Name "Unlink GPO ($($Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPO']))" -Value $Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPO']
New-ChartBar -Name "Unlink GPO Delete OU ($($Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPOEmpty']))" -Value $Script:Reporting['GPOOrganizationalUnit']['Variables']['UnlinkGPOEmpty']
New-ChartBar -Name "Delete OU ($($Script:Reporting['GPOOrganizationalUnit']['Variables']['DeleteOU']))" -Value $Script:Reporting['GPOOrganizationalUnit']['Variables']['DeleteOU']
} -Title 'Organizational Units' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policy Organizational Units' {
New-HTMLTable -DataTable $Script:Reporting['GPOOrganizationalUnit']['Data'] -Filtering {
New-TableHeader -ResponsiveOperations none -Names 'GPONames', 'Objects'
New-HTMLTableCondition -Name 'Status' -ComparisonType string -Value 'Unlink GPO, Delete OU' -BackgroundColor Salmon -Row
New-HTMLTableCondition -Name 'Status' -ComparisonType string -Value 'Unlink GPO' -BackgroundColor YellowOrange -Row
New-HTMLTableCondition -Name 'Status' -ComparisonType string -Value 'Delete OU' -BackgroundColor Red -Row
New-HTMLTableCondition -Name 'Status' -ComparisonType string -Value 'OK' -BackgroundColor LightGreen -Row
New-HTMLTableCondition -Name 'Status' -ComparisonType string -Value 'Excluded' -BackgroundColor DeepSkyBlue -Row
} -PagingOptions 10, 20, 30, 40, 50 -ExcludeProperty GPO
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Organizational Units' {
New-HTMLContainer {
New-HTMLSpanStyle -FontSize 10pt {
#New-HTMLText -Text 'Following steps will guide you how to fix group policy owners'
New-HTMLWizard {
New-HTMLWizardStep -Name 'Prepare environment' {
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
New-HTMLCodeBlock -Code {
Install-Module GPOZaurr -Force
Import-Module GPOZaurr -Force
} -Style powershell
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
}
if ($Script:Reporting['GPOOrganizationalUnit']['Exclusions']) {
New-HTMLWizardStep -Name 'Required exclusions' {
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
)
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOOrganizationalUnit']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
New-HTMLWizardStep -Name 'Prepare report' {
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with unlinking unused Group Policies. To generate new report please use:"
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOOrganizationalUnitBefore.html -Verbose -Type GPOOrganizationalUnit
}
New-HTMLText -TextBlock {
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
}
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
New-HTMLCodeBlock -Code {
$OwnersGPO = Get-GPOZaurrOrganizationalUnit -Verbose
$OwnersGPO | Format-Table
}
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
}
New-HTMLWizardStep -Name 'Unlink unused Group Policies' {
New-HTMLText -Text @(
"Following command when executed runs cleanup procedure that unlinks all Group Policies from Organizational Units that have no user or computer objects. "
"Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental unlinking."
'When run it will remove any GPO links from Organizational Units that have no objects applicable for GPOs.'
) -FontWeight normal, normal, bold, normal -Color Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurrLinkEmptyOU -WhatIf -Verbose
}
New-HTMLText -TextBlock {
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurrLinkEmptyOU -WhatIf -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be removed matches expected data. "
"Keep in mind that there is no backup for this, and if link is removed you would need to relink it yourself."
"Once you remove it, it's gone. "
} -LineBreak
New-HTMLText -Text 'Once happy with results please follow with command (this will start removal process): ' -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurrLinkEmptyOU -WhatIf -LimitProcessing 2 -Verbose
}
New-HTMLText -TextBlock {
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurrLinkEmptyOU -WhatIf -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed deletes only first X broken GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
} -LineBreak
New-HTMLText -TextBlock {
"It's possible to exclude certain OU's from having GPO's unlinked using follwing method: "
} -FontWeight bold
New-HTMLCodeBlock -Code {
$Exclude = @(
"OU=Groups,OU=Production,DC=ad,DC=evotec,DC=pl"
"OU=Test \, OU,OU=ITR02,DC=ad,DC=evotec,DC=xyz"
)
Remove-GPOZaurrLinkEmptyOU -Verbose -LimitProcessing 3 -WhatIf -ExcludeOrganizationalUnit $Exclude
}
}
New-HTMLWizardStep -Name 'Delete unused Organizational Units' {
New-HTMLText -Text @(
"Following automation is not yet implemented. Requires more testing as potentially it could do more damage than help."
)
}
New-HTMLWizardStep -Name 'Verification report' {
New-HTMLText -TextBlock {
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
}
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOOrganizationalUnitAfter.html -Verbose -Type GPOOrganizationalUnit
}
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
}
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
}
if ($Script:Reporting['GPOOrganizationalUnit']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOOrganizationalUnit']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 10, 20, 30, 40, 50
}
}
}
}
+2 -2
View File
@@ -99,7 +99,7 @@
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies which exists, but have wrong ObjectClass: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssue'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which couldn't be assessed due to permissions issue: ", $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
@@ -128,7 +128,7 @@
New-HTMLTableCondition -Name 'Status' -Value "Not available on SYSVOL" -BackgroundColor LightCoral -ComparisonType string
New-HTMLTableCondition -Name 'Status' -Value "ObjectClass issue" -BackgroundColor MediumOrchid -ComparisonType string
New-HTMLTableCondition -Name 'Status' -Value "Permissions issue" -BackgroundColor MediumVioletRed -ComparisonType string -Color White
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory / ObjectClass issue' {
+89 -10
View File
@@ -4,7 +4,11 @@
ActionRequired = $null
Data = $null
Execute = {
Get-GPOZaurrOwner -IncludeSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
if ($Script:Reporting['GPOOwners']['Exclusions']) {
Get-GPOZaurrOwner -IncludeSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ApprovedOwner $Script:Reporting['GPOOwners']['Exclusions']
} else {
Get-GPOZaurrOwner -IncludeSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
}
Processing = {
# Create Per Domain Variables
@@ -19,17 +23,35 @@
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName] = 0
}
# Checks
if ($GPO.IsOwnerConsistent) {
if ($GPO.Status -contains 'Consistent') {
$Script:Reporting['GPOOwners']['Variables']['IsConsistent']++
} else {
} elseif ($GPO.Status -contains 'Inconsistent') {
$Script:Reporting['GPOOwners']['Variables']['IsNotConsistent']++
}
if ($GPO.IsOwnerAdministrative) {
if ($GPO.Status -contains 'Administrative') {
$Script:Reporting['GPOOwners']['Variables']['IsAdministrative']++
} elseif ($GPO.Status -contains 'Approved') {
$Script:Reporting['GPOOwners']['Variables']['IsApproved']++
} else {
$Script:Reporting['GPOOwners']['Variables']['IsNotAdministrative']++
}
if (($GPO.IsOwnerAdministrative -eq $false -or $GPO.IsOwnerConsistent -eq $false) -and $GPO.SysvolExists -eq $true) {
if ($GPO.SysvolExists -eq $false) {
$Script:Reporting['GPOOwners']['Variables']['RequiresDiffFix']++
$Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'][$GPO.DomainName]++
} else {
if ($GPO.Status -contains 'Inconsistent') {
$Script:Reporting['GPOOwners']['Variables']['WillFix']++
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
} elseif ($GPO.Status -contains 'NotAdministrative' -and $GPO.Status -notcontains 'Approved') {
$Script:Reporting['GPOOwners']['Variables']['WillFix']++
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOOwners']['Variables']['WillNotTouch']++
}
}
<#
if (($GPO.IsOwnerAdministrative -eq $false -or $GPO.IsOwnerConsistent -eq $false) -and $GPO.Status -and $GPO.SysvolExists -eq $true) {
$Script:Reporting['GPOOwners']['Variables']['WillFix']++
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
} elseif ($GPO.SysvolExists -eq $false) {
@@ -38,6 +60,7 @@
} else {
$Script:Reporting['GPOOwners']['Variables']['WillNotTouch']++
}
#>
}
if ($Script:Reporting['GPOOwners']['Variables']['WillFix'] -gt 0) {
$Script:Reporting['GPOOwners']['ActionRequired'] = $true
@@ -47,6 +70,7 @@
}
Variables = @{
IsAdministrative = 0
IsApproved = 0
IsNotAdministrative = 0
IsConsistent = 0
IsNotConsistent = 0
@@ -93,6 +117,7 @@
New-HTMLText -Text "Here's a short summary of ", "Group Policy Owners", ": " -FontSize 10pt -FontWeight normal, bold, normal
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Administrative Owners: ', $Script:Reporting['GPOOwners']['Variables']['IsAdministrative'] -FontWeight normal, bold
New-HTMLListItem -Text 'Non-Administrative, but approved Owners (for example AGPM): ', $Script:Reporting['GPOOwners']['Variables']['IsApproved'] -FontWeight normal, bold
New-HTMLListItem -Text 'Non-Administrative Owners: ', $Script:Reporting['GPOOwners']['Variables']['IsNotAdministrative'] -FontWeight normal, bold
New-HTMLListItem -Text "Owners consistent in AD and SYSVOL: ", $Script:Reporting['GPOOwners']['Variables']['IsConsistent'] -FontWeight normal, bold
New-HTMLListItem -Text "Owners not-consistent in AD and SYSVOL: ", $Script:Reporting['GPOOwners']['Variables']['IsNotConsistent'] -FontWeight normal, bold
@@ -115,6 +140,22 @@
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
if ($Script:Reporting['GPOOwners']['Exclusions']) {
New-HTMLText -LineBreak
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
) -FontSize 10pt -FontWeight bold, normal -Color Red, None -LineBreak
New-HTMLText -Text "Code to use for exclusions: " -FontSize 10pt -FontWeight bold -LineBreak
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOOwners']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
Solution = {
New-HTMLSection -Invisible {
@@ -124,17 +165,26 @@
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, Salmon
New-ChartBar -Name 'Is administrative' -Value $Script:Reporting['GPOOwners']['Variables']['IsAdministrative'], $Script:Reporting['GPOOwners']['Variables']['IsNotAdministrative']
New-ChartLegend -Name 'Yes', 'No', 'Approved' -Color LightGreen, Salmon, DeepSkyBlue
New-ChartBar -Name 'Is administrative' -Value $Script:Reporting['GPOOwners']['Variables']['IsAdministrative'], $Script:Reporting['GPOOwners']['Variables']['IsNotAdministrative'], $Script:Reporting['GPOOwners']['Variables']['IsApproved']
New-ChartBar -Name 'Is consistent' -Value $Script:Reporting['GPOOwners']['Variables']['IsConsistent'], $Script:Reporting['GPOOwners']['Variables']['IsNotConsistent']
} -Title 'Group Policy Owners' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policy Owners' {
New-HTMLTable -DataTable $Script:Reporting['GPOOwners']['Data'] -Filtering {
New-HTMLTableCondition -Name 'IsOwnerConsistent' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
New-HTMLTableCondition -Name 'IsOwnerAdministrative' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
#New-HTMLTableCondition -Name 'IsOwnerConsistent' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
#New-HTMLTableCondition -Name 'IsOwnerAdministrative' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
New-HTMLTableCondition -Name 'Status' -Value 'Administrative, Consistent' -BackgroundColor LightGreen -ComparisonType string -Row
New-HTMLTableCondition -Name 'Status' -Value 'NotAdministrative, Consistent, Approved' -BackgroundColor DeepSkyBlue -ComparisonType string -Row
New-HTMLTableCondition -Name 'Status' -Value 'Administrative, Inconsistent' -BackgroundColor Salmon -ComparisonType string -Row
New-HTMLTableCondition -Name 'Status' -Value 'NotAdministrative, Inconsistent' -BackgroundColor Salmon -ComparisonType string -Row
#New-HTMLTableCondition -Name 'Status' -Value 'Administrative, Inconsistent, Approved' -BackgroundColor Salmon -ComparisonType string -Row
# New-HTMLTableCondition -Name 'Status' -Value 'NotAdministrative, Inconsistent, Approved' -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Owners' {
@@ -150,6 +200,19 @@
} -Style powershell
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
}
if ($Script:Reporting['GPOOwners']['Exclusions']) {
New-HTMLWizardStep -Name 'Required exclusions' {
New-HTMLText -Text @(
"While preparing this report following exclusions were defined. "
"Please make sure that when you execute your steps to include those exclusions to prevent any issues. "
)
$Code = New-GPOZaurrExclusions -ExclusionsArray $Script:Reporting['GPOOwners']['Exclusions']
if ($Code) {
New-HTMLCodeBlock -Code $Code -Style powershell
}
}
}
New-HTMLWizardStep -Name 'Prepare report' {
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with fixing Group Policy Owners. To generate new report please use:"
New-HTMLCodeBlock -Code {
@@ -207,6 +270,22 @@
New-HTMLText -TextBlock {
"This command when executed sets new owner only on first X non-compliant GPO Owners for AD/SYSVOL. Use LimitProcessing parameter to prevent mass change and increase the counter when no errors occur. "
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
} -LineBreak
New-HTMLText -TextBlock {
"It's possible to define certain owners as being approved (for example with domain that have AGPM). "
"Make sure to verify if excluded/approved owners were provided in Required Exclusions tab, or add your own when nessecary. "
"You can approve owners with following code: "
} -FontWeight bold
New-HTMLCodeBlock -Code {
$Approved = @(
'EVOTEC\przemyslaw.klys'
'EVOTEC\green.b'
)
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -ApprovedOwner $Approved
}
New-HTMLText -TextBlock {
"Please keep in mind that ApprovedOwner is only applicable to Non-Administrative permissions to provide a way to approve special use cases. "
"It won't do anything for inconsistent, unknown permissions as those are still treated as wrong. "
}
}
New-HTMLWizardStep -Name 'Verification report' {
+1 -1
View File
@@ -23,7 +23,7 @@
New-HTMLTable -DataTable $Script:Reporting['GPOPassword']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -SearchBuilder
}
}
}
}
@@ -94,12 +94,12 @@
New-HTMLSection -Name 'Group Policy Administrative Users Permissions Summary' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsAdministrative']['Data'].PermissionsPerRow -Filtering {
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60
}
New-HTMLSection -Name 'Group Policy Administrative Users Analysis' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsAdministrative']['Data'].PermissionsAnalysis -Filtering {
# New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
@@ -309,7 +309,7 @@
New-HTMLSection -Name 'Group Policy Visibility Analysis' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'].PermissionsIssues -Filtering {
New-HTMLTableCondition -Name 'PermissionIssue' -Value $true -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending
}
New-HTMLSection -Name 'Group Policy Permissions Analysis' {
New-HTMLContainer {
@@ -344,7 +344,7 @@
New-HTMLTableCondition -Name 'EnterpriseAdmins' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
New-TableEvent -TableID 'GPOPermissionsAll' -SourceColumnName 'GUID' -TargetColumnID 1 # TargetColumnID 1 eq GUID on the other table
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60
}
}
New-HTMLSection -Name 'All Permissions' {
@@ -355,7 +355,7 @@
New-HTMLTableCondition -Name 'Permission' -Value 'GpoApply' -BackgroundColor Orange -ComparisonType string
New-HTMLTableCondition -Name 'Permission' -Value 'GpoRead' -BackgroundColor MediumSpringGreen -ComparisonType string -Operator eq
New-HTMLTableCondition -Name 'PrincipalSidType' -Value 'Unknown' -BackgroundColor Salmon -ComparisonType string -Operator eq
} -PagingOptions 7, 15, 30, 45, 60 -DataTableID 'GPOPermissionsAll' -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60 -DataTableID 'GPOPermissionsAll'
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
+2 -2
View File
@@ -151,12 +151,12 @@
New-HTMLSection -Name 'Group Policy Authenticated Users Analysis' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['Data'].Permissions -Filtering {
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60
}
New-HTMLSection -Name 'Group Policy Issues Assesment' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['Data'].Issues -Filtering {
New-HTMLTableCondition -Name 'PermissionIssue' -Value $true -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Authenticated Users' {
+1 -1
View File
@@ -22,7 +22,7 @@
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRoot']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
} -SearchBuilder
}
}
}
}
@@ -71,7 +71,7 @@
New-HTMLSection -Name 'Group Policy Unknown Permissions Analysis' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsUnknown']['Data'] -Filtering {
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
} -PagingOptions 7, 15, 30, 45, 60
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Unknown Permissions' {
+33
View File
@@ -0,0 +1,33 @@
function New-GPOZaurrExclusions {
[cmdletBinding()]
param(
[alias('ExcludeGroupPolicies', 'ExclusionsCode', 'ExclusionsArray')][Parameter(Position = 1)][object] $Exclusions
)
if ($Exclusions) {
if ($Exclusions -is [scriptblock]) {
#$Script:Reporting[$T]['Exclusions'] = $Exclusions
#$Script:Reporting[$T]['ExclusionsCode'] = $Exclusions
[string] $Code = @(
"`$Exclusions = {"
" " + $Exclusions.ToString()
"}"
)
$Code
}
if ($Exclusions -is [Array]) {
#$Script:Reporting[$T]['Exclusions'] = $Exclusions
#$ExclusionsArray = $Exclusions
[string] $Code = @(
'$Exclusions = @('
[System.Environment]::NewLine
foreach ($Exclusion in $Exclusions) {
" `"$Exclusion`"" + [System.Environment]::NewLine
}
[System.Environment]::NewLine
')'
)
$Code
}
}
}
+2
View File
@@ -4,6 +4,7 @@
GPOOwners = $GPOZaurrOwners
GPOConsistency = $GPOZaurrConsistency
GPODuplicates = $GPOZaurrDuplicates
GPOOrganizationalUnit = $GPOZaurrOrganizationalUnit
GPOList = $GPOZaurrList
GPOLinks = $GPOZaurrLinks
GPOPassword = $GPOZaurrPassword
@@ -15,6 +16,7 @@
GPOFiles = $GPOZaurrFiles
GPOBlockedInheritance = $GPOZaurrBlockedInheritance
GPOAnalysis = $GPOZaurrAnalysis
GPOUpdates = $GPOZaurrGPOUpdates
NetLogonOwners = $GPOZaurrNetLogonOwners
NetLogonPermissions = $GPOZaurrNetLogonPermissions
SysVolLegacyFiles = $GPOZaurrSysVolLegacyFiles
+40 -2
View File
@@ -10,6 +10,11 @@
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[DateTime] $DateFrom,
[DateTime] $DateTo,
[ValidateSet('PastHour', 'CurrentHour', 'PastDay', 'CurrentDay', 'PastMonth', 'CurrentMonth', 'PastQuarter', 'CurrentQuarter', 'Last14Days', 'Last21Days', 'Last30Days', 'Last7Days', 'Last3Days', 'Last1Days')][string] $DateRange,
[ValidateSet('WhenCreated', 'WhenChanged')][string[]] $DateProperty = 'WhenCreated',
[System.Collections.IDictionary] $ExtendedForestInformation
)
Begin {
@@ -48,7 +53,39 @@
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
}
Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName | ForEach-Object -Process {
# allows to only get GPOs from a specific date range
if ($PSBoundParameters.ContainsKey('DateRange')) {
$Dates = Get-ChoosenDates -DateRange $DateRange
$DateFrom = $($Dates.DateFrom)
$DateTo = $($Dates.DateTo)
if ($DateProperty -contains 'WhenChanged' -and $DateProperty -contains 'WhenCreated') {
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ((WhenChanged -ge $DateFrom -and WhenChanged -le $DateTo) -or (WhenCreated -ge $DateFrom -and WhenCreated -le $DateTo))')
} elseif ($DateProperty -eq 'WhenChanged' -or $DateProperty -eq 'WhenCreated') {
$Property = $DateProperty[0]
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ($Property -ge $DateFrom -and $Property -le $DateTo)')
} else {
Write-Warning -Message "Get-GPOZaurrAD - DateProperty parameter is empty. Provide name and try again."
continue
}
} elseif ($PSBoundParameters.ContainsKey('DateFrom') -and $PSBoundParameters.ContainsKey('DateTo')) {
# already set $DateFrom,DateTo
#$Splat['Filter'] = -join ($Splat['Filter'], '-and ($DateProperty -ge $DateFrom -and $DateProperty -le $DateTo)')
if ($DateProperty -contains 'WhenChanged' -and $DateProperty -contains 'WhenCreated') {
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ((WhenChanged -ge $DateFrom -and WhenChanged -le $DateTo) -or (WhenCreated -ge $DateFrom -and WhenCreated -le $DateTo))')
} elseif ($DateProperty -eq 'WhenChanged' -or $DateProperty -eq 'WhenCreated') {
$Property = $DateProperty[0]
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ($Property -ge $DateFrom -and $Property -le $DateTo)')
} else {
Write-Warning -Message "Get-GPOZaurrAD - DateProperty parameter is empty. Provide name and try again."
continue
}
} else {
# not needed
}
Write-Verbose -Message "Get-GPOZaurrAD - Searching domain $Domain with filter $($Splat['Filter'])"
Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, ntSecurityDescriptor, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName | ForEach-Object -Process {
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDomainCN
$GUID = $_.Name -replace '{' -replace '}'
if (($GUID).Length -ne 36) {
@@ -60,9 +97,10 @@
$Output['Description'] = $_.Description
$Output['GUID'] = $GUID
$Output['Path'] = $_.gPCFileSysPath
$Output['FunctionalityVersion'] = $_.gPCFunctionalityVersion
#$Output['FunctionalityVersion'] = $_.gPCFunctionalityVersion
$Output['Created'] = $_.Created
$Output['Modified'] = $_.Modified
$Output['Owner'] = $_.ntSecurityDescriptor.Owner
$Output['GPOCanonicalName'] = $_.CanonicalName
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDC
$Output['GPODistinguishedName'] = $_.DistinguishedName
+7 -3
View File
@@ -72,9 +72,13 @@
# That's why we use $ForestInformation.Forest.Domains instead
foreach ($Domain in $ForestInformation.Forest.Domains) {
Write-Verbose "Get-GPOZaurrLink - Building GPO cache for domain $Domain"
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
$GPOCache["$Domain$($_.ID.Guid)"] = $_
if ($ForestInformation['QueryServers'][$Domain]) {
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
$GPOCache["$Domain$($_.ID.Guid)"] = $_
}
} else {
Write-Warning -Message "Get-GPOZaurrLink - Couldn't get query server for $Domain. Skipped."
}
}
}
+150
View File
@@ -0,0 +1,150 @@
function Get-GPOZaurrOrganizationalUnit {
[CmdletBinding()]
param(
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation,
[ValidateSet('OK', 'Unlink', 'Delete')][string[]] $Option,
[alias('ExcludeOU', 'Exclusions')][string[]] $ExcludeOrganizationalUnit
)
$CachedOu = [ordered] @{}
$CachedGPO = [ordered] @{}
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
$GroupPolicies = Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
foreach ($GPO in $GroupPolicies) {
$CachedGPO[$GPO.GPODistinguishedName] = $GPO
}
foreach ($Domain in $ForestInformation.Domains) {
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain)"
$CountTop = 0
$TopOrganizationalUnits = Get-ADOrganizationalUnit -Filter * -Properties LinkedGroupPolicyObjects, DistinguishedName, ntSecurityDescriptor -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0] -SearchScope OneLevel
foreach ($TopOU in $TopOrganizationalUnits) {
$CountTop++
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)]"
# cache top ou
if ($TopOU.LinkedGroupPolicyObjects) {
$LinkedGPOs = $CachedGPO[$TopOU.LinkedGroupPolicyObjects]
} else {
$LinkedGPOs = $null
}
$CachedOu[$TopOU.DistinguishedName] = [ordered]@{
'LinkedGroupPolicyObjects' = $TopOU.LinkedGroupPolicyObjects
'LinkedGroupPolicy' = $LinkedGPOs
'Objects' = [ordered] @{}
'ObjectsClasses' = [ordered] @{}
'ObjectsCountDirect' = 0
'ObjectsCountIndirect' = 0
'ObjectsCountTotal' = 0
'Level' = 'Top'
'RootLevel' = $TopOU.Name
'Domain' = $Domain
}
# cache children OUs
$OUs = Get-ADOrganizationalUnit -SearchScope Subtree -SearchBase $TopOU.DistinguishedName -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0] -Properties LinkedGroupPolicyObjects, DistinguishedName -Filter *
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)], found $($OUs.Count) OU's to process."
foreach ($OU in $OUs) {
if (-not $CachedOu[$OU.DistinguishedName]) {
if ($OU.LinkedGroupPolicyObjects) {
$LinkedGPOs = $CachedGPO[$OU.LinkedGroupPolicyObjects]
} else {
$LinkedGPOs = $null
}
$CachedOu[$OU.DistinguishedName] = [ordered]@{
'LinkedGroupPolicyObjects' = $OU.LinkedGroupPolicyObjects
'LinkedGroupPolicy' = $LinkedGPOs
'Objects' = [ordered] @{}
'ObjectsClasses' = [ordered] @{}
'ObjectsCountDirect' = 0
'ObjectsCountIndirect' = 0
'ObjectsCountTotal' = 0
'Level' = 'Child'
'RootLevel' = $TopOU.Name
'Domain' = $Domain
}
}
}
# Find all objects in those OUs
$ObjectsInOu = Get-ADObject -LDAPFilter "(|(ObjectClass=user)(ObjectClass=contact)(ObjectClass=computer)(ObjectClass=group)(objectClass=inetOrgPerson))" -SearchBase $TopOU.distinguishedName -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0]
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)], found $($ObjectsInOu.Count) objects to process."
foreach ($Object in $ObjectsInOu) {
$Place = ConvertFrom-DistinguishedName -ToOrganizationalUnit -DistinguishedName $Object.DistinguishedName
$AllOUs = ConvertFrom-DistinguishedName -ToMultipleOrganizationalUnit -IncludeParent -DistinguishedName $Place
foreach ($OU in $AllOUs) {
if ($OU -eq $Place) {
$CachedOu[$OU]['Objects'][$Object.DistinguishedName] = $Object
$CachedOu[$OU]['ObjectsClasses'][$Object.ObjectClass] = ''
$CachedOu[$OU]['ObjectsCountDirect']++
} else {
$CachedOu[$OU]['ObjectsClasses'][$Object.ObjectClass] = ''
$CachedOu[$OU]['ObjectsCountIndirect']++
}
$CachedOu[$OU]['ObjectsCountTotal']++
}
}
}
}
foreach ($OU in $CachedOu.Keys) {
$ObjectClasses = [string[]] $CachedOu[$OU]['ObjectsClasses'].Keys
if ($CachedOu[$OU]['ObjectsCountTotal'] -eq 0 -and $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count -gt 0) {
$Status = "Unlink GPO", 'Delete OU'
} elseif ($CachedOu[$OU]['ObjectsCountTotal'] -eq 0 -and $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count -eq 0) {
$Status = 'Delete OU'
} elseif ($CachedOU[$Ou]['ObjectsCountTotal'] -gt 0 -and $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count -gt 0 -and $ObjectClasses -notcontains 'User' -and $ObjectClasses -notcontains 'Computer' ) {
$Status = "Unlink GPO"
} else {
$Status = 'OK'
}
if ($Option) {
$Found = $false
if ($Option -contains 'Ok' -and $Status -contains 'OK') {
$Found = $true
} elseif ($Option -contains 'Unlink' -and $Status -contains 'Unlink GPO') {
$Found = $true
} elseif ($Option -contains 'Delete' -and $Status -contains 'Delete OU') {
$Found = $true
}
if ($ExcludeOrganizationalUnit) {
foreach ($ExcludedOU in $ExcludeOrganizationalUnit) {
if ($OU -like $ExcludedOU) {
$Found = $false
break
}
}
}
if (-not $Found) {
continue
}
} else {
if ($ExcludeOrganizationalUnit) {
foreach ($ExcludedOU in $ExcludeOrganizationalUnit) {
if ($OU -like $ExcludedOU) {
$Status = 'Excluded'
break
}
}
}
}
[PSCustomObject] @{
Organizationalunit = $OU
Level = $CachedOu[$OU]['Level']
RootLevel = $CachedOu[$OU]['RootLevel']
DomainName = $CachedOu[$OU]['Domain']
Status = $Status
GPOCount = $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count
ObjectCountDirect = $CachedOu[$OU]['ObjectsCountDirect']
ObjectCountIndirect = $CachedOu[$OU]['ObjectsCountIndirect']
ObjectCountTotal = $CachedOu[$OU]['ObjectsCountTotal']
ObjectClasses = $ObjectClasses
GPONames = $CachedOu[$OU]['LinkedGroupPolicy'].DisplayName
Objects = $CachedOu[$OU]['Objects'].Values.Name
GPO = $CachedOu[$OU]['LinkedGroupPolicy']
}
}
}
+31 -2
View File
@@ -33,6 +33,9 @@
.PARAMETER ADAdministrativeGroups
Ability to provide AD Administrative Groups from another command to speed up processing
.PARAMETER ApprovedOwner
Ability to provide different owner (non administrative that still is approved for use)
.EXAMPLE
Get-GPOZaurrOwner -Verbose -IncludeSysvol
@@ -54,7 +57,9 @@
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation,
[System.Collections.IDictionary] $ADAdministrativeGroups
[System.Collections.IDictionary] $ADAdministrativeGroups,
[alias('Exclusion', 'Exclusions')][string[]] $ApprovedOwner
)
Begin {
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
@@ -79,11 +84,12 @@
foreach ($_ in $Objects) {
$Count++
Write-Verbose "Get-GPOZaurrOwner - Processing GPO [$Count/$($Objects.Count)]: $($_.DisplayName) from domain: $($_.DomainName)"
$ACL = Get-ADACLOwner -ADObject $_.GPODistinguishedName -Resolve -ADAdministrativeGroups $ADAdministrativeGroups -Verbose:$false
$ACL = Get-ADACLOwner -ADObject $_.GPODistinguishedName -Resolve -Verbose:$false
$Object = [ordered] @{
DisplayName = $_.DisplayName
DomainName = $_.DomainName
GUID = $_.GUID
Status = [System.Collections.Generic.List[string]]::new()
Owner = $ACL.OwnerName
OwnerSid = $ACL.OwnerSid
OwnerType = $ACL.OwnerType
@@ -104,6 +110,29 @@
} else {
$Object['IsOwnerAdministrative'] = if ($Object['OwnerType'] -eq 'Administrative') { $true } else { $false }
}
if ($Object['IsOwnerAdministrative'] -eq $true) {
$Object['Status'].Add('Administrative')
} else {
$Object['Status'].Add('NotAdministrative')
}
if ($Object['IsOwnerConsistent']) {
$Object['Status'].Add('Consistent')
} else {
$Object['Status'].Add('Inconsistent')
}
if ($Object['IsOwnerConsistent'] -eq $true -and $Object['IsOwnerAdministrative'] -eq $false) {
# We want to approve only OWNER if it's consistent and not administrative, otherwise it makes no sense
# This is mostly here to allow for use of AGPM or similar approved owner of GPOs
foreach ($Owner in $ApprovedOwner) {
if ($Owner -eq $Object['Owner']) {
$Object['Status'].Add('Approved')
break
} elseif ($Owner -eq $Object['OwnerSid']) {
$Object['Status'].Add('Approved')
break
}
}
}
if ($SkipBroken -and $Object['SysvolExists'] -eq $false) {
continue
}
+104
View File
@@ -0,0 +1,104 @@
function Get-GPOZaurrUpdates {
[cmdletBinding(DefaultParameterSetName = 'DateRange')]
param(
[parameter(ParameterSetName = 'Dates')]
[parameter(ParameterSetName = 'DateRange')]
[alias('ForestName')][string] $Forest,
[parameter(ParameterSetName = 'Dates')]
[parameter(ParameterSetName = 'DateRange')]
[string[]] $ExcludeDomains,
[parameter(ParameterSetName = 'Dates')]
[parameter(ParameterSetName = 'DateRange')]
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[parameter(Mandatory, ParameterSetName = 'Dates')][DateTime] $DateFrom,
[parameter(Mandatory, ParameterSetName = 'Dates')][DateTime] $DateTo,
[parameter(Mandatory, ParameterSetName = 'DateRange')][ValidateSet('PastHour', 'CurrentHour', 'PastDay', 'CurrentDay', 'PastMonth', 'CurrentMonth', 'PastQuarter', 'CurrentQuarter', 'Last14Days', 'Last21Days', 'Last30Days', 'Last7Days', 'Last3Days', 'Last1Days')][string] $DateRange,
[parameter(ParameterSetName = 'Dates')]
[parameter(ParameterSetName = 'DateRange')]
[ValidateSet('WhenCreated', 'WhenChanged')][string[]] $DateProperty = 'WhenCreated',
[parameter(ParameterSetName = 'Dates')]
[parameter(ParameterSetName = 'DateRange')]
[System.Collections.IDictionary] $ExtendedForestInformation
)
$getGPOZaurrADSplat = @{
Forest = $Forest
IncludeDomains = $IncludeDomains
ExcludeDomains = $ExcludeDomains
ExtendedForestInformation = $ExtendedForestInformation
DateFrom = $DateFrom
DateTo = $DateTo
DateRange = $DateRange
DateProperty = $DateProperty
}
Remove-EmptyValue -Hashtable $getGPOZaurrADSplat
# lets get all the links including sites
if ($DateRange) {
Write-Verbose -Message "Get-GPOZaurrUpdates - Get group policies for defined range $DateRange"
} elseif ($DateFrom -and $DateTo) {
Write-Verbose -Message "Get-GPOZaurrUpdates - Get group policies for defined range $DateFrom to $DateTo"
} else {
Write-Warning -Message "Get-GPOZaurrUpdates - No range is selected. Try again."
return
}
$LinksSummaryCache = Get-GPOZaurrLink -AsHashTable -Summary -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
$OUCache = [ordered] @{}
foreach ($Domain in $ForestInformation.Domains) {
Write-Verbose -Message "Get-GPOZaurrUpdates - Getting OU's for $Domain"
$OrganizationalUnits = Get-ADOrganizationalUnit -Filter * -Properties gpOptions, canonicalName -Server $ForestInformation['QueryServers'][$Domain]['HostName'][0]
$OUCache[$OrganizationalUnits.DistinguishedName] = if ($OrganizationalUnits.gpOptions -eq 1) { $true } else { $false } # blocked inheritance
}
$CurrentCount = 0
Write-Verbose -Message "Get-GPOZaurrUpdates - Getting GPO information"
[Array] $GPOs = Get-GPOZaurrAD @getGPOZaurrADSplat
foreach ($GPO in $GPOs) {
$CurrentCount++
Write-Verbose -Message "Get-GPOZaurrUpdates - Processing $($GPO.DisplayName) / $($GPO.DomainName) [$CurrentCount/$($GPOs.Count)]"
$GPOLinkData = $LinksSummaryCache["$($GPO.DomainName)$($GPO.GUID)"]
#$GPOLinkData
[Array] $LinksDN = if ($GPOLinkData.Links.Count -gt 0) {
foreach ($Link in $GPOLinkData.LinksObjects) {
If ($Link.Enabled -eq $true) {
$Link.DistinguishedName
}
}
}
if ($LinksDN.Count -gt 0) {
$OrganizationalUnitsObjects = Get-ADOrganizationalUnitObject -OrganizationalUnit $LinksDN -Summary -IncludeAffectedOnly
} else {
# GPO is not linked
$OrganizationalUnitsObjects = [PSCUstomObject] @{
ObjectsTotalCount = 0
ObjectsBlockedInheritanceCount = 0
ObjectsClasses = @()
}
}
if ($GPO.Owner) {
$Owner = Get-WinADObject -Identity $GPO.Owner -AddType
} else {
$Owner = [PSCustomObject] @{
Name = 'Unknown'
Type = 'Unknown'
ObjectClass = 'Unknown'
}
}
[PSCustomObject] @{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
Owner = $GPO.Owner
OwnerName = $Owner.Name
OwnerType = $Owner.Type
OwnerClass = $Owner.ObjectClass
LinksCount = if ($GPOLinkData) { $GPOLinkData.LinksCount } else { 0 }
LinksEnabledCount = if ($GPOLinkData) { $GPOLinkData.LinksEnabledCount } else { 0 }
AffectedCount = $OrganizationalUnitsObjects.ObjectsTotalCount
BlockedInheritanceCount = $OrganizationalUnitsObjects.ObjectsBlockedInheritanceCount
AffectedClasses = $OrganizationalUnitsObjects.ObjectsClasses.GetEnumerator().Name
Created = $GPO.Created
Changed = $GPO.Modified
LinksEnabled = $LinksDN
}
}
}
+60 -1
View File
@@ -1,4 +1,62 @@
function Invoke-GPOZaurr {
<#
.SYNOPSIS
Single cmdlet that provides 360 degree overview of Group Policies in Active Directory Forest.
.DESCRIPTION
Single cmdlet that provides 360 degree overview of Group Policies in Active Directory Forest with ability to pick reports and export to HTML.
.PARAMETER Exclusions
Allows to mark as excluded some Group Policies or Organizational Units depending on type.
Can be a scriptblock or array depending on supported way by underlying report.
Not every report support exclusions.
Not every report support exclusions the same way.
Exclusions should be used only if there is single report being asked for.
.PARAMETER FilePath
Path to the file where the report will be saved.
.PARAMETER Type
Type of report to be generated from a list of available reports.
.PARAMETER PassThru
Returns created objects after the report is done
.PARAMETER HideHTML
Do not auto open HTML report in default browser
.PARAMETER HideSteps
Do not show steps in report
.PARAMETER ShowError
Show errors in HTML report. Useful in case the report is being run as Scheduled Task
.PARAMETER ShowWarning
Show warnings in HTML report. Useful in case the report is being run as Scheduled Task
.PARAMETER Forest
Target different Forest, by default current forest is used
.PARAMETER ExcludeDomains
Exclude domain from search, by default whole forest is scanned
.PARAMETER IncludeDomains
Include only specific domains, by default whole forest is scanned
.PARAMETER Online
Forces report to use online resources in HTML (using CDN most of the time), by default it is run offline, and inlines all CSS/JS code.
.EXAMPLE
Invoke-GPOZaurr
.EXAMPLE
Invoke-GPOZaurr -Type GPOOrganizationalUnit -Online -FilePath $PSScriptRoot\Reports\GPOZaurrOU.html -Exclusions @(
'*OU=Production,DC=ad,DC=evotec,DC=pl'
)
.NOTES
General notes
#>
[alias('Show-GPOZaurr', 'Show-GPO')]
[cmdletBinding()]
param(
@@ -76,7 +134,8 @@
}
if ($Exclusions) {
if ($Exclusions -is [scriptblock]) {
$Script:Reporting[$T]['ExclusionsCode'] = $Exclusions
$Script:Reporting[$T]['Exclusions'] = $Exclusions
#$Script:Reporting[$T]['ExclusionsCode'] = $Exclusions
}
if ($Exclusions -is [Array]) {
$Script:Reporting[$T]['Exclusions'] = $Exclusions
+38
View File
@@ -0,0 +1,38 @@
function Remove-GPOZaurrLinkEmptyOU {
[cmdletbinding(SupportsShouldProcess)]
param(
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation,
[string[]] $ExcludeOrganizationalUnit,
[int] $LimitProcessing = [int32]::MaxValue
)
$Processed = 0
$OrganizationalUnits = Get-GPOZaurrOrganizationalUnit -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Option Unlink -ExcludeOrganizationalUnit $ExcludeOrganizationalUnit
foreach ($OU in $OrganizationalUnits) {
if ($OU.Status -contains 'Unlink GPO') {
if ($OU.OrganizationalUnit -in $ExcludeOrganizationalUnit) {
Write-Verbose "Remove-GPOZaurrLinkEmptyOU - Processing $($OU.Organizationalunit) was skipped as it's excluded."
continue
}
Write-Verbose "Remove-GPOZaurrLinkEmptyOU - Processing $($OU.Organizationalunit) found OU with GPOs to unlink"
$Processed++
foreach ($GPO in $OU.GPO) {
Write-Verbose "Remove-GPOZaurrLinkEmptyOU - Removing $($GPO.DisplayName) link from $($OU.Organizationalunit)"
try {
Remove-GPLink -ErrorAction Stop -Guid $GPO.GUID -Domain $GPO.DomainName -Target $OU.Organizationalunit
} catch {
Write-Warning "Remove-GPOZaurrLinkEmptyOU - Error removing link of $($GPO.DisplayName) from $($OU.OrganizationalUnit) error: $($_.Exception.Message)"
}
}
if ($Processed -ge $LimitProcessing) {
Write-Verbose "Remove-GPOZaurrLinkEmptyOU - Limit processing hit, stopping."
break
}
}
}
}
+44 -5
View File
@@ -9,6 +9,7 @@
.PARAMETER Type
Unknown - finds unknown Owners and sets them to Administrative (Domain Admins) or chosen principal
NotMatching - find administrative groups only and if sysvol and gpo doesn't match - replace with chosen principal or Domain Admins if not specified
Inconsistent - same as not NotMatching
NotAdministrative - combination of Unknown/NotMatching and NotAdministrative - replace with chosen principal or Domain Admins if not specified
All - if Owner is known it checks if it's Administrative, if it sn't it fixes that. If owner is unknown it fixes it
.PARAMETER GPOName
@@ -38,6 +39,9 @@
.PARAMETER LimitProcessing
Allows to specify maximum number of items that will be fixed in a single run. It doesn't affect amount of GPOs processed
.PARAMETER Force
Pushes new owner regardless if it's already set or not
.EXAMPLE
Set-GPOZaurrOwner -Type All -Verbose -WhatIf -LimitProcessing 2
@@ -47,7 +51,7 @@
[cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Type')]
param(
[Parameter(ParameterSetName = 'Type', Mandatory)]
[validateset('Unknown', 'NotAdministrative', 'NotMatching', 'All')][string] $Type,
[validateset('Unknown', 'NotAdministrative', 'NotMatching', 'Inconsistent', 'All')][string] $Type,
[Parameter(ParameterSetName = 'Named')][string] $GPOName,
[Parameter(ParameterSetName = 'Named')][alias('GUID', 'GPOID')][string] $GPOGuid,
@@ -72,17 +76,28 @@
[Parameter(ParameterSetName = 'Named')]
[string] $Principal,
[Parameter(ParameterSetName = 'Type')]
[Parameter(ParameterSetName = 'Named')]
[switch] $SkipSysvol,
[Parameter(ParameterSetName = 'Type')]
[Parameter(ParameterSetName = 'Named')]
[int] $LimitProcessing = [int32]::MaxValue,
[Parameter(ParameterSetName = 'Type')]
[Parameter(ParameterSetName = 'Named')]
[alias('Exclusion', 'Exclusions')][string[]] $ApprovedOwner,
[Parameter(ParameterSetName = 'Type')]
[Parameter(ParameterSetName = 'Named')]
[validateset('OnlyAD', 'OnlyFileSystem')][string] $Action,
[Parameter(ParameterSetName = 'Type')]
[Parameter(ParameterSetName = 'Named')]
[switch] $Force
)
Begin {
#Write-Verbose "Set-GPOZaurrOwner - Getting ADAdministrativeGroups"
$ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
#Write-Verbose "Set-GPOZaurrOwner - Processing GPO for Type $Type"
}
Process {
$getGPOZaurrOwnerSplat = @{
@@ -94,6 +109,7 @@
ADAdministrativeGroups = $ADAdministrativeGroups
Verbose = $VerbosePreference
SkipBroken = $true
ApprovedOwner = $ApprovedOwner
}
if ($GPOName) {
$getGPOZaurrOwnerSplat['GPOName'] = $GPOName
@@ -103,11 +119,13 @@
$Count = 0
Get-GPOZaurrOwner @getGPOZaurrOwnerSplat | Where-Object {
$Count++
<#
if ($_.Owner) {
$AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"]
} else {
$AdministrativeGroup = $null
}
if (-not $SkipSysvol) {
if ($_.SysvolOwner) {
$AdministrativeGroupSysvol = $ADAdministrativeGroups['ByNetBIOS']["$($_.SysvolOwner)"]
@@ -115,11 +133,19 @@
$AdministrativeGroupSysvol = $null
}
}
#>
if ($Force) {
Write-Verbose "Set-GPOZaurrOwner - Force was used to push new owner to $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner)."
$_
} else {
if ($Type -eq 'NotAdministrative') {
if ($_.Status -contains 'NotAdministrative' -and $_.Status -notcontains 'Approved') {
$_
} elseif ($_.Status -contains 'Inconsistent') {
$_
}
<#
if (-not $AdministrativeGroup -or (-not $AdministrativeGroupSysvol -and -not $SkipSysvol)) {
$_
} else {
@@ -128,23 +154,35 @@
$_
}
}
#>
} elseif ($Type -eq 'Unknown') {
if (-not $_.Owner -or (-not $_.SysvolOwner -and -not $SkipSysvol)) {
$_
}
} elseif ($Type -eq 'NotMatching') {
} elseif ($Type -in 'NotMatching', 'Inconsistent') {
if ($SkipSysvol) {
Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). SysVol scanning is disabled. Skipping."
} else {
if ($_.Status -contains 'Inconsistent') {
$_
}
<#
if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) {
#Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required."
$_
}
#>
}
} else {
# we run with no type, that means we need to either set it to principal or to Administrative
if ($_.Owner) {
# we check if Principal is not set
if ($_.Status -contains 'NotAdministrative' -and $_.Status -notcontains 'Approved') {
$_
} elseif ($_.Status -contains 'Inconsistent') {
$_
}
<#
$AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"]
if (-not $SkipSysvol -and $_.SysvolOwner) {
$AdministrativeGroupSysvol = $ADAdministrativeGroups['ByNetBIOS']["$($_.SysvolOwner)"]
@@ -156,6 +194,7 @@
$_
}
}
#>
} else {
$_
}
@@ -168,7 +207,7 @@
} else {
$DefaultPrincipal = $Principal
}
if ($Action -eq 'OnlyGPO') {
if ($Action -eq 'OnlyAD') {
Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) (SID: $($GPO.OwnerSID)) to $DefaultPrincipal"
Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference
} elseif ($Action -eq 'OnlyFileSystem') {
+10 -11
View File
@@ -27,22 +27,21 @@
.NOTES
General notes
#>
[cmdletBinding()]
[cmdletBinding(DefaultParameterSetName = 'Name')]
param(
#[ValidateSet('GPOList')][string] $Type,
[alias('GpoName', 'DisplayName')][string] $Name,
[parameter(ParameterSetName = 'Name')][alias('GpoName', 'DisplayName')][string] $Name,
[parameter(ParameterSetName = 'Guid')]
[alias('ID')][string] $GUID,
[parameter(ParameterSetName = 'Name')]
[parameter(ParameterSetName = 'Guid')]
[string] $DomaiName
)
#if ($Type) {
# [PSCustomObject] @{
# Type = $Type
# Name = $Name
# DomainName = $DomaiName
# }
#} else {
[PSCustomObject] @{
$Output = @{
Name = $Name
ID = $GUID
DomainName = $DomaiName
}
#}
Remove-EmptyValue -Hashtable $Output
[PSCustomObject] $Output
}
+35 -376
View File
@@ -19,6 +19,40 @@
# GPOZaurr
Group Policy Eater is a PowerShell module that aims to gather information about Group Policies but also allows fixing issues that you may find in them.
**GPOZaurr** provides 360 degrees of information about Group Policies and their settings.
Just a single command (`Invoke-GPOZaurr`) provides following reports:
- GPOBroken
- GPOBrokenLink
- GPOOwners
- GPOConsistency
- GPODuplicates
- GPOOrganizationalUnit
- GPOList
- GPOLinks
- GPOPassword
- GPOPermissions
- GPOPermissionsAdministrative
- GPOPermissionsRead
- GPOPermissionsRoot
- GPOPermissionsUnknown
- GPOFiles
- GPOBlockedInheritance
- GPOAnalysis
- GPOUpdates
- NetLogonOwners
- NetLogonPermissions
- SysVolLegacyFiles
But that's not all.
There are over 50 other commands available that make it even more powerful helping with day to day tasks to manage Group Policies.
To understand the usage of `Invoke-GPOZaurr` I've created blog post you may find useful
- [The only command you will ever need to understand and fix your Group Policies (GPO)](https://evotec.xyz/the-only-command-you-will-ever-need-to-understand-and-fix-your-group-policies-gpo/)
## Installing
GPOZaurr requires `RSAT` installed to provide results. If you don't have them you can install them as below. Keep in mind it also installs GUI tools so it shouldn't be installed on user workstations.
@@ -45,379 +79,4 @@ Update-Module -Name GPOZaurr
That's it. Whenever there's a new version, you run the command, and you can enjoy it. Remember that you may need to close, reopen PowerShell session if you have already used module before updating it.
**The essential thing** is if something works for you on production, keep using it till you test the new version on a test computer. I do changes that may not be big, but big enough that auto-update may break your code. For example, small rename to a parameter and your code stops working! Be responsible!
## Resources
To understand the usage I've created blog post you may find useful
- [The only command you will ever need to understand and fix your Group Policies (GPO)](https://evotec.xyz/the-only-command-you-will-ever-need-to-understand-and-fix-your-group-policies-gpo/)
## Changelog
- 0.0.128 - 2021.05.26
- ☑ Improved `Invoke-GPOZaurrContent` - type `PublicKeyPoliciesCertificates` - added more certificate information
- ☑ Improved `Invoke-GPOZaurr` - type `GPOAnalysis` - added more certificate information
- 0.0.128 Alpha 1 - 2021.05.17
- 🐛 Fixes errors when normalizing properties [#17](https://github.com/EvotecIT/GPOZaurr/issues/17)
- 0.0.127 - 2021.04.15
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOList` - moved description closer to statuses
- ☑ Improved `Get-GPOZaurr` - moved description closer to statuses
- 0.0.126 - 2021.04.12
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOBlockedInheritance` - hidden DistinguishedName, fixed some small typos
- 0.0.125 - 2021.04.11
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOBlockedInheritance` - small fixes
- 0.0.124 - 2021.04.11
- ☑ Added `SearchBuilder` to all tables
- ☑ Automatically joins arrays in tables in `Invoke-GPOZaurr`
- ☑ Improved `Get-GPOZaurrInheritance` with Exclusions and some help information
- ☑ Improved `Invoke-GPOZaurr` with some Exclusions
- ☑ Improved `Invoke-GPOZaurr`
- 🔥 Report `GPOBlockedInheritance` - heavily improved functionality and data
- 0.0.123 - 2021.03.21
- ☑ Fixes `Get-GPOZaurrLinkSummary`
- 0.0.122 - 2021.02.11
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report `GPOAnalysis` - added `WindowsFirewallRules`,`WindowsFirewallProfiles`,`WindowsFirewallConnectionSecurityAuthentication`,`WindowsFirewallConnectionSecurityRules`
- ☑ Improved `Invoke-GPOZaurrContent` as mentioned above for `GPOAnalysis`
- 0.0.121 - 2021.02.10
- ☑ Improvement to `Get-GPOZaurr` - added description [#13](https://github.com/EvotecIT/GPOZaurr/issues/13)
- ☑ Improvement to `Invoke-GPOZaurr -Type GPOList` - added description [#13](https://github.com/EvotecIT/GPOZaurr/issues/13)
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report GPOAnalysis - added `FolderRedirection`
- ☑ Report GPOAnalysis - renamed `FolderRedirection` to `FolderRedirectionPolicy`
- ☑ Improved `Invoke-GPOZaurrContent` as mentioned above for `GPOAnalysis`
- 0.0.120 - 2021.02.10
- ☑ Improvement to `Get-GPOZaurr` to warn if there is potential issue with EMPTY (which can happen on non-english system)
- ☑ In such case GPOZaurr will asses EMPTY or not using old method which doesn't detect all EMPTY cases but shouldn't provide false positives
- 0.0.119
- Broken release - weird
- 0.0.118 - 2021.02.09
- ☑ Added information where the report is saved
- ☑ Small improvement to `Get-GPOZaurr` to exlicitly define variable types
- 0.0.117 - 2021.02.09
- ☑ Small fix to `Get-GPOZaurr` to exclude GPOList.xml which is used in offline mode by `Save-GPOZaurrFiles`
- 0.0.116 - 2021.02.08
- ☑ Improved `Remove-GPOZaurrBroken` to handle ObjectClass problem, and removed reduntant check
- 0.0.115 - 2021.02.07
- ☑ Improved `Invoke-GPOZaurr`
- ☑ `GPOList` - clarified some texts, changed 7 days to 30 days as default
- ☑ `NetLogonPermissions` - fixed missing text
- ☑ Fixes `Get-GPOZaurrNetLogon` error on empty Owner - [#9](https://github.com/EvotecIT/GPOZaurr/issues/9)
- 0.0.114 - 2021.01.27
- ☑ Improved `Invoke-GPOZaurr`
- ☑ HTML now uses offline mode by default (no CDN) - increase in size of HTML up to 3MB
- ☑ Using Online switch forces use of CDN - smaller files. For example `Invoke-GPOZaurr -Type GPOList -Online`
- [ ] Improved `Invoke-GPOZaurrSupport`
- ☑ HTML now uses offline mode by default (no CDN) - increase in size of HTML up to 3MB
- ☑ Using Online switch forces use of CDN - smaller files. For example `Invoke-GPOZaurrSupport -Online`
- ☑ Removed parameter Offline, added parameter Online
- ☑ The cmdlet is not really production ready. It's work in progress
- 0.0.113 - 2021.01.25
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Report GPOAnalysis - added WindowsTimeService
- ☑ Improved `Invoke-GPOZaurrContent`
- ☑ Added `WindowsTimeService` type
- 0.0.112 - 2021.01.25
- ☑ Improved `Invoke-GPOZaurr`
- 0.0.111 - 2021.01.24
- ☑ Improved `Invoke-GPOZaurr`
- 0.0.110 - 2021.01.22
- ☑ Improved `Invoke-GPOZaurr`
- 0.0.109 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurr`
- 0.0.108 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Improved `GPOConsistency`
- 0.0.107 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurr`
- 0.0.106 - 2021.01.11
- ☑ Improved `Invoke-GPOZaurrContent`
- 0.0.105 - 2021.01.05
- ☑ Improved `Get-GPOZaurr`
- ☑ Improved report `GPOBrokenLink`
- 0.0.104 - 2021.01.04
- ☑ Improved `Get-GPOZaurrBrokenLink`
- ☑ Improved `Repair-GPOZaurrBrokenLink`
- ☑ Improved `Get-GPOZaurr`
- ☑ Improved report `GPOBrokenLink`
- 0.0.103 - 2021.01.04
- ☑ Improved `Get-GPOZaurr`
- ☑ Added new report `GPOBrokenLink`
- ☑ Added `Get-GPOZaurrBrokenLink`
- ☑ Added `Repair-GPOZaurrBrokenLink`
- 0.0.102 - 2021.01.02
- ☑ Improved `Get-GPOZaurrLink`
- ☑ Supports all links across forest
- ☑ Renamed Linked validate set from `Other` to `OrganizationalUnit`
- ☑ Improved `Get-GPOZaurrLinkSummary`
- ☑ Improved/BugFix `Get-GPOZaurr` to properly detect linked GPOs in sites/cross-domain
- ☑ Improved `Invoke-GPOZaurrPermission`
- ☑ Renamed Linked validate set from `Other` to `OrganizationalUnit`
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Added `GPOLinks` basic list
- 0.0.101 - 23.12.2020
- ☑ Improved `Get-GPOZaurrBroken`
- ☑ It now detects `ObjectClass Issue`
- ☑ Heavily improved performance
- ☑ Removed some useless properties for this particular cmdlet
- ☑ All states: `Not available on SYSVOL`, `Not available in AD`, `Exists`, `Permissions Issue`, `ObjectClass Issue`
- ☑ Improved help
- ☑ Improved `Remove-GPOZaurrBroken`
- ☑ It now deals with `ObjectClass Issue`
- ☑ Heavily improved performance
- ☑ Removed some useless properties for this particular cmdlet
- ☑ Now requires manual type insert AD, SYSVOL or ObjectClass (or all of them). Before it was auto using AD/SYSVOL.
- ☑ Improved help
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList`
- ☑ Renamed `GPOOrphans` to `GPOBroken`
- ☑ Improved `GPOBroken` with `ObjectClass issue`
- 0.0.100 - 21.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOPermissionsRead`
- ☑ Type `GPOPermissions`
- 0.0.99 - 13.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - require GPO to be 7 days old for deletion to be proposed
- ☑ Type `GPOPermissions` - one stop for permissions
- ☑ Allows Steps to be chosen via their menu and out-of-order
- ☑ Improved `Remove-GPOZaurr` - added `RequireDays` parameter to prevent deletion of just modified GPOs
- ☑ Added `Get-GPOZaurrPermissionAnalysis`
- ☑ Added `Repair-GPOZaurrPermission`
- 0.0.98 - 10.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - fixed unexpected ending of cmdlet when error occurs (for example deleted GPO while script is running) which could impact results
- ☑ Other types - small color adjustment
- ☑ Fixed/Improved `Get-GPOZaurr` - fixed unexpected ending of cmdlet when error occurs (for example deleted GPO while script is running), improved code base
- ☑ Improved `Invoke-GPOZaurrSupport`
- 0.0.97 - 07.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - added more data, did small reorganization
- 0.0.96 - 07.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - added more data, added Optimization Step
- ☑ Added `Set-GPOZaurrStatus`
- ☑ Added `Optimize-GPOZaurr`
- ☑ Fixed `Invoke-GPOZaurrPermission` which would not remove permission due to internal changes earlier on
- ☑ Small change to `Backup-GPOZaurr`
- ☑ Added support for `Disabled`. It's now possbile to backup `All` (default), `Empty`,`Unlinked`,`Disabled` or a mix of them
- ☑ Removed useless `GPOPath` parameter
- 0.0.95 - 04.12.2020
- ☑ Fix for too big int - [#4](https://github.com/EvotecIT/GPOZaurr/issues/4) - tnx neztach
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` - added ability for Exclusions
- ☑ All other types, small improvements
- ☑ Added HideSteps, ShowError, ShowWarning -> Disabled Warnings/Errors by default as they tend to show too much information
- ☑ Improved `Remove-GPOZaurr` - added Exclusions
- 0.0.93 - 03.12.2020
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` reverted charts colors for entries to match colors
- [ ] Added `Skip-GroupPolicy` to use within `Invoke-GPOZaurr`
- ☑ Improved `Invoke-GPOZaurr` with basic support for Exclusions
- ☑ Improved `Get-GPOZaurr` with basic support for Exclusions
- ☑ Improved `Remove-GPOZaurrPermission` error handling
- 0.0.92 - 01.12.2020
- ☑ Improved `Invoke-GPOZaurrSupport`
- ☑ Improved `Invoke-GPOZaurr`
- ☑ Type `GPOList` improved with more data, more problems and clearer information
- ☑ Improved `Remove-GPOZaurr`
- ☑ Added ability do remove disabed GPO
- ☑ Improved `Get-GPOZaurr` detecting more issues, delivering more data
- 0.0.91 - 24.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Improve Type `GPOPermissionsUnknown`
- 0.0.90 - 23.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Improves Type `GPODuplicates`
- ☑ Fix for chart color to be RED
- ☑ Add Type `GPOPermissionsUnknown`
- ☑ Improves logic for Data with 0/1 element
- ☑ Improves `Remove-GPOZaurrDuplicateObject` - removed `Confirm` requirement
- ☑ Improves `Get-GPOZaurrNetLogon` with more verbose
- ☑ Improves `Repair-GPOZaurrNetLogonOwner` with more verbose and fix for `LimitProcessing`
- 0.0.89 - 22.11.2020
- ☑ Small update `Add-GPOZaurrPermission`
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Added Type `GPOPermissionsAdministrative`
- 0.0.88 - 18.11.2020
- ☑ Fix for `Add-GPOZaurrPermission`
- 0.0.87 - 18.11.2020
- ☑ Improve error handling `Remove-GPOZaurrBroken`
- 0.0.86 - 18.11.2020
- ☑ Improve error handling `Remove-GPOZaurrBroken`
- 0.0.85 - 17.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Split `NetLogonPermissions` into `NetLogonPermissions` and `NetLogonOwners`
- ☑ Improved type `NetLogonPermissions`
- ☑ Improved type `NetLogonOwners`
- ☑ Improves `Get-GPOZaurrFiles`
- ☑ Improves `Get-GPOZaurrNetLogon`
- ☑ Fix for `Get-GPOZaurrNetLogon`
- 0.0.84 - 16.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `NetLogonPermissions`
- ☑ Fix for `Get-GPOZaurrNetLogon`
- 0.0.83 - 14.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Fix for wrong ActionRequired count
- 0.0.82 - 14.11.2020
- ☑ Added `Get-GPOZaurrPermissionIssue` to detect permission issue with no rights
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `GPOPermissionsRead` improved detection of problems with low permissions
- 0.0.81 - 12.11.2020
- ☑ Fix for `Set-GPOZaurrOwner` in case of missing permissions to not throw errors
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `GPOPermissionsRead` added
- 0.0.80 - 12.11.2020
- ☑ Improves `Invoke-GPOZaurr` (WIP)
- ☑ Type `GPOOrphans` clearer options, updated texts, split per domain
- ☑ Type `GPOOwners` clearer options, updated texts, split per domain
- ☑ Improves `Add-GPOZaurrPermission`
- ☑ Fixes LimitProcessing to work correctly
- ☑ Added `All` to process all GPOs
- ☑ Fixes `Remove-GPOZaurrPermission`
- ☑ Improves `Set-GPOZaurrOwner`
- ☑ Added `Force` to force `GPO Owner` to any principal (normally only Domain Admins)
- 0.0.79 - 10.11.2020
- Improved `Invoke-GPOZaurr` - type `GPOOrphans`
- 0.0.78 - 10.11.2020
- Improved `Remove-GPOZaurrBroken` more verbose
- Improved `Get-GPOZaurrBroken` more verbose
- Improved `Invoke-GPOZaurr` - type `GPOOrphans`
- Improved `Invoke-GPOZaurr` - type `GPOList` - needs more work
- Improved `Get-GPOZaurr` with better detection of Empty Policies (needs testing)
- 0.0.77 - 9.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.76 - 8.11.2020
- Improved `Get-GPOZaurrNetLogon` to better handle errors
- 0.0.75 - 8.11.2020
- Improved `Get-GPOZaurrPermissionConsistency` to stop checking consistency if path doesn't exists
- 0.0.74 - 8.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.73 - 7.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- Improved `Get-GPOZaurr`
- 0.0.72 - 6.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.71 - 3.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.70 - 29.10.2020
- Added `Get-GPOZaurrDuplicateObject`
- Added `Remove-GPOZaurrDuplicateObject`
- 0.0.69 - 29.10.2020
- Improved `Invoke-GPOZaurr` (WIP)
- Improved `Get-GPOZaurrNetLogon`
- Improved `Get-GPOZaurrOwner`
- Improved `Set-GPOZaurrOwner`
- Added `Repair-GPOZaurrNetLogonOwner`
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.68 - 28.10.2020
- Renamed `Show-GPOZaurr` to `Invoke-GPOZaurr`
- Renamed `Invoke-GPOZaurr` to `Invoke-GPOZaurrContent`
- Improvements to `Get-GPOZaurrPermissionConsistency` - don't check for inherited permissions if top level ones are inconsistent
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.67 - 22.10.2020
- Improved `Show-GPOZaurr` (WIP)
- 0.0.66 - 22.10.2020
- Improved `Show-GPOZaurr` (WIP)
- 0.0.65 - 22.10.2020
- Improved `Show-GPOZaurr` (WIP)
- 0.0.64 - 21.10.2020
- Renamed `Remove-GPOZaurrOrphaned` to `Remove-GPOZaurrBroken` keeping it as an alias
- Renamed `Get-GPOZaurrSysvol` to `Get-GPOZaurrBroken` keeping it as an alias
- Improved `Show-GPOZaurr` (WIP)
- 0.0.63 - 19.10.2020
- Renamed `Invoke-GPOZaurrContent` back to `Invoke-GPOZaurr`
- Added `Show-GPOZaurr` (WIP)
- Added `OutputType`,`OutputType`,`Open`,`Online` parameters to `Invoke-GPOZaurr`
- Added `Get-GPOZaurrNetLogon`
- Improved `Get-GPOZaurrOwner`
- Fixes `Get-GPOZaurrSysvol`
- 0.0.62 - 14.10.2020
- Renamed `Invoke-GPOZaurr` to `Invoke-GPOZaurrContent` - I want to use `Invoke-GPOZaurr` for something else
- Improvements to `Get-GPOZaurrPermissionConsistency` for GPOs without SYSVOL to be reported properly
- Added `Get-GPOZaurrPermissionRoot`
- Renamed `Remove-GPOZaurrOrphanedSysvolFolders` to `Remove-GPOZaurrOrphaned`
- Improved `Remove-GPOZaurrOrphaned` to deal with orphaned folders but also orphaned AD GPO (No sysvol data)
- Improved `Get-GPOZaurrSysVol` to detect orphaned SYSVOL or AD GPO objects
- Improved `Get-GPOZaurrSysVol` to detect permissions issue when reading AD GPO objects
- Added `Get-GPOZaurrPermissionRoot` to show which users/groups have control over all GPOs (allowed to create/modify)
- Improved `Get-GPOZaurrPermissionSummary` to include `Get-GPOZaurrPermissionRoot` custom permissions
- Updated `Remove-GPOZaurrPermission`
- Updated `Get-GpoZaurrPermission`
- Updated `Get-GPOZaurrFiles` to better handle access issue
- Reversed parameters `Get-GPOZaurrFiles` from `Limited` to `ExtendedMetaData` and fixed missing columns
- 0.0.61 - 31.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
- Fixes to `ConvertFrom-CSExtension`
- Fixes to `Find-CSExtension`
- 0.0.59 - 26.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
- 0.0.58 - 26.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
- 0.0.57 - 26.08.2020
- Improvement to `Get-GPOZaurrPermissionSummary`
- 0.0.56 - 26.08.2020
- Added `Get-GPOZaurrPermissionSummary`
- 0.0.55 - 17.08.2020
- Improved `Get-GPOZaurrInheritance`
- 0.0.54 - 16.08.2020
- Added `Invoke-GPOZaurrSupport` (WIP)
- Added `ConvertFrom-CSExtension`
- Added `Find-CSExtension`
- Added `Get-GPOZaurrInheritance`
- 0.0.53 - 16.08.2020
- Bad release
- 0.0.52 - 16.08.2020
- Bad release
- 0.0.51 - 2.08.2020
- Updates to `Invoke-GPOZaurr` - still work in progress
- Added `Get-GPOZaurrSysvolDFSR`
- Added `Clear-GPOZaurrSysvolDFSR` (requires testing)
- 0.0.50 - 29.07.2020
- Updates to couple of commands
- 0.0.49 - 23.07.2020
- Hidden files were skipped - and people do crazy things with them
- 0.0.48 - 21.07.2020
- Added `Get-GPOZaurrFilesPolicyDefinition`
- Updates to `Invoke-GPOZaurr` - still work in progress
- Updates to `Get-GPOZaurrFiles` - still work in progress
- Updates to `Remove-GPOZaurrOrphanedSysvolFolders` with backup and support for domains
- Module will now be signed
- 0.0.47 - 29.06.2020
- Update to `Get-GPOZaurrAD` for better error reporting
- Updates to `Invoke-GPOZaurr` - still work in progress
- 0.0.46 - 28.06.2020
- Additional protection for `Get-GPOZaurrAD` for CNF duplicates
- Update to `Save-GPOZaurrFiles`
- Added `Invoke-GPOZaurr` (alias: `Find-GPO`) (heavy work in progress)
- 0.0.45 - 26.06.2020
- During publishing ADEssentials required functions are now merged to prevent cyclic dependency bug [Using ModuleSpec syntax in RequiredModules causes incorrect "cyclic dependency" failures](https://github.com/PowerShell/PowerShell/issues/2607)
- 0.0.44 - 24.06.2020
- Improvement to `Get-GPOZaurrLinkSummary`
- 0.0.43 - 21.06.2020
- Added `Get-GPOZaurrFiles` to list files on NETLOGON/SYSVOL shares with a lot of details
- 0.0.42 - 19.06.2020
- Fix for `Get-GPOZaurrLink` and `SearchBase` parameter
- Fix for `Get-GPOZaurrLink` - canonical link Trim() throwing errors if empty
- 0.0.41 - 18.06.2020
- Added paramerter `SkipDuplicates` to `Invoke-GPOZaurrPermission` which prevents applying permissions over and over again if 1 GPO is linked to a multiple OU's within another OU
- 0.0.40 - 18.06.2020
- Fix for error `Get-GPOZaurrLink` - same issue as described on my [earlier blog - Get-ADObject : The server has returned the following error: invalid enumeration context.](https://evotec.xyz/get-adobject-the-server-has-returned-the-following-error-invalid-enumeration-context/).
- `WARNING: Get-GPOZaurrLink - Processing error The server has returned the following error: invalid enumeration context.`
- `WARNING: Get-GPOZaurrLink - Processing error A referral was returned from the server`
- Added `SkipDuplicates` for `Get-GPOZaurrLink`
- 0.0.39 - 17.06.2020
- Updates to `Invoke-GPOZaurrPermission` with new parameter `LimitAdministrativeGroupsToDomain`
- This will get administrative based on IncludeDomains if given. It means that if GPO has Domain admins added from multiple domains it will only find one, and remove all other Domain Admins (if working with Domain Admins that is)
- 0.0.38 - 17.06.2020
- Update to Get-PrivGPOZaurrLink which would cause problems to `Invoke-GPOZaurrPermission` if it would be run without Administrative permission and GPO wouldn't be accessible for that user
- 0.0.37 - 16.06.2020
- Updates to `Invoke-GPOZaurrPermission` with new parameterset `Level`
- Updates to `Get-GPOZaurrLinkSummary`
- 0.0.36 - 15.06.2020
- Initial release
**The essential thing** is if something works for you on production, keep using it till you test the new version on a test computer. I do changes that may not be big, but big enough that auto-update may break your code. For example, small rename to a parameter and your code stops working! Be responsible!