Compare commits

...

289 Commits

Author SHA1 Message Date
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
Przemyslaw Klys 5d69cef128 changelog update 2021-05-26 22:53:30 +02:00
Przemyslaw Klys 062374b4be Update readme, PSD1 2021-05-26 22:53:10 +02:00
Przemyslaw Klys e61329ac66 Improved certificates 2021-05-26 16:32:07 +02:00
Przemyslaw Klys d3328dbb81 Readme update 2021-05-17 23:22:11 +02:00
Przemyslaw Klys 5803371b5e Update PSD1 2021-05-17 23:14:37 +02:00
Przemyslaw Klys 263f364ede PSM1 update 2021-05-17 23:14:30 +02:00
Przemyslaw Klys 16a181155b Potentially fixes #17 2021-05-17 23:14:16 +02:00
Przemyslaw Klys 962d8829d7 PSD1 update 2021-04-15 18:44:15 +02:00
Przemyslaw Klys 4155c35cc6 Moved description a bit 2021-04-15 18:43:47 +02:00
Przemyslaw Klys 614d8cbda5 PSD1/Readme release 2021-04-12 08:46:35 +02:00
Przemyslaw Klys 43e7f2e746 Dont auto replace words 🐛 2021-04-12 08:45:35 +02:00
Przemyslaw Klys 9a3ed3b6ce Added hidding column 2021-04-12 00:09:47 +02:00
Przemyslaw Klys 50f0cfc1a6 Improved blocked inheritance 2021-04-11 21:36:40 +02:00
Przemyslaw Klys 269d611563 New release 2021-04-11 21:30:25 +02:00
Przemyslaw Klys 55ab89a5b0 Release is ready 2021-04-11 21:14:29 +02:00
Przemyslaw Klys 9da8c7c94b BlockedInheritance Improve 2021-04-11 21:11:36 +02:00
Przemyslaw Klys 53aa69029f Update examples 2021-04-11 21:11:19 +02:00
Przemyslaw Klys 4189ad12f2 Improvements 2021-04-11 20:11:46 +02:00
Przemyslaw Klys b1c3037803 Update examples 2021-04-11 20:11:33 +02:00
Przemyslaw Klys 62308cbb6d Improvement of TableOption join 2021-04-11 19:01:47 +02:00
Przemyslaw Klys 914dcfb0c4 Improved 2021-04-11 19:01:33 +02:00
Przemyslaw Klys 2cf4d2c6c9 Added exclusions 2021-04-11 16:21:59 +02:00
Przemyslaw Klys d53d50f99b Update readme 2021-04-11 15:47:43 +02:00
Przemyslaw Klys 2ef3c306ff Update example 2021-04-11 14:53:37 +02:00
Przemyslaw Klys 481338f83b Update examples 2021-04-11 14:53:28 +02:00
Przemyslaw Klys eaf3b231ae Update example 2021-04-11 14:53:00 +02:00
Przemyslaw Klys b2c73479c7 Update example 2021-04-11 14:52:55 +02:00
Przemyslaw Klys 38c6327e30 Update readme 2021-04-11 14:52:30 +02:00
Przemyslaw Klys 0b3e072a3e Added search builder 2021-04-11 14:49:58 +02:00
Przemyslaw Klys 89664bfd02 Add searchBuilder to tables 2021-04-10 20:35:33 +02:00
Przemyslaw Klys 1021ebe5f4 Update readme 2021-03-20 19:51:53 +01:00
Przemyslaw Klys 521125bbc1 Update PSD1 2021-03-20 19:51:00 +01:00
Przemyslaw Klys ae6b596e5b Fixes small error 2021-03-20 19:50:50 +01:00
Przemyslaw Klys bfe50f02fe Added Windows Firewall analysis 2021-02-11 12:40:21 +01:00
Przemyslaw Klys 187b44a19d Update readme 2021-02-11 12:35:22 +01:00
Przemyslaw Klys 36793b33c4 PSD1 update 2021-02-11 12:34:01 +01:00
Przemyslaw Klys 94e6c785c1 Update readme 2021-02-11 12:21:03 +01:00
Przemyslaw Klys efbd2b12de Firewall updates 2021-02-11 12:15:27 +01:00
Przemyslaw Klys d0a678353f Update rules 2021-02-10 23:48:01 +01:00
Przemyslaw Klys 6b0f3b332d Added Firewall Rules #7 2021-02-10 23:46:36 +01:00
Przemyslaw Klys 37483c91b5 Update PSD1 2021-02-10 19:51:17 +01:00
Przemyslaw Klys 9172948be3 Added folder redirection #12 2021-02-10 19:50:45 +01:00
Przemyslaw Klys 14567959f7 #12 2021-02-10 19:49:51 +01:00
Przemyslaw Klys 6a9ad14083 Modified readme 2021-02-10 19:25:10 +01:00
Przemyslaw Klys e00de40cd2 Adds description #13 2021-02-10 19:24:04 +01:00
Przemyslaw Klys 6f806698e9 update readme 2021-02-10 12:02:01 +01:00
Przemyslaw Klys 2e1571b0d7 Update 2021-02-10 11:56:31 +01:00
Przemyslaw Klys ffedd2d9d2 Update 2021-02-10 11:56:23 +01:00
Przemyslaw Klys 911bc50f22 Update readme 2021-02-10 11:00:52 +01:00
Przemyslaw Klys 0383d249e9 PSD1 update 2021-02-10 10:57:12 +01:00
Przemyslaw Klys 8070179d27 Update readme 2021-02-10 10:56:48 +01:00
Przemyslaw Klys db67e6191e Improved false-positive detection for Empty on non-english systesm 2021-02-10 10:47:23 +01:00
Przemyslaw Klys db9b6d60c6 PSD1 update 2021-02-09 18:07:24 +01:00
Przemyslaw Klys 2c965d81d5 Small update 2021-02-09 18:01:48 +01:00
Przemyslaw Klys bff372affe Update readme 2021-02-09 17:58:06 +01:00
Przemyslaw Klys 138a0f411e Added information about filepath 2021-02-09 17:56:56 +01:00
Przemyslaw Klys 1c37a9d1df Update readme / PSD1 2021-02-09 10:58:02 +01:00
Przemyslaw Klys 30535c1baf Update readme 2021-02-09 10:55:23 +01:00
Przemyslaw Klys 56c722edd0 Small fix to exclude GPOList.xml 2021-02-09 10:54:43 +01:00
Przemyslaw Klys 1f43ae21fe PSD1 update 2021-02-08 17:43:40 +01:00
Przemyslaw Klys ef90ef05f7 Update readme 2021-02-08 17:43:13 +01:00
Przemyslaw Klys 43b304d252 Removed redundant code
Handles ObjectClass problem properly now
2021-02-08 17:43:07 +01:00
Przemyslaw Klys 24e691edb9 Update PSD1/readme 2021-02-07 15:08:54 +01:00
Przemyslaw Klys 1c787735d4 update readme 2021-02-07 10:08:36 +01:00
Przemyslaw Klys 13a2aa6482 Missing text added 2021-02-07 10:08:29 +01:00
Przemyslaw Klys 1ac1f83abd Fix #9 2021-02-07 10:06:11 +01:00
Przemyslaw Klys 65b2867588 Update readme 2021-02-04 18:43:10 +01:00
Przemyslaw Klys 1043a2d512 update list 2021-02-04 18:37:36 +01:00
Przemyslaw Klys 7002813027 PSD1 update 2021-01-27 19:09:28 +01:00
Przemyslaw Klys 03b8e4f2cb Update readme 2021-01-27 19:09:02 +01:00
Przemyslaw Klys 680762733e Update to Online 2021-01-27 19:08:54 +01:00
Przemyslaw Klys 7a37d5b9f6 Added Online switch 2021-01-27 18:59:06 +01:00
Przemyslaw Klys a1e9a4a3fa PSD1 update 2021-01-25 21:25:05 +01:00
Przemyslaw Klys 8cbb3272b2 Update readme 2021-01-25 21:24:40 +01:00
Przemyslaw Klys 8da0c1793d Added WindowsTimeService #6 2021-01-25 21:23:19 +01:00
Przemyslaw Klys 5a7b20ca2b Update examples 2021-01-25 19:46:15 +01:00
Przemyslaw Klys ebffba3b95 Update readme 2021-01-25 19:43:33 +01:00
Przemyslaw Klys a79071c395 PSD1 update 2021-01-25 19:43:02 +01:00
Przemyslaw Klys a5a889b468 Small update to docs 2021-01-25 19:42:36 +01:00
Przemyslaw Klys 62d73041ea Update readme 2021-01-24 17:56:37 +01:00
Przemyslaw Klys d88307047c PSD1 update 2021-01-24 17:53:34 +01:00
Przemyslaw Klys 7d85d41747 Text improvement 2021-01-24 16:48:37 +01:00
Przemyslaw Klys a1fab2ceb2 Text improvement 2021-01-24 10:28:35 +01:00
Przemyslaw Klys 99f07f61e3 Text improvement 2021-01-24 10:28:29 +01:00
Przemyslaw Klys 58136f0c43 Update psd1 2021-01-22 12:40:45 +01:00
Przemyslaw Klys b55729d8e0 Update deployment module 2021-01-22 12:40:36 +01:00
Przemyslaw Klys 6206a33a2e Update readme 2021-01-22 12:40:27 +01:00
Przemyslaw Klys 165381b1e3 Small update 2021-01-22 12:39:53 +01:00
Przemyslaw Klys ea1de10fd9 Update readme 2021-01-11 10:30:41 +01:00
Przemyslaw Klys 03453b6bdb PSD1 update 2021-01-11 10:27:41 +01:00
Przemyslaw Klys 4d7f49902d Update 2021-01-11 10:27:34 +01:00
Przemyslaw Klys 508d778d06 Update consistency report 2021-01-11 10:14:01 +01:00
Przemyslaw Klys 5c3157f15f Update psd1 2021-01-11 10:13:54 +01:00
Przemyslaw Klys b33f42b320 Update readme 2021-01-11 10:13:48 +01:00
Przemyslaw Klys f8d3b363e7 Update list 2021-01-11 09:52:59 +01:00
Przemyslaw Klys a68d917d19 Small test 2021-01-11 09:51:10 +01:00
Przemyslaw Klys 946bb3029f Update 2021-01-11 09:51:04 +01:00
Przemyslaw Klys 975bf5b889 Update PSD1 2021-01-11 09:00:13 +01:00
Przemyslaw Klys 6fa0818375 Update Examples 2021-01-11 08:59:35 +01:00
Przemyslaw Klys 2abec9579a Update Invoke-GPOZaurrContent 2021-01-11 08:58:51 +01:00
Przemyslaw Klys 75a8083368 Update PSD1/Readme 2021-01-11 08:58:24 +01:00
Przemyslaw Klys 06c711694e Update readme/psd1 2021-01-05 13:32:57 +01:00
Przemyslaw Klys 8a38ac4556 Improved report 2021-01-05 13:31:45 +01:00
Przemyslaw Klys 9d2ae288c0 Update PSD1/Readme 2021-01-04 21:47:54 +01:00
Przemyslaw Klys 0bc50328ee solves issue when gpLink is empty 2021-01-04 21:47:26 +01:00
Przemyslaw Klys a74b662c9b Prevent errors from doing harm 2021-01-04 21:29:57 +01:00
Przemyslaw Klys 37d8db92f7 Update to make sure it works properly for domains 2021-01-04 21:15:49 +01:00
Przemyslaw Klys d094344f9f Update docs 2021-01-04 21:15:28 +01:00
Przemyslaw Klys a24b1ff958 Added new report 2021-01-04 09:25:02 +01:00
Przemyslaw Klys de076a1cb4 Added new report 2021-01-04 09:24:55 +01:00
Przemyslaw Klys 663eecc01b Small typo fix for GPODuplicate 2021-01-04 09:24:48 +01:00
Przemyslaw Klys d1b7d71ad9 Update readme 2021-01-04 09:24:35 +01:00
Przemyslaw Klys d888f135e0 Update readme 2021-01-03 20:58:13 +01:00
Przemyslaw Klys 81ecf580c4 Added Repair-GPOZaurrBrokenLink 2021-01-03 20:58:06 +01:00
Przemyslaw Klys 34c9d59150 Added Get-GPOZaurrBrokenLink 2021-01-03 20:57:27 +01:00
Przemyslaw Klys 80580b7dce Update PSD1 2021-01-03 20:55:53 +01:00
Przemyslaw Klys 304f70a4d9 PSD1 update 2021-01-02 16:40:03 +01:00
Przemyslaw Klys ab6c61ac52 Update ReADME 2021-01-02 16:39:58 +01:00
Przemyslaw Klys dbe79a7833 Update PSD1 2020-12-28 12:15:35 +01:00
Przemyslaw Klys 0cc05c4aeb Update readme 2020-12-28 12:06:46 +01:00
Przemyslaw Klys c10a4c088e Improved GPOZaurr 2020-12-28 12:06:40 +01:00
Przemyslaw Klys 015afd69a4 Update 2020-12-28 11:53:29 +01:00
Przemyslaw Klys 2fa9b202bc Example updates 2020-12-28 11:42:30 +01:00
Przemyslaw Klys 25bbf8d52e Update 2020-12-28 11:42:04 +01:00
Przemyslaw Klys 8a009bf288 Update 2020-12-28 11:16:59 +01:00
Przemyslaw Klys ed76fc9513 Update example 2020-12-28 10:31:56 +01:00
Przemyslaw Klys 646c22bdab Update example 2020-12-28 10:31:35 +01:00
Przemyslaw Klys d4f8cdc8e8 Update examples 2020-12-28 10:31:25 +01:00
Przemyslaw Klys 166d4fb767 Impoved Get-GPOzaurr Links 2020-12-28 10:30:56 +01:00
Przemyslaw Klys 0ca98a4165 Improvement to links 2020-12-28 10:04:56 +01:00
Przemyslaw Klys a5bcbbf285 Update 2020-12-28 10:04:27 +01:00
Przemyslaw Klys 513179fd03 Invoke-GPOZaurrPermission improvement 2020-12-28 10:04:15 +01:00
Przemyslaw Klys 72cd1da9ae update readme 2020-12-28 10:03:29 +01:00
Przemyslaw Klys 3fe52c99b5 Private use only 2020-12-28 09:55:14 +01:00
Przemyslaw Klys fc6fe14579 Update readme 2020-12-27 23:25:34 +01:00
Przemyslaw Klys bd5a73439d Update 2020-12-27 23:25:15 +01:00
Przemyslaw Klys 469332e543 PSD1 update 2020-12-27 22:38:57 +01:00
Przemyslaw Klys 6cbe3a375a Improved Get-GPOZaurrLink 2020-12-27 22:38:48 +01:00
Przemyslaw Klys c987ca9863 Update 2020-12-27 22:38:31 +01:00
Przemyslaw Klys f0d24e1902 Update 2020-12-27 22:38:05 +01:00
Przemyslaw Klys 61b9c916e7 Update 2020-12-24 09:32:15 +01:00
Przemyslaw Klys deebcb825d Update Get-GPOZaurrLink 2020-12-24 09:27:57 +01:00
Przemyslaw Klys 7adfd1ef65 PSD1 2020-12-23 11:06:39 +01:00
Przemyslaw Klys 828c221ac9 Renamed GPOBroken 2020-12-23 10:46:07 +01:00
Przemyslaw Klys 8e80fd423d Update readme 2020-12-23 10:45:55 +01:00
Przemyslaw Klys f52fd60fef Update 2020-12-23 10:33:30 +01:00
Przemyslaw Klys 9594afb246 Update example 2020-12-23 10:00:53 +01:00
Przemyslaw Klys 7c52284b48 Improved Remove-GPOZaurrBroken 2020-12-23 09:47:14 +01:00
Przemyslaw Klys 2fd64952af Update readme 2020-12-23 09:47:04 +01:00
Przemyslaw Klys 15538e8559 Improve Get-GPOZaurrBroken 2020-12-23 09:32:07 +01:00
Przemyslaw Klys a36a470538 Update readme 2020-12-23 09:31:57 +01:00
Przemyslaw Klys 0a5d65761c PSD1 / README update 2020-12-21 13:22:20 +01:00
Przemyslaw Klys 7ed3cb6dad Update 2020-12-21 13:21:29 +01:00
Przemyslaw Klys 4d9edde212 Update example 2020-12-15 19:11:24 +01:00
Przemyslaw Klys 7ba40e3981 Small update to permission analysis 2020-12-13 15:44:33 +01:00
Przemyslaw Klys ec81655019 Update readme 2020-12-13 15:44:22 +01:00
Przemyslaw Klys 752a34204b Update readme 2020-12-13 15:41:44 +01:00
Przemyslaw Klys 0afe6c6d23 Update readme 2020-12-13 15:40:58 +01:00
Przemyslaw Klys 2a300747a1 Update example 2020-12-13 15:37:43 +01:00
Przemyslaw Klys 94b8a71192 Fix encoding 2020-12-13 14:54:36 +01:00
Przemyslaw Klys 49b9eccfd1 Update Example 2020-12-13 14:54:27 +01:00
Przemyslaw Klys 92b5f00d7f update gpo example 2020-12-13 14:54:14 +01:00
Przemyslaw Klys 1f625e4e90 Permissions report 2020-12-13 14:53:58 +01:00
Przemyslaw Klys 7ac406ca24 Update examples 2020-12-13 14:52:23 +01:00
Przemyslaw Klys 4d584902e8 Repair-GPOZaurrPermission new 2020-12-13 14:51:54 +01:00
Przemyslaw Klys 7e6efb81f1 Update PSD1/Readme 2020-12-13 14:51:47 +01:00
Przemyslaw Klys 16b0a0f4b6 Update report steps to be clickable 2020-12-13 14:06:36 +01:00
Przemyslaw Klys 85eaa4e5d6 Update report permission analysis 2020-12-13 14:04:05 +01:00
Przemyslaw Klys 8c555a4fa9 Update Perm Analisys 2020-12-13 14:03:55 +01:00
Przemyslaw Klys 8bc85a4c91 Encoding update 2020-12-13 13:33:41 +01:00
Przemyslaw Klys 84ad1df972 Update 2020-12-13 13:33:31 +01:00
Przemyslaw Klys 71a12316e3 Update Get-GPOZaurrPermissionAnalysis 2020-12-13 09:39:01 +01:00
Przemyslaw Klys 4a3a49440f Force encoding utf 8 with bom 2020-12-12 23:14:02 +01:00
Przemyslaw Klys 0b2e2ea96c Update examples 2020-12-12 22:16:02 +01:00
Przemyslaw Klys 4ae3bbce12 Update examples 2020-12-12 22:15:28 +01:00
Przemyslaw Klys 471bc04fb2 Update examples 2020-12-12 22:15:18 +01:00
Przemyslaw Klys 4d050c536d Update examples 2020-12-12 22:15:07 +01:00
Przemyslaw Klys 508402b4bf Update examples 2020-12-12 22:14:42 +01:00
Przemyslaw Klys 6f1ac33df8 Update examples 2020-12-12 22:14:27 +01:00
Przemyslaw Klys 5130ef77e5 Update 2020-12-12 22:14:04 +01:00
Przemyslaw Klys 19c2b6bf90 Update 2020-12-12 19:44:56 +01:00
Przemyslaw Klys 5b1aaae915 Update 2020-12-12 19:44:51 +01:00
Przemyslaw Klys d239c979e9 modified readme 2020-12-12 19:41:01 +01:00
Przemyslaw Klys 35c04c88c0 added Get-GPOZaurrPermissionAnalysis 2020-12-12 19:40:54 +01:00
Przemyslaw Klys 048347c830 Internal Get-PermissionsAnalysis update 2020-12-11 22:43:04 +01:00
Przemyslaw Klys 563ba55342 readme update 2020-12-11 22:42:41 +01:00
Przemyslaw Klys 5a62968925 PSD1 update 2020-12-11 22:42:30 +01:00
Przemyslaw Klys a47fa85a8c RequireDays for Remove-GPOZaurr added 2020-12-11 10:49:00 +01:00
Przemyslaw Klys b156c91c7c Improvement to GPOList 2020-12-11 10:48:51 +01:00
Przemyslaw Klys d44e27e68c Day counting adding 2020-12-11 10:48:41 +01:00
Przemyslaw Klys e5dc00007f Remove dead code 2020-12-11 10:48:34 +01:00
Przemyslaw Klys c31c8257a3 Color adjustment 2020-12-10 11:16:20 +01:00
Przemyslaw Klys b135fc3c7f Update Readme/PSD1 2020-12-10 11:16:08 +01:00
Przemyslaw Klys 0699cdf2ff Fix and Improvement Get-GPOZaurr 2020-12-10 11:04:10 +01:00
Przemyslaw Klys fb366e5e78 Update for Invoke-GPOZaurrSupport 2020-12-10 11:03:59 +01:00
Przemyslaw Klys 6456325584 update PSD1 2020-12-10 11:03:21 +01:00
Przemyslaw Klys 808d05adb4 NoApplyPermission checks 2020-12-07 13:17:56 +01:00
Przemyslaw Klys f72a8d8018 Update PSD1/Readme 2020-12-07 13:17:26 +01:00
Przemyslaw Klys de6d06e60c Update 2020-12-07 09:10:20 +01:00
Przemyslaw Klys d14a8b7d5a build code 2020-12-07 08:59:31 +01:00
Przemyslaw Klys d9d4a641eb Update InvokeGPOZaurrList 2020-12-07 08:58:15 +01:00
Przemyslaw Klys a4c2e69117 Update readme 2020-12-07 08:58:05 +01:00
126 changed files with 5829 additions and 1109 deletions
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$T = Get-GPOZaurrPermission -Type Unknown -Verbose
$T | Out-HtmlView -ScrollX -Filtering -DisablePaging -ScrollY -Online
$T #| Out-HtmlView #-ScrollX -Filtering -DisablePaging -ScrollY -Online
@@ -1,11 +1,11 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Step 1 - Create report
$Report = Get-GPOZaurrPermission -Type All
$Report | ConvertTo-Excel -FilePath $Env:UserProfile\Desktop\GPOOutput.xlsx -ExcelWorkSheetName 'GPO Permissions Before' -AutoFilter -AutoFit
#$Report = Get-GPOZaurrPermission -Type All
#$Report | ConvertTo-Excel -FilePath $Env:UserProfile\Desktop\GPOOutput.xlsx -ExcelWorkSheetName 'GPO Permissions Before' -AutoFilter -AutoFit
# Step 2 - Verify couple of GPOS returned with whatif
#Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 4 -WhatIf
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 4 -WhatIf
# Step 3 - Confirm the change without whatif
#Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 4
@@ -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'
)
@@ -0,0 +1,5 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$SummaryHashtable = Get-GPOZaurrLink -AsHashTable -Summary
$SummaryHashtable | Format-Table -AutoSize
$SummaryHashtable[5]
+1 -1
View File
@@ -1,3 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-GPOZaurrLink | Format-Table -AutoSize *
Get-GPOZaurrLink -Verbose | Format-Table -AutoSize *
+1 -1
View File
@@ -2,6 +2,6 @@
Get-GPOZaurrLink -SearchBase 'OU=Domain Controllers,DC=ad,DC=evotec,DC=xyz' | Format-Table -AutoSize
Get-GPOZaurrLink -SearchBase 'OU=Computers,OU=Production,DC=ad,DC=evotec,DC=xyz' | Format-Table -AutoSize
Get-GPOZaurrLink -SearchBase 'OU=Accounts,OU=Production,DC=ad,DC=evotec,DC=xyz' | Format-Table -AutoSize
Get-GPOZaurrLink -SearchBase 'DC=ad,DC=evotec,DC=xyz' -SearchScope Base | Format-Table -AutoSize
+3 -2
View File
@@ -1,6 +1,7 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-ADOrganizationalUnit -Filter * -Properties distinguishedName, LinkedGroupPolicyObjects | Get-GPOZaurrLink | Format-Table
Get-ADOrganizationalUnit -Filter * -Properties canonicalname, distinguishedName, LinkedGroupPolicyObjects | Get-GPOZaurrLink | Format-Table
# gpLink is required property. While LinkedGroupPolicyObjects does work it doesn't contain information about enabled/enforced GPO
Get-ADOrganizationalUnit -Filter * -Properties distinguishedName, LinkedGroupPolicyObjects, gpLink | Get-GPOZaurrLink | Format-Table
Get-ADOrganizationalUnit -Filter * -Properties canonicalname, distinguishedName, LinkedGroupPolicyObjects, gpLink | Get-GPOZaurrLink | Format-Table
Get-ADObject -Filter * -Properties distinguishedName, gplink -Server 'ad.evotec.pl' | Get-GPOZaurrLink | Format-Table -AutoSize
Get-GPOZaurrLink | Format-Table -AutoSize
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-GPOZaurrLink -Site 'Katowice-1','Katowice-2' | Format-Table -AutoSize *
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-GPOZaurrLink -Linked Site | Format-Table -AutoSize *
@@ -0,0 +1,8 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Summary = Get-GPOZaurrLink -Summary
$Summary | Format-Table -AutoSize *
$OneGPO = $Summary | Where-Object { $_.DisplayName -eq 'ALL | Enable RDP' }
$OneGPO.Links
$OneGPO.LinksObjects | Format-Table *
+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
+41
View File
@@ -0,0 +1,41 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Clear-Host
$GPOName = 'TEST | Deny Admins'
$T = Get-GPOZaurrPermission -GPOName $GPOName #-IncludePermissionType GpoEditDeleteModifySecurity -PermitType Allow -Principal 'Domain Admins' -PrincipalType 'Name'
$T | Format-Table *
return
<#
# this will go and check for both Domain Admins / Enterprise Admins - if found won't do anything
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Type Administrative -Verbose
# this will go thru, because PrincipalType is not set to look by Name. Be precise with what you ask for
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'Domain Admins' -Verbose
# this will be detected as already existing
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'Domain Admins' -PrincipalType Name -Verbose
# this will be added only if it doesn't exists - assuming that przemyslaw.klys is displayed in Get-GPOZaurrPermissions
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoApply -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
# this will be added only if it doesn't exists - assuming that przemyslaw.klys is displayed in Get-GPOZaurrPermissions
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
# this will ADD system if it doesn't eists
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Type WellKnownAdministrative -Verbose
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoApply -Principal 'przemyslaw.klys' -Verbose
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'przemyslaw.klys' -Verbose
# this will not work because we already have GPOEditDeleteModifySecurity which is higher than GpoEDIT
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEdit -Principal 'przemyslaw.klys' -Verbose
#>
Add-GPOZaurrPermission -GPOName $GPOName -Type AuthenticatedUsers -PermissionType GpoRead -Verbose #-WhatIf
#$T = Get-GPOZaurrPermission -GPOName $GPOName #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
#$T | Format-Table -AutoSize *
#Remove-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoApply -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
#$T = Get-GPOZaurrPermission -GPOName $GPOName #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
#$T = Get-GPOZaurrPermission -GPOName $GPOName #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
#$T | Format-Table -AutoSize *
@@ -9,4 +9,4 @@ Invoke-GPOZaurrPermission -Linked Root -Verbose {
Remove-GPOPermission -Type NotAdministrative, NotWellKnownAdministrative -IncludePermissionType GpoEdit, GpoEditDeleteModifySecurity
Add-GPOPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity
#Add-GPOPermission -Type WellKnownAdministrative -IncludePermissionType GpoEditDeleteModifySecurity
} #-WhatIf #| Format-Table *
} -WhatIf
@@ -1,11 +1,11 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Invoke-GPOZaurrPermission -Verbose -SearchBase 'OU=Computers,OU=Production,DC=ad,DC=evotec,DC=xyz' {
Invoke-GPOZaurrPermission -Verbose -SearchBase 'OU=Production,DC=ad,DC=evotec,DC=pl' {
Set-GPOOwner -Type Administrative
#Set-GPOOwner -Principal 'EVOTEC\Enterprise Admins'
#Set-GPOOwner -Principal 'Domain Admins'
#Remove-GPOPermission -Type Administrative -IncludePermissionType GPOCustom
Remove-GPOPermission -Type NotAdministrative, NotWellKnownAdministrative -IncludePermissionType GpoEdit, GpoEditDeleteModifySecurity
#Add-GPOPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity
#Add-GPOPermission -Type WellKnownAdministrative -IncludePermissionType GpoEditDeleteModifySecurity
} -WhatIf #| Format-Table *
Add-GPOPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity
Add-GPOPermission -Type WellKnownAdministrative -IncludePermissionType GpoEditDeleteModifySecurity
} -WhatIf
@@ -1,10 +1,10 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Find broken GPOs
Get-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.pl' | Format-Table
Get-GPOZaurrBroken -Verbose | Format-Table # -IncludeDomains 'ad.evotec.pl' | Format-Table
# this allows you to process X amount of orphaned folders/files (good for testing)
Remove-GPOZaurrBroken -Verbose -WhatIf #-IncludeDomains 'ad.evotec.pl' #-LimitProcessing 2
Remove-GPOZaurrBroken -Verbose -WhatIf -Type AD -LimitProcessing 10 #-IncludeDomains 'ad.evotec.pl' #-LimitProcessing 2
# this runs for whole SYSVOL and checks things against GPOS
Remove-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf
Remove-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf -Type AD, SYSVOL
+3 -3
View File
@@ -8,7 +8,7 @@ Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
#Get-GPOZaurrLinkSummary -Report 'LinksSummary' -UnlimitedProperties | Format-Table *
$Report = Get-GPOZaurrLinkSummary #-UnlimitedProperties
$Report | Format-Table *
$Report.MultipleLinks | Format-Table *
#$Report | Format-Table
#$Report.MultipleLinks | Format-Table *
$Report.OneLink | Format-Table *
$Report.LinksSummary | Format-Table *
#$Report.LinksSummary | Format-Table *
+1 -1
View File
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Output = Invoke-GPOZaurrContent -Verbose -OutputType HTML, Object -Open
$Output = Invoke-GPOZaurrContent -Verbose -OutputType HTML, Object -Open -GPOPath "C:\Support\GitHub\GpoZaurr\Ignore\NewExamples" ##-Type LocalGroups
$Output | Format-Table
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Policies = Get-GPOZaurrFilesPolicyDefinition -Signature
$Policies | Format-Table
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Report on empty folders
Get-GPOZaurrFolders -FolderType Empty | Format-Table *
+1 -1
View File
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Cleanup based on https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/manually-clearing-the-conflictanddeleted-folder-in-dfsr/ba-p/395711
+2 -2
View File
@@ -1,7 +1,7 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Invoke-GPOZaurrSupport -ComputerName 'ad1.ad.evotec.xyz' -UserName 'EVOTEC\przemyslaw.klys' -Type NativeHTML -ForceGPResult -Verbose
#Invoke-GPOZaurrSupport -ComputerName 'ad1.ad.evotec.xyz' -UserName 'EVOTEC\przemyslaw.klys' -Type HTML -Verbose -Path $PSScriptRoot\Reports\GPOSupport.html
Invoke-GPOZaurrSupport -Type HTML -Verbose -Path $PSScriptRoot\Reports\GPOSupport.html -ComputerName ad1.ad.evotec.xyz
return
#$Support1 = Invoke-GPOZaurrSupport -ComputerName 'AD1' -UserName 'przemyslaw.klys' -Type Object
#$Support = Invoke-GPOZaurrSupport -ComputerName 'AD1' -UserName 'EVOTEC\Administrator' -Type Object
+1 -1
View File
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Extracts CSE from registry
$AllRegistryExtensions = Find-CSExtension
@@ -6,5 +6,10 @@
# Get same output DN, CanonicalName, BlockInheritance (True/False) + Users/Computers + UsersCount/ComputerCount for those with Blocked Inhertiance
# This is so you can have a list what machines are affected
$Objects = Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance
$ExcludedOU = @(
# Works on OU/
'ad.evotec.xyz/ITR02/Test'
)
$Objects = Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -Exclusions $ExcludedOU -IncludeGroupPoliciesForBlockedObjects
$Objects | Format-Table
+1 -1
View File
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$FilesAll = Get-GPOZaurrNetLogon -SkipOwner -IncludeDomains 'ad.evotec.pl' #-OwnerOnly
$FilesAll = Get-GPOZaurrNetLogon -IncludeDomains 'ad.evotec.xyz' -Verbose -OwnerOnly
$FilesAll | Format-Table -a *
+16 -4
View File
@@ -1,7 +1,19 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOOrphans -PassThru
$Output
Invoke-GPOZaurr -Type GPOOrganizationalUnit -Online -FilePath $PSScriptRoot\Reports\GPOZaurr.html
Write-Color -Text 'Output of nested report' -Color DarkYellow -LinesBefore 1 -LinesAfter 1
$Output.GPOOrphans
# 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'
}
+1 -1
View File
@@ -1,3 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type NetLogonPermissions, GPOOrphans, GPOList, GPOConsistency, GPOOwners, GPODuplicates
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOConsistency, GPOList, GPODuplicates, GPOBroken, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative, GPOPermissionsUnknown, GPOPermissions
@@ -5,7 +5,7 @@ $Types = @(
@{ Name = 'GPOConsistency'; Path = "$PSScriptRoot\Reports\GPOConsistency.html" }
@{ Name = 'GPODuplicates'; Path = "$PSScriptRoot\Reports\GPODuplicates.html" }
@{ Name = 'GPOList'; Path = "$PSScriptRoot\Reports\GPOList.html" }
@{ Name = 'GPOOrphans'; Path = "$PSScriptRoot\Reports\GPOOrphans.html" }
@{ Name = 'GPOBroken'; Path = "$PSScriptRoot\Reports\GPOBroken.html" }
@{ Name = 'GPOPassword'; Path = "$PSScriptRoot\Reports\GPOPassword.html" }
@{ Name = 'NetLogonPermissions'; Path = "$PSScriptRoot\Reports\NetLogonPermissions.html" }
)
+16
View File
@@ -0,0 +1,16 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$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 *
Invoke-GPOZaurr -Type GPOList -Exclusions {
Skip-GroupPolicy -Name 'All | Trusted Websites' -DomaiName 'ad.evotec.xyz'
'{D39BF08A-87BF-4662-BFA0-E56240EBD5A2}'
'COMPUTERS | Enable Sets'
}
+2 -2
View File
@@ -3,6 +3,6 @@
# Optimize All
Optimize-GPOZaurr -All -Verbose -IncludeDomains 'ad.evotec.pl' -LimitProcessing 1 {
Skip-GroupPolicy -Name 'TEST | Empty GPO - AD.EVOTEC.PL CrossDomain GPO' -DomaiName 'ad.evotec.pl'
}
} -WhatIf
# Optimize just one
#Optimize-GPOZaurr -GPOName 'TEST | Empty GPO - AD.EVOTEC.PL CrossDomain GPO' -WhatIf -Verbose
Optimize-GPOZaurr -GPOName 'TEST | Empty GPO - AD.EVOTEC.PL CrossDomain GPO' -WhatIf -Verbose
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-GPOZaurrPermissionAnalysis | Format-Table *
+3
View File
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Repair-GPOZaurrPermission -Verbose -WhatIf -Type Administrative -LimitProcessing 1
@@ -0,0 +1,5 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
#Get-GPOZaurrBrokenLink -Verbose | Format-Table -AutoSize *
Get-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl | Format-Table -AutoSize *
@@ -0,0 +1,5 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Repair-GPOZaurrBrokenLink -Verbose -LimitProcessing 1 #-WhatIf
#Repair-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl -LimitProcessing 30 #-WhatIf
@@ -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,16 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
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'
'*OU=Production,DC=ad,DC=evotec,DC=pl'
'*OU=Production,DC=ad,DC=evotec,DC=pl'
)
+6 -6
View File
@@ -4,11 +4,11 @@
CmdletsToExport = @()
CompanyName = 'Evotec'
CompatiblePSEditions = @('Desktop')
Copyright = '(c) 2011 - 2020 Przemyslaw Klys @ Evotec. All rights reserved.'
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-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-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-GPOZaurrNetLogonOwner', '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.96'
ModuleVersion = '0.0.143'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
@@ -18,15 +18,15 @@
}
}
RequiredModules = @(@{
ModuleVersion = '0.0.189'
ModuleVersion = '0.0.212'
ModuleName = 'PSSharedGoods'
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
}, @{
ModuleVersion = '0.0.103'
ModuleVersion = '0.0.134'
ModuleName = 'ADEssentials'
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
}, @{
ModuleVersion = '0.0.122'
ModuleVersion = '0.0.158'
ModuleName = 'PSWriteHTML'
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
+46 -6
View File
@@ -2,13 +2,53 @@
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue -Recurse )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue -Recurse )
#Dot source the files
Foreach ($import in @($Public + $Private)) {
Try {
. $import.fullname
} Catch {
Write-Error -Message "Failed to import function $($import.fullname): $_"
$AssemblyFolders = Get-ChildItem -Path $PSScriptRoot\Lib -Directory -ErrorAction SilentlyContinue
if ($AssemblyFolders.BaseName -contains 'Standard') {
$Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Standard\*.dll -ErrorAction SilentlyContinue )
} else {
if ($PSEdition -eq 'Core') {
$Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Core\*.dll -ErrorAction SilentlyContinue )
} else {
$Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Default\*.dll -ErrorAction SilentlyContinue )
}
}
$FoundErrors = @(
Foreach ($Import in @($Assembly)) {
try {
Add-Type -Path $Import.Fullname -ErrorAction Stop
} catch [System.Reflection.ReflectionTypeLoadException] {
Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
$LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
foreach ($E in $LoaderExceptions) {
Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
}
$true
#Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
} catch {
Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
$LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
foreach ($E in $LoaderExceptions) {
Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
}
$true
#Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
}
}
#Dot source the files
Foreach ($Import in @($Private + $Public)) {
Try {
. $Import.Fullname
} Catch {
Write-Error -Message "Failed to import functions from $($import.Fullname): $_"
$true
}
}
)
if ($FoundErrors.Count -gt 0) {
$ModuleName = (Get-ChildItem $PSScriptRoot\*.psd1).BaseName
Write-Warning "Importing module $ModuleName failed. Fix errors before continuing."
break
}
Export-ModuleMember -Function '*' -Alias '*'
+2 -2
View File
@@ -3,14 +3,14 @@
param(
[System.Xml.XmlElement]$Content,
[string] $ResultsType,
[Microsoft.GroupPolicy.GPRsop] $ResultantSetPolicy,
# [Microsoft.GroupPolicy.GPRsop] $ResultantSetPolicy,
[string] $Splitter = [System.Environment]::NewLine
)
$GPOPrimary = [ordered] @{
Summary = $null
SummaryDetails = [System.Collections.Generic.List[PSCustomObject]]::new()
SummaryDownload = $null
ResultantSetPolicy = $ResultantSetPolicy
#ResultantSetPolicy = $ResultantSetPolicy
GroupPolicies = $null
GroupPoliciesLinks = $null
+101
View File
@@ -0,0 +1,101 @@
function ConvertTo-XMLCertificates {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
[string[]] $Category,
[switch] $SingleObject
)
$SkipNames = ('Name', 'LocalName', 'NamespaceURI', 'Prefix', 'NodeType', 'ParentNode', 'OwnerDocument', 'IsEmpty', 'Attributes', 'HasAttributes', 'SchemaInfo', 'InnerXml', 'InnerText', 'NextSibling', 'PreviousSibling', 'ChildNodes', 'FirstChild', 'LastChild', 'HasChildNodes', 'IsReadOnly', 'OuterXml', 'BaseURI', 'PreviousText')
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Count = 0
Settings = $null
}
[Array] $CreateGPO['Settings'] = foreach ($Setting in $GPO.DataSet) {
$SettingName = $Setting.Name -split ":"
$MySettings = [ordered] @{
CreatedTime = $GPO.CreatedTime # : 06.06.2020 18:03:36
ModifiedTime = $GPO.ModifiedTime # : 17.06.2020 16:08:10
ReadTime = $GPO.ReadTime # : 13.08.2020 10:15:37
SecurityDescriptor = $GPO.SecurityDescriptor # : SecurityDescriptor
FilterDataAvailable = $GPO.FilterDataAvailable # : True
}
$Name = $SettingName[1]
#$Name = Format-ToTitleCase -Text $Setting.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
$MySettings['Name'] = $Name # $Setting.Name
ConvertTo-XMLNested -CreateGPO $MySettings -Setting $Setting -SkipNames $SkipNames #-Name $Name
if ($MySettings.Data) {
$bytes = $MySettings.Data -replace '\r?\n' -split '(?<=\G.{2})' -ne '' -replace '^', '0x' -as [byte[]]
$CertificateData = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes)
$MySettings['NotBefore'] = $CertificateData.NotBefore
$MySettings['NotAfter'] = $CertificateData.NotAfter
$MySettings['HasPrivateKey'] = $CertificateData.HasPrivateKey
$MySettings['Thumbprint'] = $CertificateData.Thumbprint
$MySettings['SerialNumber'] = $CertificateData.SerialNumber
$MySettings['Version'] = $CertificateData.Version
$MySettings['Handle'] = $CertificateData.Handle
$MySettings['SignatureAlgorithm'] = $CertificateData.SignatureAlgorithm.Value
$MySettings['SignatureAlgorithmName'] = $CertificateData.SignatureAlgorithm.FriendlyName
$MySettings['KeyUsages'] = $CertificateData.Extensions.KeyUsages
$MySettings.Remove('Data')
}
[PSCustomObject] $MySettings
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Setting in $GPO.DataSet) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
}
$SettingName = $Setting.Name -split ":"
$CreateGPO['CreatedTime'] = $GPO.CreatedTime # : 06.06.2020 18:03:36
$CreateGPO['ModifiedTime'] = $GPO.ModifiedTime # : 17.06.2020 16:08:10
$CreateGPO['ReadTime'] = $GPO.ReadTime # : 13.08.2020 10:15:37
$CreateGPO['SecurityDescriptor'] = $GPO.SecurityDescriptor # : SecurityDescriptor
$CreateGPO['FilterDataAvailable'] = $GPO.FilterDataAvailable # : True
$Name = $SettingName[1]
$CreateGPO['Name'] = $Name # $Setting.Name
ConvertTo-XMLNested -CreateGPO $CreateGPO -Setting $Setting -SkipNames $SkipNames #-Name $Name
if ($CreateGPO.Data) {
$bytes = $CreateGPO.Data -replace '\r?\n' -split '(?<=\G.{2})' -ne '' -replace '^', '0x' -as [byte[]]
$CertificateData = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes)
$CreateGPO['NotBefore'] = $CertificateData.NotBefore
$CreateGPO['NotAfter'] = $CertificateData.NotAfter
$CreateGPO['HasPrivateKey'] = $CertificateData.HasPrivateKey
$CreateGPO['Thumbprint'] = $CertificateData.Thumbprint
$CreateGPO['SerialNumber'] = $CertificateData.SerialNumber
$CreateGPO['Version'] = $CertificateData.Version
$CreateGPO['Handle'] = $CertificateData.Handle
$CreateGPO['SignatureAlgorithm'] = $CertificateData.SignatureAlgorithm.Value
$CreateGPO['SignatureAlgorithmName'] = $CertificateData.SignatureAlgorithm.FriendlyName
$CreateGPO['KeyUsages'] = $CertificateData.Extensions.KeyUsages
$CreateGPO.Remove('Data')
}
$CreateGPO['Filters'] = $Setting.Filters
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLDriveMapSettings {
function ConvertTo-XMLDriveMapSettings {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
@@ -0,0 +1,89 @@
function ConvertTo-XMLFolderRedirection {
[cmdletBinding()]
param(
[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
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
#GpoCategory = $GPOEntry.GpoCategory
#GpoSettings = $GPOEntry.GpoSettings
Count = 0
Settings = $null
}
[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'
GrantExclusiveRights = if ($Folder.GrantExclusiveRights -eq 'true') { $true } else { $false }
MoveContents = if ($Folder.MoveContents -eq 'true') { $true } else { $false }
FollowParent = if ($Folder.FollowParent -eq 'true') { $true } else { $false }
ApplyToDownLevel = if ($Folder.ApplyToDownLevel -eq 'true') { $true } else { $false }
DoNotCare = if ($Folder.DoNotCare -eq 'true') { $true } else { $false }
RedirectToLocal = if ($Folder.RedirectToLocal -eq 'true') { $true } else { $false }
PolicyRemovalBehavior = $Folder.PolicyRemovalBehavior # : LeaveContents
ConfigurationControl = if ($Folder.ConfigurationControl -eq 'GP') { 'Group Policy' } else { $Folder.ConfigurationControl } # : GP
PrimaryComputerEvaluation = $Folder.PrimaryComputerEvaluation # : PrimaryComputerPolicyDisabled
}
}
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Folder in $GPO.DataSet) {
foreach ($Location in $Folder.Location) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
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'
GrantExclusiveRights = if ($Folder.GrantExclusiveRights -eq 'true') { $true } else { $false }
MoveContents = if ($Folder.MoveContents -eq 'true') { $true } else { $false }
FollowParent = if ($Folder.FollowParent -eq 'true') { $true } else { $false }
ApplyToDownLevel = if ($Folder.ApplyToDownLevel -eq 'true') { $true } else { $false }
DoNotCare = if ($Folder.DoNotCare -eq 'true') { $true } else { $false }
RedirectToLocal = if ($Folder.RedirectToLocal -eq 'true') { $true } else { $false }
PolicyRemovalBehavior = $Folder.PolicyRemovalBehavior # : LeaveContents
ConfigurationControl = if ($Folder.ConfigurationControl -eq 'GP') { 'Group Policy' } else { $Folder.ConfigurationControl } # : GP
PrimaryComputerEvaluation = $Folder.PrimaryComputerEvaluation # : PrimaryComputerPolicyDisabled
Linked = $GPO.Linked
LinksCount = $GPO.LinksCount
Links = $GPO.Links
}
[PSCustomObject] $CreateGPO
}
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLGenericPolicy {
function ConvertTo-XMLGenericPolicy {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLGenericPublicKey {
function ConvertTo-XMLGenericPublicKey {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
@@ -1,4 +1,4 @@
function ConvertTo-XMLGenericSecuritySettings {
function ConvertTo-XMLGenericSecuritySettings {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLLocalGroups {
function ConvertTo-XMLLocalGroups {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLPrinter {
function ConvertTo-XMLPrinter {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLPrinterInternal {
function ConvertTo-XMLPrinterInternal {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
@@ -1,4 +1,4 @@
function ConvertTo-XMLRegistryAutologonOnReport {
function ConvertTo-XMLRegistryAutologonOnReport {
[cmdletBinding()]
param(
[PSCustomObject] $GPO
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLTaskScheduler {
function ConvertTo-XMLTaskScheduler {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+44
View File
@@ -0,0 +1,44 @@
function ConvertTo-XMLWindowsFirewall {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
[switch] $SingleObject
)
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
#GpoCategory = $GPOEntry.GpoCategory
#GpoSettings = $GPOEntry.GpoSettings
Count = 0
Settings = $null
}
[Array] $CreateGPO['Settings'] = foreach ($Policy in $GPO.DataSet) {
[PSCustomObject] @{
Name = $Policy.LocalName
Version = $Policy.PolicyVersion.Value
}
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Policy in $GPO.DataSet) {
[PSCustomObject]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Name = $Policy.LocalName
Version = $Policy.PolicyVersion.Value
Linked = $GPO.Linked
LinksCount = $GPO.LinksCount
Links = $GPO.Links
}
}
}
}
@@ -0,0 +1,56 @@
function ConvertTo-XMLWindowsFirewallConnectionSecurityAuthentiation {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
[switch] $SingleObject
)
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
#GpoCategory = $GPOEntry.GpoCategory
#GpoSettings = $GPOEntry.GpoSettings
Count = 0
Settings = $null
}
[Array] $CreateGPO['Settings'] = foreach ($Connection in $GPO.DataSet) {
[PSCustomObject] @{
Name = $Connection.LocalName
Version = $Connection.Version
ConnectionGUID = $Connection.GUID
Method = $Connection.AuthenticationSuites.Method #: MachineCert
CAName = $Connection.AuthenticationSuites.CAName #: DC = xyz, DC = evotec, DC = ad, CN = ad-ADCS-CA
CertAccountMapping = if ($Connection.AuthenticationSuites.CertAccountMapping -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.CertAccountMapping -eq 'false') { $false } else { $Connection.AuthenticationSuites.CertAccountMapping }
ExcludeCAName = if ($Connection.AuthenticationSuites.ExcludeCAName -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.ExcludeCAName -eq 'false') { $false } else { $Connection.AuthenticationSuites.ExcludeCAName }
HealthCert = if ($Connection.AuthenticationSuites.HealthCert -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.HealthCert -eq 'false') { $false } else { $Connection.AuthenticationSuites.HealthCert }
}
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Connection in $GPO.DataSet) {
[PSCustomObject]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Name = $Connection.LocalName
Version = $Connection.Version
ConnectionGUID = $Connection.GUID
Method = $Connection.AuthenticationSuites.Method #: MachineCert
CAName = $Connection.AuthenticationSuites.CAName #: DC = xyz, DC = evotec, DC = ad, CN = ad-ADCS-CA
CertAccountMapping = if ($Connection.AuthenticationSuites.CertAccountMapping -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.CertAccountMapping -eq 'false') { $false } else { $Connection.AuthenticationSuites.CertAccountMapping }
ExcludeCAName = if ($Connection.AuthenticationSuites.ExcludeCAName -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.ExcludeCAName -eq 'false') { $false } else { $Connection.AuthenticationSuites.ExcludeCAName }
HealthCert = if ($Connection.AuthenticationSuites.HealthCert -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.HealthCert -eq 'false') { $false } else { $Connection.AuthenticationSuites.HealthCert }
Linked = $GPO.Linked
LinksCount = $GPO.LinksCount
Links = $GPO.Links
}
}
}
}
@@ -0,0 +1,66 @@
function ConvertTo-XMLWindowsFirewallProfile {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
[switch] $SingleObject
)
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
#GpoCategory = $GPOEntry.GpoCategory
#GpoSettings = $GPOEntry.GpoSettings
Count = 0
Settings = $null
}
[Array] $CreateGPO['Settings'] = foreach ($Profile in $GPO.DataSet) {
[PSCustomObject] @{
Profile = $Profile.LocalName
EnableFirewall = if ($Profile.EnableFirewall.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
AllowLocalIPsecPolicyMerge = if ($Profile.AllowLocalIPsecPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
AllowLocalPolicyMerge = if ($Profile.AllowLocalPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DefaultInboundAction = if ($Profile.DefaultInboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DefaultOutboundAction = if ($Profile.DefaultOutboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DisableNotifications = if ($Profile.DisableNotifications.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DisableUnicastResponsesToMulticastBroadcast = if ($Profile.DisableUnicastResponsesToMulticastBroadcast.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DoNotAllowExceptions = if ($Profile.DoNotAllowExceptions.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
LogFilePath = if ($Profile.LogFilePath.Value) { $Profile.LogFilePath.Value } else { 'Not configured' }
LogDroppedPackets = if ($Profile.LogDroppedPackets.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
LogFileSize = if ($Profile.LogFileSize.Value) { $Profile.LogFileSize.Value } else { 'Not configured' }
LogSuccessfulConnections = if ($Profile.LogSuccessfulConnections.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
}
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Profile in $GPO.DataSet) {
[PSCustomObject]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Profile = $Profile.LocalName
EnableFirewall = if ($Profile.EnableFirewall.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
AllowLocalIPsecPolicyMerge = if ($Profile.AllowLocalIPsecPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
AllowLocalPolicyMerge = if ($Profile.AllowLocalPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DefaultInboundAction = if ($Profile.DefaultInboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DefaultOutboundAction = if ($Profile.DefaultOutboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DisableNotifications = if ($Profile.DisableNotifications.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DisableUnicastResponsesToMulticastBroadcast = if ($Profile.DisableUnicastResponsesToMulticastBroadcast.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
DoNotAllowExceptions = if ($Profile.DoNotAllowExceptions.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
LogFilePath = if ($Profile.LogFilePath.Value) { $Profile.LogFilePath.Value } else { 'Not configured' }
LogDroppedPackets = if ($Profile.LogDroppedPackets.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
LogFileSize = if ($Profile.LogFileSize.Value) { $Profile.LogFileSize.Value } else { 'Not configured' }
LogSuccessfulConnections = if ($Profile.LogSuccessfulConnections.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
Linked = $GPO.Linked
LinksCount = $GPO.LinksCount
Links = $GPO.Links
}
}
}
}
@@ -0,0 +1,133 @@
function ConvertTo-XMLWindowsFirewallRules {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
[switch] $SingleObject
)
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
#GpoCategory = $GPOEntry.GpoCategory
#GpoSettings = $GPOEntry.GpoSettings
Count = 0
Settings = $null
}
[Array] $CreateGPO['Settings'] = foreach ($Rule in $GPO.DataSet) {
[PSCustomObject] @{
Version = $Rule.Version
Type = if ($Rule.Dir -eq 'In') { 'Inbound' } elseif ($Rule.Dir -eq 'Out') { 'Outbound' } else { $Rule.Dir }
Name = $Rule.Name
Action = $Rule.Action
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
Profile = $Rule.Profile
Svc = $Rule.Svc
LocalAddressIPv4 = $Rule.LA4
LocalAddressIPv6 = $Rule.LA6
RemoteAddressIPV4 = $Rule.RA4
RemoteAddressIPV6 = $Rule.RA6
LocalPort = $Rule.LPort
RemotePort = $Rule.RPort
Description = $Rule.Desc
EmbedCtxt = $Rule.EmbedCtxt
Edge = $Rule.Edge
IFType = $Rule.IFType
Security = $Rule.Security
App = $Rule.App
Protocol = $Rule.Protocol
RMAuth = $Rule.RMAuth
RUAuth = $Rule.RUAuth
ICMP4 = $Rule.ICMP4
LocalName = $Rule.LocalName
}
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Rule in $GPO.DataSet) {
[PSCustomObject]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Version = $Rule.Version
Type = if ($Rule.Dir -eq 'In') { 'Inbound' } elseif ($Rule.Dir -eq 'Out') { 'Outbound' } else { $Rule.Dir }
Name = $Rule.Name
Action = $Rule.Action
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
Profile = $Rule.Profile
Svc = $Rule.Svc
LocalAddressIPv4 = $Rule.LA4
LocalAddressIPv6 = $Rule.LA6
RemoteAddressIPV4 = $Rule.RA4
RemoteAddressIPV6 = $Rule.RA6
LocalPort = $Rule.LPort
RemotePort = $Rule.RPort
Description = $Rule.Desc
EmbedCtxt = $Rule.EmbedCtxt
Edge = $Rule.Edge
IFType = $Rule.IFType
Security = $Rule.Security
App = $Rule.App
Protocol = $Rule.Protocol
RMAuth = $Rule.RMAuth
RUAuth = $Rule.RUAuth
ICMP4 = $Rule.ICMP4
LocalName = $Rule.LocalName
Linked = $GPO.Linked
LinksCount = $GPO.LinksCount
Links = $GPO.Links
}
}
}
}
<#
Version : 2.30
Action : Allow
Name : @%SystemRoot%\system32\firewallapi.dll,-37303
Dir : In
App : %SystemRoot%\system32\svchost.exe
Svc : dnscache
Profile : Public
RA4 : LocalSubnet
RA6 : LocalSubnet
LPort : 5353
Protocol : 17
Desc : @%SystemRoot%\system32\firewallapi.dll,-37304
Active : true
EmbedCtxt : @%SystemRoot%\system32\firewallapi.dll,-37302
Version : 2.30
Action : Allow
Name : TEST APP
Dir : In
App : C:\Test\exe.exe
Active : true
Version : 2.30
Action : Block
Name : Blo
Dir : Out
App : dfdff
Active : true
Version : 2.30
Action : Block
Name : @FirewallAPI.dll,-36012
Dir : Out
App : %SystemRoot%\system32\svchost.exe
Svc : Qwave
Profile : {Private, Public}
RPort : 2177
Protocol : 17
Desc : @FirewallAPI.dll,-36013
Active : true
EmbedCtxt : @FirewallAPI.dll,-36001
#>
@@ -0,0 +1,76 @@
function ConvertTo-XMLWindowsFirewallSecurityRules {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
[switch] $SingleObject
)
if ($SingleObject) {
$CreateGPO = [ordered]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
#GpoCategory = $GPOEntry.GpoCategory
#GpoSettings = $GPOEntry.GpoSettings
Count = 0
Settings = $null
}
[Array] $CreateGPO['Settings'] = foreach ($Rule in $GPO.DataSet) {
[PSCustomObject] @{
Version = $Rule.Version
Name = $Rule.Name
Action = $Rule.Action
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
Auth1Set = $Rule.Auth1Set
Auth2Set = $Rule.Auth2Set
Crypto2Set = $Rule.Crypto2Set
Description = $Rule.Desc
}
}
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
$CreateGPO['Linked'] = $GPO.Linked
$CreateGPO['LinksCount'] = $GPO.LinksCount
$CreateGPO['Links'] = $GPO.Links
[PSCustomObject] $CreateGPO
} else {
foreach ($Rule in $GPO.DataSet) {
[PSCustomObject]@{
DisplayName = $GPO.DisplayName
DomainName = $GPO.DomainName
GUID = $GPO.GUID
GpoType = $GPO.GpoType
Version = $Rule.Version
Name = $Rule.Name
Action = $Rule.Action
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
Auth1Set = $Rule.Auth1Set
Auth2Set = $Rule.Auth2Set
Crypto2Set = $Rule.Crypto2Set
Description = $Rule.Desc
Linked = $GPO.Linked
LinksCount = $GPO.LinksCount
Links = $GPO.Links
}
}
}
}
<#
Version : 2.30
Action : Boundary
Name : TeST Aut
Auth1Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE3}
Auth2Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE4}
Crypto2Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE2}
Desc :
Active : true
Version : 2.30
Action : Boundary
Name : CA TEST
Auth1Set : {0E3A2DDC-F31B-42B5-BEAC-890752F9C0BB}
Auth2Set : EmptySet
Crypto2Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE2}
Desc :
Active : true
#>
+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] $_ }
}
}
}
+94
View File
@@ -0,0 +1,94 @@
function Get-ChoosenDates {
[CmdletBinding()]
param(
[ValidateSet('Everything', 'PastHour', 'CurrentHour', 'PastDay', 'CurrentDay', 'PastMonth', 'CurrentMonth', 'PastQuarter', 'CurrentQuarter', 'Last14Days', 'Last7Days', 'Last3Days', 'Last1Days')][string] $DateRange
)
#$Dates = @(
# 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
}
}
#)
#$Dates
}
+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
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
function Get-GPOCategories {
function Get-GPOCategories {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+39
View File
@@ -0,0 +1,39 @@
function Get-GPOPrivInheritance {
[cmdletBinding()]
param(
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
[System.Collections.IDictionary] $CacheReturnedGPOs,
[System.Collections.IDictionary] $ForestInformation,
[string] $Domain,
[switch] $SkipDomainRoot,
[switch] $SkipDomainControllers
)
foreach ($Object in $ADObject) {
if ($SkipDomainRoot) {
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) {
# other skips Domain Root
continue
}
}
if ($SkipDomainControllers) {
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) {
# other skips Domain Controllers
continue
}
}
$Inheritance = Get-GPInheritance -Target $Object.DistinguishedName
foreach ($Link in $Inheritance.GpoLinks) {
[PSCustomObject] @{
DisplayName = $Link.DisplayName
DomainName = $Domain
GUID = $Link.GPOID
Enabled = $Link.Enabled
Enforced = $Link.Enforced
Order = $Link.Order
Target = $Object.DistinguishedName
TargetCanonical = $Object.CanonicalName
TargetObjectClass = $Object.objectClass
}
}
}
}
+92
View File
@@ -0,0 +1,92 @@
function Get-GPOPrivInheritanceLoop {
[cmdletBinding()]
param(
[Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
[System.Collections.IDictionary] $CacheReturnedGPOs,
[System.Collections.IDictionary] $ForestInformation,
[validateset('Root', 'DomainControllers', 'OrganizationalUnit')][string[]] $Linked,
[string] $SearchBase,
[Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope,
[string] $Filter
)
if (-not $ADObject) {
if ($Linked) {
foreach ($Domain in $ForestInformation.Domains) {
$Splat = @{
#Filter = $Filter
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
# Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')"
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
if ($Linked -contains 'DomainControllers') {
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
$Splat['SearchBase'] = $SearchBase
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation
}
if ($Linked -contains 'Root') {
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
$Splat['Filter'] = "objectClass -eq 'domainDNS'"
$Splat['SearchBase'] = $SearchBase
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation
}
if ($Linked -contains 'Site') {
# Sites are defined only in primary domain
# Sites are not supported by Get-GPInheritance
}
if ($Linked -contains 'OrganizationalUnit') {
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
$Splat['SearchBase'] = $SearchBase
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -SkipDomainRoot -SkipDomainControllers
}
}
} elseif ($Filter) {
foreach ($Domain in $ForestInformation.Domains) {
$Splat = @{
Filter = $Filter
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
if ($PSBoundParameters.ContainsKey('SearchBase')) {
$DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
if ($SearchBaseDC -ne $DomainDistinguishedName) {
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
continue
}
$Splat['SearchBase'] = $SearchBase
}
if ($PSBoundParameters.ContainsKey('SearchScope')) {
$Splat['SearchScope'] = $SearchScope
}
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation
}
}
} else {
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObject -Domain '' -ForestInformation $ForestInformation
}
}
+39
View File
@@ -0,0 +1,39 @@
function Get-GPOPrivLink {
[cmdletBinding()]
param(
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
[System.Collections.IDictionary] $CacheReturnedGPOs,
[System.Collections.IDictionary] $ForestInformation,
[string] $Domain,
[switch] $SkipDomainRoot,
[switch] $SkipDomainControllers,
[switch] $AsHashTable,
[switch] $SkipDuplicates
)
foreach ($Object in $ADObject) {
if ($SkipDomainRoot) {
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) {
# other skips Domain Root
continue
}
}
if ($SkipDomainControllers) {
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) {
# other skips Domain Controllers
continue
}
}
$OutputGPOs = Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache
foreach ($OutputGPO in $OutputGPOs) {
if (-not $SkipDuplicates) {
$OutputGPO
} else {
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
$OutputGPO
}
}
}
}
}
+197
View File
@@ -0,0 +1,197 @@
function Get-GPOZaurrLinkInheritance {
<#
.SYNOPSIS
Short description
.DESCRIPTION
Long description
.PARAMETER ADObject
Parameter description
.PARAMETER Filter
Parameter description
.PARAMETER SearchBase
Parameter description
.PARAMETER SearchScope
Parameter description
.PARAMETER Linked
Parameter description
.PARAMETER Limited
Parameter description
.PARAMETER SkipDuplicates
Parameter description
.PARAMETER GPOCache
Parameter description
.PARAMETER Forest
Parameter description
.PARAMETER ExcludeDomains
Parameter description
.PARAMETER IncludeDomains
Parameter description
.PARAMETER ExtendedForestInformation
Parameter description
.PARAMETER AsHashTable
Parameter description
.PARAMETER Summary
Parameter description
.EXAMPLE
$Output = Get-GPOZaurrLinkInheritance -Summary
$Output | Format-Table
$Output[5]
$Output[5].Links | Format-Table
$Output[5].LinksObjects | Format-Table
.NOTES
This is based on Get-GPInheritance which isn't ideal and doesn't support sites. Get-GPOZaurrLink is better. Leaving in case I need it later on for private use only.
#>
[cmdletbinding(DefaultParameterSetName = 'All')]
param(
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
# weirdly enough site doesn't really work this way unless you give it 'CN=Configuration,DC=ad,DC=evotec,DC=xyz' as SearchBase
[parameter(ParameterSetName = 'Filter')][string] $Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')",
[parameter(ParameterSetName = 'Filter')][string] $SearchBase,
[parameter(ParameterSetName = 'Filter')][Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope,
[parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'OrganizationalUnit')][string[]] $Linked,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[switch] $Limited,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[switch] $SkipDuplicates,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[System.Collections.IDictionary] $GPOCache,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[alias('ForestName')][string] $Forest,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[string[]] $ExcludeDomains,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[System.Collections.IDictionary] $ExtendedForestInformation,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[switch] $AsHashTable,
[parameter(ParameterSetName = 'Filter')]
[parameter(ParameterSetName = 'ADObject')]
[parameter(ParameterSetName = 'Linked')]
[switch] $Summary
)
Begin {
$CacheReturnedGPOs = [ordered] @{}
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
if (-not $GPOCache -and -not $Limited) {
$GPOCache = @{ }
# 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)"] = $_
}
}
}
}
Process {
if (-not $Filter -and -not $Linked) {
# We choose ALL, except SITE which is not supported gor Get-GPInheritance
# that's why it's better to use Get-GPOZaurrLink
#$Linked = 'Root', 'DomainControllers', 'Site', 'OrganizationalUnit'
}
$getGPOPrivInheritanceLoopSplat = @{
Linked = $Linked
ForestInformation = $ForestInformation
CacheReturnedGPOs = $CacheReturnedGPOs
SearchScope = $SearchScope
SearchBase = $SearchBase
ADObject = $ADObject
Filter = $Filter
}
Remove-EmptyValue -Hashtable $getGPOPrivInheritanceLoopSplat -Recursive
# we need to use nested functions to support pipeline output and as hashtable and reporting that returns single value
if ($AsHashTable -or $Summary) {
$HashTable = [ordered] @{}
$SummaryHashtable = [ordered] @{}
$Links = Get-GPOPrivInheritanceLoop @getGPOPrivInheritanceLoopSplat
foreach ($Link in $Links) {
$Key = -join ($Link.DomainName, $Link.GUID)
if (-not $HashTable[$Key]) {
$HashTable[$Key] = [System.Collections.Generic.List[PSCustomObject]]::new()
}
$HashTable[$Key].Add($Link)
}
foreach ($Key in $HashTable.Keys) {
[Array] $Link = $HashTable[$Key]
$EnabledLinks = $Link.Enabled.Where( { $_ -eq $true }, 'split')
if ($EnabledLinks[0].Count -gt 0) {
$IsLinked = $true
} else {
$IsLinked = $false
}
$SummaryLink = [PSCustomObject] @{
DisplayName = $Link[0].DisplayName
DomainName = $Link[0].DomainName
GUID = $Link[0].GUID
Linked = $IsLinked
LinksCount = $Link.Count
LinksEnabledCount = $EnabledLinks[0].Count
LinksDisabledCount = $EnabledLinks[1].Count
Links = $Link.Target
LinksObjects = $Link
}
$SummaryHashtable[$Key] = $SummaryLink
}
if ($AsHashTable -and $Summary) {
$SummaryHashtable
} elseif ($AsHashTable) {
$HashTable
} elseif ($Summary) {
$SummaryHashtable.Values
}
} else {
Get-GPOPrivInheritanceLoop @getGPOPrivInheritanceLoopSplat
}
}
End {
}
}
+175
View File
@@ -0,0 +1,175 @@
function Get-GPOZaurrLinkLoop {
[cmdletBinding()]
param(
[Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
[System.Collections.IDictionary] $CacheReturnedGPOs,
[System.Collections.IDictionary] $ForestInformation,
[validateset('All', 'Root', 'DomainControllers', 'Site', 'OrganizationalUnit')][string[]] $Linked,
[string] $SearchBase,
[Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope,
[string] $Filter,
[switch] $SkipDuplicates,
[string[]] $Site
)
if (-not $ADObject) {
if ($Site) {
foreach ($S in $Site) {
foreach ($Domain in $ForestInformation.Domains) {
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for site $Site"
# Sites are defined only in primary domain
if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) {
$Splat = @{
#Filter = $Filter
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
# Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')"
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
$Splat['Filter'] = "(objectClass -eq 'site') -and (name -eq '$S')"
$Splat['SearchBase'] = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'])
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
}
}
} elseif ($SearchBase -or $SearchScope -or $Filter) {
foreach ($Domain in $ForestInformation.Domains) {
if (-not $Filter) {
$Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')"
}
$Splat = @{
Filter = $Filter
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
if ($PSBoundParameters.ContainsKey('SearchBase')) {
$DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
if ($SearchBaseDC -ne $DomainDistinguishedName) {
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
continue
}
$Splat['SearchBase'] = $SearchBase
}
if ($PSBoundParameters.ContainsKey('SearchScope')) {
$Splat['SearchScope'] = $SearchScope
}
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
} elseif (-not $Filter) {
# if not linked, we force it to All
if (-not $Linked) {
$Linked = 'All'
}
foreach ($Domain in $ForestInformation.Domains) {
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain"
$Splat = @{
#Filter = $Filter
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
# Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')"
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
if ($Linked -contains 'Root' -or $Linked -contains 'All') {
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at ROOT level"
$Splat['Filter'] = "objectClass -eq 'domainDNS'"
$Splat['SearchBase'] = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
if ($Linked -contains 'Site' -or $Linked -contains 'All') {
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at SITE level"
# Sites are defined only in primary domain
if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) {
$Splat['Filter'] = "(objectClass -eq 'site')"
$Splat['SearchBase'] = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'])
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
}
if ($Linked -contains 'DomainControllers' -or $Linked -contains 'All') {
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at DC level"
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
$Splat['SearchBase'] = $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
if ($Linked -contains 'OrganizationalUnit' -or $Linked -contains 'All') {
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at OU level"
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
$Splat['SearchBase'] = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -SkipDomainRoot -SkipDomainControllers -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
}
}
<#
elseif ($Filter) {
foreach ($Domain in $ForestInformation.Domains) {
$Splat = @{
Filter = $Filter
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
if ($PSBoundParameters.ContainsKey('SearchBase')) {
$DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
if ($SearchBaseDC -ne $DomainDistinguishedName) {
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
continue
}
$Splat['SearchBase'] = $SearchBase
}
if ($PSBoundParameters.ContainsKey('SearchScope')) {
$Splat['SearchScope'] = $SearchScope
}
try {
$ADObjectGPO = Get-ADObject @Splat
} catch {
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
}
if ($ADObjectGPO) {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
}
#>
} else {
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObject -Domain '' -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
}
}
+5 -2
View File
@@ -14,7 +14,10 @@
if (-not $ADAdministrativeGroups) {
$ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
}
$AdministrativeExists = @{
$AdministrativeExists = [ordered] @{
DisplayName = $GPOPermissions[0].DisplayName
DomainName = $GPOPermissions[0].DomainName
GUID = $GPOPermissions[0].GUID
Skip = $false
DomainAdmins = $false
EnterpriseAdmins = $false
@@ -55,5 +58,5 @@
}
}
}
$AdministrativeExists
[PSCustomObject] $AdministrativeExists
}
+62 -60
View File
@@ -6,69 +6,71 @@
[System.Collections.IDictionary] $GPOCache
)
if ($Object.GpLink -and $Object.GpLink.Trim() -ne '') {
#$Object.GpLink -split { $_ -eq '[' -or $_ -eq ']' } -replace ';0' -replace 'LDAP://'
$Object.GpLink -split '\[LDAP://' -split ';' | ForEach-Object -Process {
#Write-Verbose $_
if ($_.Length -gt 10) {
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN
$Output = [ordered] @{
DistinguishedName = $Object.DistinguishedName
CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName }
Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}'
}
$Search = -join ($DomainCN, $Output['Guid'])
if ($GPOCache -and -not $Limited) {
if ($GPOCache[$Search]) {
$Output['DisplayName'] = $GPOCache[$Search].DisplayName
$Output['DomainName'] = $GPOCache[$Search].DomainName
$Output['Owner'] = $GPOCache[$Search].Owner
$Output['GpoStatus'] = $GPOCache[$Search].GpoStatus
$Output['Description'] = $GPOCache[$Search].Description
$Output['CreationTime'] = $GPOCache[$Search].CreationTime
$Output['ModificationTime'] = $GPOCache[$Search].ModificationTime
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC
$Output['GPODistinguishedName'] = $_
[PSCustomObject] $Output
} else {
Write-Warning "Get-PrivGPOZaurrLink - Couldn't find link $Search in a GPO Cache. Lack of permissions for given GPO? Are you running as admin? Skipping."
}
} else {
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC
$Output['GPODistinguishedName'] = $_
[PSCustomObject] $Output
}
}
}
$ObjectsToProcess = $Object.GpLink -split '\]\['
} elseif ($Object.LinkedGroupPolicyObjects -and $Object.LinkedGroupPolicyObjects.Trim() -ne '') {
$Object.LinkedGroupPolicyObjects -split '\[LDAP://' -split ';' | ForEach-Object -Process {
if ($_.Length -gt 10) {
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN
$Output = [ordered] @{
DistinguishedName = $Object.DistinguishedName
CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName }
Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}'
}
$Search = -join ($DomainCN, $Output['Guid'])
if ($GPOCache -and -not $Limited) {
if ($GPOCache[$Search]) {
$Output['Name'] = $GPOCache[$Search].DisplayName
$Output['DomainName'] = $GPOCache[$Search].DomainName
$Output['Owner'] = $GPOCache[$Search].Owner
$Output['GpoStatus'] = $GPOCache[$Search].GpoStatus
$Output['Description'] = $GPOCache[$Search].Description
$Output['CreationTime'] = $GPOCache[$Search].CreationTime
$Output['ModificationTime'] = $GPOCache[$Search].ModificationTime
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC
$Output['GPODistinguishedName'] = $_
[PSCustomObject] $Output
} else {
Write-Warning "Get-PrivGPOZaurrLink - Couldn't find link $Search in a GPO Cache. Lack of permissions for given GPO? Are you running as admin? Skipping."
}
$ObjectsToProcess = $Object.LinkedGroupPolicyObjects -split '\]\['
} else {
$ObjectsToProcess = $null
}
$ObjectsToProcess | ForEach-Object -Process {
$Link = $_ -replace 'LDAP://' -replace '\]' -replace '\['
if ($Link.Length -gt 10) {
$SplitGPLink = $Link -split ';'
$DN = $SplitGPLink[0]
$Option = $SplitGPLink[1]
if ($Option -eq '0') {
$Enforced = $false
$Enabled = $true
} elseif ($Option -eq '1') {
$Enabled = $false
$Enforced = $false
} elseif ($Option -eq '2') {
$Enabled = $true
$Enforced = $true
} elseif ($Option -eq '3') {
$Enabled = $false
$Enforced = $true
} else {
if ($Object.GpLink) {
Write-Warning "Get-PrivGPOZaurrLink - This should't happen. Please investigate - Option: $Option"
} else {
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC
$Output['GPODistinguishedName'] = $_
[PSCustomObject] $Output
Write-Warning "Get-PrivGPOZaurrLink - Property GPLink is required to be able to tell if Enabled/Enforced is added. Skipping those settings."
}
$Enabled = $null
$Enforced = $null
}
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $DN -ToDomainCN
$Output = [ordered] @{
DistinguishedName = $Object.DistinguishedName
#Domain = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDomainCN
CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName }
Guid = [Regex]::Match($DN, '(?={)(.*)(?<=})').Value -replace '{' -replace '}'
Enforced = $Enforced
Enabled = $Enabled
ObjectClass = $Object.ObjectClass
}
$Search = -join ($DomainCN, $Output['Guid'])
if ($GPOCache -and -not $Limited) {
if ($GPOCache[$Search]) {
$Output['DisplayName'] = $GPOCache[$Search].DisplayName
$Output['DomainName'] = $GPOCache[$Search].DomainName
$Output['Owner'] = $GPOCache[$Search].Owner
$Output['GpoStatus'] = $GPOCache[$Search].GpoStatus
$Output['Description'] = $GPOCache[$Search].Description
$Output['CreationTime'] = $GPOCache[$Search].CreationTime
$Output['ModificationTime'] = $GPOCache[$Search].ModificationTime
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $DN -ToDC
$Output['GPODistinguishedName'] = $DN
# This is object name, usually used for sites
$Output['Name'] = $Object.Name
[PSCustomObject] $Output
} else {
Write-Warning "Get-PrivGPOZaurrLink - Couldn't find link $Search in a GPO Cache. Lack of permissions for given GPO? Are you running as admin? Skipping."
}
} else {
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $DN -ToDC
$Output['GPODistinguishedName'] = $DN
[PSCustomObject] $Output
}
}
}
+140 -62
View File
@@ -9,25 +9,67 @@
[string] $Splitter = [System.Environment]::NewLine,
[switch] $ReturnObject,
[System.Collections.IDictionary] $ExcludeGroupPolicies,
[string[]] $Type
[string[]] $Type,
[System.Collections.IDictionary] $LinksSummaryCache
)
if ($XMLContent.GPO.LinksTo) {
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
[Array] $LinksEnabled = $LinkSplit[0]
[Array] $LinksDisabled = $LinkSplit[1]
$LinksEnabledCount = $LinksEnabled.Count
$LinksDisabledCount = $LinksDisabled.Count
$LinksTotalCount = ([Array] $XMLContent.GPO.LinksTo).Count
if ($LinksEnabledCount -eq 0) {
$Linked = $false
$DisplayName = $XMLContent.GPO.Name
$DomainName = $XMLContent.GPO.Identifier.Domain.'#text'
if ($LinksSummaryCache) {
$SearchGUID = -join ($XMLContent.GPO.Identifier.Domain.'#text', $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}')
if ($LinksSummaryCache[$SearchGUID]) {
$Linked = $LinksSummaryCache[$SearchGUID].Linked
$LinksEnabledCount = $LinksSummaryCache[$SearchGUID].LinksEnabledCount
$LinksDisabledCount = $LinksSummaryCache[$SearchGUID].LinksDisabledCount
$LinksTotalCount = $LinksSummaryCache[$SearchGUID].LinksCount
$Links = $LinksSummaryCache[$SearchGUID].Links
$LinksObjects = $LinksSummaryCache[$SearchGUID].LinksObjects
} else {
$Linked = $true
$Linked = $false
$LinksEnabledCount = 0
$LinksDisabledCount = 0
$LinksTotalCount = 0
$Links = $null
$LinksObjects = $null
}
} else {
$Linked = $false
$LinksEnabledCount = 0
$LinksDisabledCount = 0
$LinksTotalCount = 0
if ($XMLContent.GPO.LinksTo) {
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
[Array] $LinksEnabled = $LinkSplit[0]
[Array] $LinksDisabled = $LinkSplit[1]
$LinksEnabledCount = $LinksEnabled.Count
$LinksDisabledCount = $LinksDisabled.Count
$LinksTotalCount = ([Array] $XMLContent.GPO.LinksTo).Count
if ($LinksEnabledCount -eq 0) {
$Linked = $false
} else {
$Linked = $true
}
$Links = @(
$XMLContent.GPO.LinksTo | ForEach-Object -Process {
if ($_) {
$_.SOMPath
}
}
) -join $Splitter
$LinksObjects = $XMLContent.GPO.LinksTo | ForEach-Object -Process {
if ($_) {
[PSCustomObject] @{
CanonicalName = $_.SOMPath
Enabled = $_.Enabled
NoOverride = $_.NoOverride
}
}
}
} else {
$Linked = $false
$LinksEnabledCount = 0
$LinksDisabledCount = 0
$LinksTotalCount = 0
$Links = $null
$LinksObjects = $null
}
}
# Find proper values for enabled/disabled user/computer settings
if ($XMLContent.GPO.Computer.Enabled -eq 'False') {
@@ -35,7 +77,7 @@
} elseif ($XMLContent.GPO.Computer.Enabled -eq 'True') {
$ComputerEnabled = $true
} else {
Write-Warning "Get-XMLGPO - Computer enabled not set to true or false. Weird."
Write-Warning "Get-XMLGPO - Computer enabled not set to true or false [$DisplayName/$DomainName]. Weird."
$ComputerEnabled = $null
}
if ($XMLContent.GPO.User.Enabled -eq 'False') {
@@ -43,7 +85,7 @@
} elseif ($XMLContent.GPO.User.Enabled -eq 'True') {
$UserEnabled = $true
} else {
Write-Warning "Get-XMLGPO - User enabled not set to true or false. Weird."
Write-Warning "Get-XMLGPO - User enabled not set to true or false [$DisplayName/$DomainName] . Weird."
$UserEnabled = $null
}
# Translate Enabled to same as GPO GUI
@@ -62,8 +104,8 @@
}
# This is kind of old way of doing things, but it's superseded by other way below
$ComputerSettingsAvailable = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true }
$UserSettingsAvailable = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true }
[bool] $ComputerSettingsAvailable = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true }
[bool] $UserSettingsAvailable = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true }
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
$NoSettings = $true
@@ -74,35 +116,58 @@
# $OutputUser = $XMLContent.GPO.User.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
# $OutputComputer = $XMLContent.GPO.Computer.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
$OutputUser = foreach ($ExtensionType in $XMLContent.GPO.User.ExtensionData.Extension) {
if ($ExtensionType) {
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
try {
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
} catch {
Write-Warning "Get-XMLGPO - things went sideways $($_.Exception.Message)"
continue
}
# This is additional check we do for error check to prevent false-positives for EMPTY on non-english language
$PreCheckOutputUser = $false
$PreCheckOutputComputer = $false
foreach ($Extension in $XMLContent.GPO.User.ExtensionData) {
if ($Extension.Error) {
$PreCheckOutputUser = $true
}
$KeysToLoop
}
$OutputComputer = foreach ($ExtensionType in $XMLContent.GPO.Computer.ExtensionData.Extension) {
if ($ExtensionType) {
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
try {
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
} catch {
Write-Warning "Get-XMLGPO - things went sideways $($_.Exception.Message)"
continue
}
foreach ($Extension in $XMLContent.GPO.Computer.ExtensionData) {
if ($Extension.Error) {
$PreCheckOutputComputer = $true
}
$KeysToLoop
}
if ($PreCheckOutputComputer -eq $true -or $PreCheckOutputUser -eq $true) {
# in some cases GPResult seems to return an error - this was first noticed by user when using Dutch based system
# I am not sure if it's possible to fix this error for users, but once that happens checking if GPO is empty fails using the method below
# therefore we will use the old method of assuming something is empty or not empty in such case
Write-Warning "Get-XMLGPO - Reading GPO content [$DisplayName/$DomainName] returned an error. This may be because of non-english language. Assesing EMPTY using old method which can report false positives. Be careful please."
$OutputUser = @()
$OutputComputer = @()
} else {
[Array] $OutputUser = foreach ($ExtensionType in $XMLContent.GPO.User.ExtensionData.Extension) {
if ($ExtensionType) {
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
try {
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
} catch {
Write-Warning "Get-XMLGPO - things went sideways [$DisplayName/$DomainName]. Error $($_.Exception.Message)"
continue
}
}
$KeysToLoop
}
[Array] $OutputComputer = foreach ($ExtensionType in $XMLContent.GPO.Computer.ExtensionData.Extension) {
if ($ExtensionType) {
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
try {
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
} catch {
Write-Warning "Get-XMLGPO - things went sideways [$DisplayName/$DomainName]. Error $($_.Exception.Message)"
continue
}
}
$KeysToLoop
}
[bool] $ComputerSettingsAvailable = if ($OutputComputer.Count -gt 0) { $true } else { $false }
[bool] $UserSettingsAvailable = if ($OutputUser.Count -gt 0) { $true } else { $false }
}
$ComputerSettingsAvailable = if ($OutputComputer) { $true } else { $false }
$UserSettingsAvailable = if ($OutputUser) { $true } else { $false }
if (-not $ComputerSettingsAvailable -and -not $UserSettingsAvailable) {
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
$Empty = $true
} else {
$Empty = $false
@@ -165,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
}
}
@@ -217,12 +292,15 @@
'DisplayName' = $XMLContent.GPO.Name
'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text'
'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}'
'Days' = (New-TimeSpan -Start ([DateTime] $XMLContent.GPO.ModifiedTime) -End (Get-Date)).Days
'Empty' = $Empty
'Linked' = $Linked
'Enabled' = $EnabledBool
'Optimized' = $Optimized
'Problem' = $Problem
'ApplyPermission' = $null
'Exclude' = $Exclude
'Description' = $GPO.Description
'ComputerPolicies' = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
'UserPolicies' = $XMLContent.GPO.User.ExtensionData.Name -join ", "
'LinksCount' = $LinksTotalCount
@@ -237,8 +315,8 @@
'UserSettingsAvailable' = $UserSettingsAvailable
#'ComputerSettingsAvailableReal' = $ComputerSettingsAvailableReal
#'UserSettingsAvailableReal' = $UserSettingsAvailableReal
'ComputerSettingsTypes' = $OutputComputer.Name
'UserSettingsTypes' = $OutputUser.Name
'ComputerSettingsTypes' = $OutputComputer.Name -join ", "
'UserSettingsTypes' = $OutputUser.Name -join ", "
'ComputerEnabled' = $ComputerEnabled
'UserEnabled' = $UserEnabled
'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" }
@@ -279,24 +357,19 @@
}
)
'Auditing' = if ($XMLContent.GPO.SecurityDescriptor.AuditingPresent.'#text' -eq 'true') { $true } else { $false }
'Links' = @(
$XMLContent.GPO.LinksTo | ForEach-Object -Process {
if ($_) {
$_.SOMPath
}
}
) -join $Splitter
'LinksObjects' = $XMLContent.GPO.LinksTo | ForEach-Object -Process {
if ($_) {
[PSCustomObject] @{
CanonicalName = $_.SOMPath
Enabled = $_.Enabled
NoOverride = $_.NoOverride
}
}
}
'Links' = $Links
'LinksObjects' = $LinksObjects
'GPOObject' = $GPO
}
if ($GPOOutput.ACL) {
$GPOOutput.ApplyPermission = $false
foreach ($Permission in $GPOOutput.ACL) {
if ($Permission.Permissions -eq 'Apply Group Policy') {
$GPOOutput.ApplyPermission = $true
}
}
}
}
if ($PermissionsOnly -or $OwnerOnly) {
$GPOOutput
@@ -319,6 +392,11 @@
$GPOOutput
}
}
if ($Type -contains 'NoApplyPermission') {
if ($GPOOutput.ApplyPermission -eq $false) {
$GPOOutput
}
}
}
}
}
+215 -3
View File
@@ -4,19 +4,231 @@
ActionRequired = $null
Data = $null
Execute = {
Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
if ($Script:Reporting['GPOBlockedInheritance']['Exclusions']) {
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $Excludeomains -Exclusions $Script:Reporting['GPOBlockedInheritance']['Exclusions']
} else {
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $Excludeomains
}
}
Processing = {
foreach ($GPO in $Script:Reporting['GPOBlockedInheritance']['Data']) {
if (-not $Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$GPO.DomainName] = 0
}
if ($GPO.Exclude -eq $true) {
$Script:Reporting['GPOBlockedInheritance']['Variables']['Exclude']++
$Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude'] + $GPO.UsersCount
$Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude'] + $GPO.ComputersCount
} else {
$Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'] + $GPO.UsersCount
$Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'] + $GPO.ComputersCount
}
$Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedIncludingExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedIncludingExclude'] + $GPO.UsersCount
$Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedIncludingExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedIncludingExclude'] + $GPO.ComputersCount
if ($GPO.Exclude -eq $false -and ($GPO.UsersCount -gt 0 -or $GPO.ComputersCount -gt 0)) {
$Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigation']++
$Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$GPO.DomainName]++
}
if ($GPO.Exclude -eq $false -and ($GPO.UsersCount -eq 0 -and $GPO.ComputersCount -eq 0)) {
$Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmless']++
$Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$GPO.DomainName]++
}
# add gpo from blocked inheritance to create additional table
#foreach ($GpoBlocked in $Script:Reporting['GPOBlockedInheritance']['Data'].GroupPolicies) {
#$Script:Reporting['GPOBlockedInheritance']['Variables']['GroupPolicies'].Add($GpoBlocked)
#}
}
if ($Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigation'] -gt 0 -or $Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmless'] -gt 0) {
$Script:Reporting['GPOBlockedInheritance']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOBlockedInheritance']['ActionRequired'] = $false
}
}
Resources = @(
'http://www.firewall.cx/microsoft-knowledgebase/windows-2012/1056-windows-2012-group-policy-enforcement.html'
)
Variables = @{
Total = 0
Exclude = 0
RequiresInvesigation = 0
RequiresInvesigationPerDomain = [ordered] @{}
DeletionHarmless = 0
DeletionHarmlessPerDomain = [ordered] @{}
UsersAffected = 0
UsersAffectedExclude = 0
UsersAffectedIncludingExclude = 0
ComputersAffected = 0
ComputersAffectedIncludingExclude = 0
ComputersAffectedExclude = 0
GroupPolicies = [System.Collections.Generic.List[PSCustomObject]]::new()
}
Overview = {
}
Summary = {
New-HTMLText -FontSize 10pt -TextBlock {
"By default, group policy settings that are linked to parent objects are inherited to the child objects in the active directory hierarchy. "
"By default, Default Domain Policy is linked to the domain and is inherited to all the child objects of the domain hierarchy. "
"So does any other policies linked to the top level OU's. "
}
New-HTMLText -Text "Blocked Inheritance" -FontSize 10pt -FontWeight bold
New-HTMLText -FontSize 10pt -Text @(
"As GPOs can be inherited by default, they can also be blocked, if required using the Block Inheritance. "
"If the Block Inheritance setting is enabled, the inheritance of group policy setting is blocked. "
"This setting is mostly used when the OU contains users or computers that require different settings than what is applied to the domain level. "
"Unfortunetly blocking inheritance can have serious security consequences. "
)
New-HTMLText -Text @(
'As it stands currently there are ',
$Script:Reporting['GPOBlockedInheritance']['Data'].Count,
' organisational units with '
'GPO Inheritance Block'
' out of which '
$Script:Reporting['GPOBlockedInheritance']['Variables']['Exclude'],
' are marked as Excluded '
'(approved by IT). '
) -FontSize 10pt -FontWeight normal, bold, normal, bold, normal, bold, normal, bold -LineBreak
if ($Script:Reporting['GPOBlockedInheritance']['Data'].Count -ne 0) {
New-HTMLText -Text 'Users & Computers affected by inheritance blocks:' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'], ' users affected due to inheritance blocks' -FontWeight bold, normal
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude'], ' users affected, but approved/excluded, due to inheritance blocks' -FontWeight bold, normal
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'], ' computers affected due to inheritance blocks' -FontWeight bold, normal
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude'], ' computers affected, but approved/excluded, due to inheritance blocks' -FontWeight bold, normal
} -FontSize 10pt
New-HTMLText -Text 'Following domains require:' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain proposes ", $Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$Domain], " investigation (computers or users inside)." -FontWeight normal, bold, normal
New-HTMLListItem -Text "$Domain proposes ", $Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$Domain], " removal (mostly harmless due to no computers or users inside)." -FontWeight normal, bold, normal
}
} -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-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['Data'] -Filtering
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOBlockedInheritance']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartLegend -Names 'Affected', 'Affected, but excluded' -Color Salmon, PaleGreen
New-ChartBarOptions -Type barStacked
New-ChartBar -Name 'Users' -Value $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'], $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude']
New-ChartBar -Name 'Computers' -Value $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'], $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude']
} -Title 'Users & Computers affected due to blocked inheritance' -TitleAlignment center
}
}
New-HTMLSection -Name 'Organizational Units with Group Policy Blocked Inheritance' {
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['Data'] -Filtering {
New-TableEvent -TableID 'TableWithGroupPoliciesBlockedInheritance' -SourceColumnID 8 -TargetColumnID 9
New-HTMLTableCondition -Name 'Exclude' -Value $true -BackgroundColor DeepSkyBlue -ComparisonType string -Row
New-TableConditionGroup {
New-TableCondition -Name 'BlockedInheritance' -Value $true
New-TableCondition -Name 'Exclude' -Value $false
} -BackgroundColor Salmon -FailBackgroundColor SpringGreen -HighlightHeaders 'BlockedInheritance', 'Exclude'
New-TableConditionGroup {
New-TableCondition -Name 'UsersCount' -Value 0
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 -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 -DataTableID 'TableWithGroupPoliciesBlockedInheritance'
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix - Organizational Units with Group Policy Blocked Inheritance' {
New-HTMLContainer {
New-HTMLSpanStyle -FontSize 10pt {
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['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. "
"Please keep in mind that if exclusions for some Organizational OU's were defined you need to pass them to cmdlet below to not remove approved GPO Inheritance Blocks. "
"To generate new report please use:"
)
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBlockedGPOInheritanceBefore.html -Verbose -Type GPOBlockedInheritance
}
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 {
$GPOOutput = Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance
$GPOOutput | Format-Table # do your actions as desired
}
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
}
New-HTMLWizardStep -Name 'Remove OU GPO Inheritance Blocks' {
New-HTMLText -Text @(
"Removing inheritance blocks is quite trivial and can be done from GPO GUI. However knowing when to remove is the important part. "
"Please consult other Domain Admins before removing any inheritance blocks, and either approve exclusion or remove blocking inheritance. "
)
}
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\GPOZaurrBlockedGPOInheritanceAfter.html -Verbose -Type GPOBlockedInheritance
}
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['GPOBlockedInheritance']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['WarningsAndErrors'] -Filtering {
+151
View File
@@ -0,0 +1,151 @@
$GPOZaurrBrokenLink = [ordered] @{
Name = 'Group Policy Broken Links'
Enabled = $true
ActionRequired = $null
Data = $null
Execute = {
Get-GPOZaurrBrokenLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
Processing = {
$Script:Reporting['GPOBrokenLink']['Variables']['RequireDeletion'] = $Script:Reporting['GPOBrokenLink']['Data'].Count
$Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'] = @{}
$Script:Reporting['GPOBrokenLink']['Variables']['Unique'] = @{}
foreach ($Link In $Script:Reporting['GPOBrokenLink']['Data']) {
$DomainName = ConvertFrom-DistinguishedName -ToDomainCN -DistinguishedName $Link.DistinguishedName
# Create Per Domain Variables
if (-not $Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$DomainName]) {
$Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$DomainName] = 0
}
$Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$DomainName]++
# Lets do unique OU counting
$Script:Reporting['GPOBrokenLink']['Variables']['Unique'][$Link.CanonicalName] = $Link
}
$Script:Reporting['GPOBrokenLink']['Variables']['UniqueObjects'] = $Script:Reporting['GPOBrokenLink']['Variables']['Unique'].Keys
if ($Script:Reporting['GPOBrokenLink']['Data'].Count -gt 0) {
$Script:Reporting['GPOBrokenLink']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOBrokenLink']['ActionRequired'] = $false
}
}
Variables = @{
RequireDeletion = 0
WillFixPerDomain = $null
UniqueObjects = $null
Unique = $null
}
Overview = {
}
Summary = {
New-HTMLText -FontSize 10pt -TextBlock {
"When GPO is deleted correctly, it usually is removed from AD, SYSVOL, and any link to it is also discarded. "
"Unfortunately, this is true only if the GPO is created and linked within the same domain. "
"If GPO is linked in another domain, this leaves a broken link hanging on before it was linked. "
"Additionally, the Remove-GPO cmdlet doesn't handle site link deletions, which causes dead links to be stuck on sites until those are manually deleted. "
"This means that any GPOs deleted using PowerShell may leave a trail."
}
New-HTMLText -Text @(
'As it stands currently there are ',
$Script:Reporting['GPOBrokenLink']['Data'].Count,
' broken links that need to be deleted over '
$Script:Reporting['GPOBrokenLink']['Variables']['UniqueObjects'].Count,
' unique objects. '
) -FontSize 10pt -FontWeight normal, bold, normal, bold, normal -LineBreak
if ($Script:Reporting['GPOBrokenLink']['Data'].Count -ne 0) {
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
}
}
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOBrokenLink']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartLegend -Names 'Bad' -Color Salmon
New-ChartBar -Name 'Broken Links' -Value $Script:Reporting['GPOBrokenLink']['Data'].Count
} -Title 'Broken Links' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policy Broken Links' {
New-HTMLTable -DataTable $Script:Reporting['GPOBrokenLink']['Data'] -Filtering {
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to remove Broken Links' {
New-HTMLContainer {
New-HTMLSpanStyle -FontSize 10pt {
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 fixing GPO links. To generate new report please use:"
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenLinkBefore.html -Verbose -Type GPOBrokenLink
}
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 {
$GPOOutput = Get-GPOZaurrBrokenLink -Verbose
$GPOOutput | Format-Table * # do your actions as desired
}
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
}
New-HTMLWizardStep -Name 'Remove Broken Links' {
New-HTMLText -Text "Following command when executed, runs internally command that lists all broken links. After finding them all it delets them according to given criteria. "
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-GPOZaurrBrokenLink -WhatIf -Verbose
}
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-GPOZaurrBrokenLink -Verbose -LimitProcessing 2
}
New-HTMLText -TextBlock {
"This command when executed removes only first X number of links. Keep in mind that 5 broken links on a single Organizational Unit are treated as one. 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. "
}
}
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\GPOZaurrBrokenLinkAfter.html -Verbose -Type GPOBrokenLink
}
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['GPOBrokenLink']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOBrokenLink']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
+15 -10
View File
@@ -52,11 +52,12 @@
}
Summary = {
New-HTMLText -FontSize 10pt -TextBlock {
"When GPO is created it creates an entry in Active Directory (metadata) and SYSVOL (content). "
"Two different places meens two different sets of permissions. Group Policy module is making sure the data in both places is correct. "
"However, for different reasons it's not nessecary the case and often permissions go out of sync between AD and SYSVOL. "
"This test verifies consistency of policies between AD and SYSVOL in two ways. "
"It checks top level permissions for a GPO, and then checks if all files within said GPO are inheriting permissions or have different permissions in place. "
"When GPO is created, it creates an entry in Active Directory (metadata) and SYSVOL (content). "
"Two different places mean two different sets of permissions. "
"The group Policy module is making sure the data in both places is correct. "
"However, it's not necessarily the case for different reasons, and often permissions go out of sync between AD and SYSVOL. "
"This test verifies the consistency of policies between AD and SYSVOL in two ways. "
"It checks top-level permissions for a GPO and then checks if all files within said GPO is inheriting permissions or have different permissions in place."
}
New-HTMLText -Text 'Following list presents ', 'permissions consistency between Active Directory and SYSVOL for Group Policies' -FontSize 10pt -FontWeight normal, bold
New-HTMLList -Type Unordered {
@@ -111,10 +112,10 @@
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrPermissionsInconsistentBefore.html -Verbose -Type GPOConsistency
}
New-HTMLText -Text {
New-HTMLText -Text @(
"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 {
$GPOOutput = Get-GPOZaurrPermissionConsistency
@@ -143,8 +144,12 @@
New-HTMLText -Text "If there's nothing else to be fixed, we can skip to next step step"
}
New-HTMLWizardStep -Name 'Fix inconsistent downlevel permissions' {
New-HTMLText -Text "Unfortunetly this step is manual until automation is developed. "
New-HTMLText -Text "If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
New-HTMLText -Text @(
"Unfortunetly this step is manual until automation is developed. "
"If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
"Please keep in mind that it's possible inconsistent downlevel permissions fix will not be required once the top level fix is applied. "
"Rerun report to find out if you've just fixed top-level permissions. "
)
}
New-HTMLWizardStep -Name 'Verification report' {
New-HTMLText -TextBlock {
@@ -155,7 +160,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
+2 -2
View File
@@ -68,7 +68,7 @@
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrDuplicateObjectsBefore.html -Verbose -Type GPODuplicates
}
New-HTMLText -Text {
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. "
}
@@ -106,7 +106,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
+29
View File
@@ -0,0 +1,29 @@
$GPOZaurrLinks = [ordered] @{
Name = 'Group Policy Links'
Enabled = $true
ActionRequired = $null
Data = $null
Execute = {
Get-GPOZaurrLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Summary
}
Processing = {
}
Variables = @{
}
Overview = {
}
Solution = {
New-HTMLTable -DataTable $Script:Reporting['GPOLinks']['Data'] -Filtering
if ($Script:Reporting['GPOLinks']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
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
}
}
}
}
}
+234 -55
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
}
@@ -19,6 +18,8 @@
$Script:Reporting['GPOList']['Variables']['GPOOptimizedPerDomain'] = @{}
$Script:Reporting['GPOList']['Variables']['GPOProblemPerDomain'] = @{}
$Script:Reporting['GPOList']['Variables']['GPONoProblemPerDomain'] = @{}
$Script:Reporting['GPOList']['Variables']['GPOApplyPermissionYesPerDomain'] = @{}
$Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'] = @{}
foreach ($GPO in $Script:Reporting['GPOList']['Data']) {
# Create Per Domain Variables
if (-not $Script:Reporting['GPOList']['Variables']['GPONotValidPerDomain'][$GPO.DomainName]) {
@@ -39,7 +40,30 @@
if (-not $Script:Reporting['GPOList']['Variables']['GPONoProblemPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOList']['Variables']['GPONoProblemPerDomain'][$GPO.DomainName] = 0
}
if ($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false) {
if (-not $Script:Reporting['GPOList']['Variables']['GPOApplyPermissionYesPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOList']['Variables']['GPOApplyPermissionYesPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'][$GPO.DomainName] = 0
}
if ($GPO.Days -le $Script:Reporting['GPOList']['Variables']['GPOOlderThan']) {
# Skip GPOS that are younger than 30 days
$Script:Reporting['GPOList']['Variables']['GPOSkip']++
}
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']++
$Script:Reporting['GPOList']['Variables']['GPONotValidPerDomain'][$GPO.DomainName]++
} else {
@@ -78,6 +102,11 @@
} else {
$Script:Reporting['GPOList']['Variables']['GPODisabled']++
}
if ($GPO.ApplyPermission -eq $true) {
$Script:Reporting['GPOList']['Variables']['ApplyPermissionYes']++
} else {
$Script:Reporting['GPOList']['Variables']['ApplyPermissionNo']++
}
if ($GPO.LinksDisabledCount -eq $GPO.LinksCount -and $GPO.LinksCount -gt 0) {
$Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled']++
}
@@ -120,45 +149,55 @@
}
}
$Script:Reporting['GPOList']['Variables']['GPOTotal'] = $Script:Reporting['GPOList']['Data'].Count
if ($Script:Reporting['GPOList']['Variables']['GPONotValid'] -gt 0) {
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 = @{
GPONotValidPerDomain = $null
GPOValidPerDomain = $null
GPONotOptimizedPerDomain = $null
GPOOptimizedPerDomain = $null
GPOProblemPerDomain = $null
GPONoProblemPerDomain = $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
GPOValid = 0
GPONotValid = 0
GPOLinkedButLinkDisabled = 0
GPOTotal = 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 = {
@@ -167,21 +206,31 @@
New-HTMLText -TextBlock {
"Over time Administrators add more and more group policies, as business requirements change. "
"Due to neglection or thinking it may serve it's purpose later on a lot of Group Policies often have no value at all. "
"Either the Group Policy is not linked to anything and just stays unlinked forever, or GPO is linked, but the link (links) are disabled. "
"Either the Group Policy is not linked to anything and just stays unlinked forever, or GPO is linked, but the link (links) are disabled or GPO is totally disabled. "
"Then there are Group Policies that are targetting certain group or person and that group is removed leaving Group Policy doing nothing. "
"Additionally sometimes new GPO is created without any settings or the settings are removed over time, but GPO stays in place. "
} -FontSize 10pt
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 to delete: ", $Script:Reporting['GPOList']['Variables']['GPONotValid'] -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
New-HTMLListItem -Text "Group Policies that are empty (have no settings): ", $Script:Reporting['GPOList']['Variables']['GPOEmpty'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies that are linked, but empty: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButEmpty'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies that are linked, but link disabled: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies that are disabled (both user/computer sections): ", $Script:Reporting['GPOList']['Variables']['GPODisabled'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies that have no Apply Permission: ", $Script:Reporting['GPOList']['Variables']['ApplyPermissionNo'] -FontWeight normal, bold
}
}
} -Color Black, Red, Black, Red, Black
New-HTMLListItem -Text @(
"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
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
@@ -257,6 +306,29 @@
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOList']['Variables']['GPONotOptimizedPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
# Just in case report is too big and the full file is not attached
New-HTMLText -FontSize 10pt -Text "To generate up to date report please execute: " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Install-Module GPOZaurr -Force', ' or ', ' install module manually.' -Color RoyalBlue, None, None
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 {
@@ -270,6 +342,7 @@
New-ChartBar -Name 'Linked' -Value $Script:Reporting['GPOList']['Variables']['GPOLinked'], $Script:Reporting['GPOList']['Variables']['GPONotLinked']
New-ChartBar -Name 'Not Empty' -Value $Script:Reporting['GPOList']['Variables']['GPONotEmpty'], $Script:Reporting['GPOList']['Variables']['GPOEmpty']
New-ChartBar -Name 'Enabled' -Value $Script:Reporting['GPOList']['Variables']['GPOEnabled'], $Script:Reporting['GPOList']['Variables']['GPODisabled']
New-ChartBar -Name 'Apply Permission' -Value $Script:Reporting['GPOList']['Variables']['ApplyPermissionYes'], $Script:Reporting['GPOList']['Variables']['ApplyPermissionNo']
New-ChartBar -Name 'Valid' -Value $Script:Reporting['GPOList']['Variables']['GPOValid'], $Script:Reporting['GPOList']['Variables']['GPONotValid']
New-ChartBar -Name 'Optimized (for speed)' -Value $Script:Reporting['GPOList']['Variables']['GPOOptimized'], $Script:Reporting['GPOList']['Variables']['GPONotOptimized']
New-ChartBar -Name 'No problem' -Value $Script:Reporting['GPOList']['Variables']['GPONoProblem'], $Script:Reporting['GPOList']['Variables']['GPOProblem']
@@ -289,6 +362,7 @@
New-HTMLListItem -FontWeight bold, normal -Text "Enabled", " - means GPO has at least one section enabled. If enabled is set to false that means both sections are disabled, and therefore GPO is not active. "
New-HTMLListItem -FontWeight bold, normal -Text "Optimized", " - means GPO section that is not in use is disabled. If section (user or computer) is enabled and there is no content, it's not optimized. "
New-HTMLListItem -FontWeight bold, normal -Text "Problem", " - means GPO has one or more section (user or computer) that is disabled, yet there is content in it. "
New-HTMLListItem -FontWeight bold, normal -Text "ApplyPermission", " - means GPO has no Apply Permission. This means there's no user/computer/group it's applicable to. "
} -FontSize 10pt
New-HTMLTable -DataTable $Script:Reporting['GPOList']['Data'] -Filtering {
New-HTMLTableCondition -Name 'Exclude' -Value $true -BackgroundColor DeepSkyBlue -ComparisonType string -Row
@@ -298,6 +372,7 @@
New-HTMLTableCondition -Name 'Enabled' -Value $false -BackgroundColor Salmon -ComparisonType string
New-HTMLTableCondition -Name 'Optimized' -Value $false -BackgroundColor Salmon -ComparisonType string
New-HTMLTableCondition -Name 'Problem' -Value $true -BackgroundColor Salmon -ComparisonType string
New-HTMLTableCondition -Name 'ApplyPermission' -Value $false -BackgroundColor Salmon -ComparisonType string
New-HTMLTableCondition -Name 'ComputerProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
New-HTMLTableCondition -Name 'UserProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $false -BackgroundColor Salmon -ComparisonType string
@@ -308,6 +383,7 @@
New-HTMLTableCondition -Name 'Enabled' -Value $true -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'Optimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'Problem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'ApplyPermission' -Value $true -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'ComputerProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'UserProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
@@ -329,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 {
@@ -369,11 +457,14 @@
"You would do so using following approach "
) -FontSize 10pt -FontWeight bold, normal
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -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'
'{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. "
@@ -382,11 +473,55 @@
"Now go ahead and find what's there"
)
}
New-HTMLWizardStep -Name 'Remove GPOs that are EMPTY or UNLINKED' {
New-HTMLWizardStep -Name 'Remove GPOs (Manual)' {
New-HTMLText -Text @(
"Please condider deleting GPOs manually if the amount of GPOs to delete is small enough. "
"Deleting 1-5-30 GPOs manually on domain of 4000 GPOs will be much faster than doing it in controlled manner with automated steps mentioned on next steps. "
"What can take 30 minutes manually, can take 8 hours using automated script, because of amount of checks required by the script over and over to delete a single GPO. "
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
}
New-HTMLWizardStep -Name 'Remove GPOs that are EMPTY' {
New-HTMLText -Text @(
"Following command when executed removes every ",
"EMPTY"
" or "
" Group Policy. Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental removal.",
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
}
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-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -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 deleted matches expected data. "
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -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-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed deletes only first X empty 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."
"Please make sure to check if backup is made as well before going all in."
}
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step"
}
New-HTMLWizardStep -Name 'Remove GPOs that are UNLINKED' {
New-HTMLText -Text @(
"Following command when executed removes every ",
"NOT LINKED"
" Group Policy. Make sure when running it for the first time to run it with ",
"WhatIf",
@@ -395,33 +530,33 @@
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
}
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-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -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 deleted matches expected data. "
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -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-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed deletes only first X empty or unlinked GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
"This command when executed deletes only first X unlinked 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."
"Please make sure to check if backup is made as well before going all in."
}
New-HTMLText -Text "If there's nothing else to be deleted on SYSVOL side, we can skip to next step step"
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step"
}
New-HTMLWizardStep -Name 'Remove GPOs that are DISABLED' {
New-HTMLText -Text @(
@@ -437,26 +572,26 @@
""
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
}
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-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -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 deleted matches expected data. "
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -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-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed deletes only first X disabled GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
@@ -465,6 +600,48 @@
}
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step."
}
New-HTMLWizardStep -Name 'Remove GPOs that do not APPLY' {
New-HTMLText -Text @(
"Following command when executed removes every ",
"NoApplyPermission"
" Group Policy. Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental removal.",
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
New-HTMLText -TextBlock {
""
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
}
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-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -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 deleted matches expected data. "
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -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-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed deletes only first X NoApplyPermission 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. "
"Please make sure to check if backup is made as well before going all in."
}
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step."
}
New-HTMLWizardStep -Name 'Optimize GPOs (optional)' {
New-HTMLText -Text @(
"Following command when executed disables user or computer section when there's no content for given type. ",
@@ -510,10 +687,11 @@
}
New-HTMLText -Text "If there are no more problems to solve, GPOs to optimize in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
}
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
<#
if ($Script:Reporting['GPOList']['Exclusions']) {
New-HTMLSection -Invisible {
New-HTMLSection -Name 'Group Policies Exclusions' {
@@ -524,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' {
+3 -3
View File
@@ -123,8 +123,8 @@
}
New-HTMLPanel {
New-HTMLChart {
New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix'] -Color Crimson
New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrators'] -Color SpringGreen
New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix'] -Color Salmon
} -Title 'NetLogon Owners' -TitleAlignment center
}
}
@@ -206,7 +206,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
+2 -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
# }
# }
# }
# 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']
@@ -272,6 +181,7 @@
New-HTMLText -Text @(
"In case of NETLOGON permissions it's impossible to tell what in a given moment for given domain should be automatically removed except for the very obvious ",
"unknown ", 'permissions. Domain Admins have to make their assesment on and remove permissions from users or groups that '
"they think do not belong. "
) -FontWeight normal, bold, normal
}
New-HTMLWizardStep -Name 'Verification report' {
@@ -283,7 +193,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
@@ -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
}
}
}
}
+95 -44
View File
@@ -1,5 +1,5 @@
$GPOZaurrOrphans = [ordered] @{
Name = 'Orphaned Group Policies'
Name = 'Broken Group Policies'
Enabled = $true
ActionRequired = $null
Data = $null
@@ -7,41 +7,52 @@
Get-GPOZaurrBroken -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
Processing = {
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'] = @{}
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'] = @{}
foreach ($GPO in $Script:Reporting['GPOOrphans']['Data']) {
if (-not $Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName] = 0
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'] = @{}
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'] = @{}
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'] = @{}
foreach ($GPO in $Script:Reporting['GPOBroken']['Data']) {
if (-not $Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName] = 0
if (-not $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'][$GPO.DomainName] = 0
}
if ($GPO.Status -eq 'Not available in AD') {
$Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD']++
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted']++
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
$Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD']++
$Script:Reporting['GPOBroken']['Variables']['ToBeDeleted']++
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
} elseif ($GPO.Status -eq 'Not available on SYSVOL') {
$Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol']++
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted']++
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
$Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol']++
$Script:Reporting['GPOBroken']['Variables']['ToBeDeleted']++
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
} elseif ($GPO.Status -eq 'Permissions issue') {
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']++
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]++
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue']++
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]++
} elseif ($GPO.Status -eq 'ObjectClass issue') {
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssue']++
$Script:Reporting['GPOBroken']['Variables']['ToBeDeleted']++
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'][$GPO.DomainName]++
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
}
}
if ($Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted'] -gt 0) {
$Script:Reporting['GPOOrphans']['ActionRequired'] = $true
if ($Script:Reporting['GPOBroken']['Variables']['ToBeDeleted'] -gt 0) {
$Script:Reporting['GPOBroken']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOOrphans']['ActionRequired'] = $false
$Script:Reporting['GPOBroken']['ActionRequired'] = $false
}
}
Variables = @{
NotAvailableInAD = 0
NotAvailableOnSysvol = 0
NotAvailablePermissionIssue = 0
NotAvailablePermissionIssuePerDomain = $null
ToBeDeleted = 0
ToBeDeletedPerDomain = $null
NotAvailableInAD = 0
NotAvailableOnSysvol = 0
NotAvailablePermissionIssue = 0
NotAvailablePermissionIssuePerDomain = $null
ToBeDeleted = 0
ToBeDeletedPerDomain = $null
NotAvailableObjectClassIssue = 0
NotAvailableObjectClassIssuePerDomain = $null
}
Overview = {
<#
@@ -58,15 +69,15 @@
}
New-HTMLText -Text 'Following chart presents ', 'Broken / Orphaned Group Policies' -FontSize 10pt -FontWeight normal, bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
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 couldn't be assed due to permissions issue: ", $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -FontSize 10pt -Text 'Those problems must be resolved before doing other clenaup activities.'
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'Permissions Issue' -Color Crimson, LightCoral, IndianRed
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue']
} -Title 'Broken / Orphaned Group Policies' -TitleAlignment center
}
#>
@@ -85,14 +96,15 @@
} -FontSize 10pt
New-HTMLText -Text 'Following problems were detected:' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
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 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 {
foreach ($Domain in $Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
foreach ($Domain in $Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
New-HTMLText -Text "Please review output in table and follow the steps below table to get Active Directory Group Policies in healthy state." -FontSize 10pt
@@ -100,25 +112,26 @@
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOOrphans']['Summary']
& $Script:GPOConfiguration['GPOBroken']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'Permissions Issue' -Color Crimson, LightCoral, IndianRed
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'ObjectClass Issue', 'Permissions Issue' -Color Crimson, LightCoral, MediumOrchid, IndianRed
New-ChartBar -Name 'Broken' -Value $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssue'], $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue']
} -Title 'Broken / Orphaned Group Policies' -TitleAlignment center
}
}
New-HTMLSection -Name 'Health State of Group Policies' {
New-HTMLTable -DataTable $Script:Reporting['GPOOrphans']['Data'] -Filtering {
New-HTMLTable -DataTable $Script:Reporting['GPOBroken']['Data'] -Filtering {
New-HTMLTableCondition -Name 'Status' -Value "Not available in AD" -BackgroundColor Salmon -ComparisonType string
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
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory' {
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory / ObjectClass issue' {
New-HTMLContainer {
New-HTMLSpanStyle -FontSize 10pt {
New-HTMLWizard {
@@ -133,7 +146,7 @@
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\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOOrphans
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOBroken
}
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."
@@ -243,23 +256,61 @@
"If there's nothing else to be deleted on AD side, we can skip to next step step. "
}
}
New-HTMLWizardStep -Name 'Fix GPOs of wrong ObjectClass' {
New-HTMLText -Text @(
"Following command when executed runs cleanup procedure that removes all GPOs which have ObjectClass of Container, rather than required groupPolicyContainer. "
"Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental removal."
'When run it will remove GPO metadata from AD, and any files/folders from SYSVOL.'
) -FontWeight normal, normal, bold, normal -Color Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurrBroken -Type ObjectClass -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-GPOZaurrBroken -Type ObjectClass -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor' -Verbose
}
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 deleted matches expected data. "
"Keep in mind that there is no backup for this as backup process doesn't see GPOs that are of wrong ObjectClass. "
"Once you delete it, it's gone. "
} -LineBreak
New-HTMLText -Text 'Once happy with results please follow with command (this will start deletion process): ' -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurrBroken -Type ObjectClass -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-GPOZaurrBroken -Type ObjectClass -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor' -Verbose
}
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. "
"If there's nothing else to be deleted, we can skip to next step step. "
}
}
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\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOOrphans
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOBroken
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
}
if ($Script:Reporting['GPOOrphans']['WarningsAndErrors']) {
if ($Script:Reporting['GPOBroken']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOOrphans']['WarningsAndErrors'] -Filtering {
New-HTMLTable -DataTable $Script:Reporting['GPOBroken']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
+102 -22
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
@@ -77,21 +101,23 @@
#>
}
Summary = {
New-HTMLText -FontSize 10pt -TextBlock {
"By default GPO creation is usually maintained by Domain Admins or Enterprise Admins. "
"When GPO is created by member of Domain Admins or Enterprise Admins group the GPO Owner is set to Domain Admins. "
"When GPO is created by member of Group Policy Creator Owners or other group has delegated rights to create a GPO the owner of said GPO is not Domain Admins group but is assigned to relevant user. "
"GPO Owners should be Domain Admins or Enterprise Admins to prevent abuse. If that isn't so it means owner is able to fully control GPO and potentially change it's settings in uncontrolled way. "
"While at the moment of creation of new GPO it's not a problem, in long term it's possible such person may no longer be admin, yet keep their rights over GPO. "
}
New-HTMLText -FontSize 10pt -TextBlock {
"As you're aware Group Policies are stored in 2 places. In Active Directory (metadata) and SYSVOL (settings). This means that there are 2 places where GPO Owners exists. "
"This also means that for multiple reasons AD and SYSVOL can be out of sync when it comes to their permissions which can lead to uncontrolled ability to modify them. "
"Ownership in Active Directory and Ownership of SYSVOL for said GPO are required to be the same. "
}
New-HTMLText -FontSize 10pt -Text @(
"By default, GPO creation is usually maintained by Domain Admins or Enterprise Admins. "
"When GPO is created by Domain Admins or Enterprise Admins group members, the GPO Owner is set to Domain Admins. "
"When GPO is created by a member of Group Policy Creator Owners or other group has delegated rights to create a GPO, "
"the owner of said GPO is not Domain Admins group but is assigned to the relevant user. "
"GPO Owners should be Domain Admins or Enterprise Admins to prevent abuse. "
"If that isn't so, it means the owner can fully control GPO and potentially change its settings in an uncontrolled way. "
"While at the moment of creation of new GPO, it's not a problem, in the long term, it's possible such a person may no longer be admin, yet keep their rights over GPO. "
"As your aware, Group Policies are stored in 2 places. In Active Directory (metadata) and SYSVOL (settings). "
"This means that there are 2 places where GPO Owners exists. "
"This also means that for multiple reasons, AD and SYSVOL can be out of sync when it comes to their permissions, which can lead to uncontrolled ability to modify them. "
"Ownership in Active Directory and Ownership of SYSVOL for said GPO is required to be the same."
)
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
@@ -114,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 {
@@ -123,16 +165,25 @@
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
#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) {
@@ -149,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 {
@@ -206,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' {
@@ -217,7 +297,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
-29
View File
@@ -1,29 +0,0 @@
$GPOZaurrPermissions = [ordered] @{
Name = 'Group Policy Permissions'
Enabled = $true
Action = $null
Data = $null
Execute = {
Get-GPOZaurrPermission -Type All -IncludePermissionType GpoEditDeleteModifySecurity, GpoEdit, GpoCustom -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
Processing = {
}
Variables = @{
}
Overview = {
}
Solution = {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'] -Filtering
if ($Script:Reporting['GPOPermissions']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
@@ -8,6 +8,7 @@
Permissions = Get-GPOZaurrPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity -ReturnSecurityWhenNoData -IncludeGPOObject -ReturnSingleObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
$Object['PermissionsPerRow'] = $Object['Permissions'] | ForEach-Object { $_ }
$Object['PermissionsAnalysis'] = [System.Collections.Generic.List[PSCustomObject]]::new()
$Object
}
Processing = {
@@ -33,6 +34,8 @@
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix']++
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'][$GPO[0].DomainName]++
}
# lets create table and add it there
$Script:Reporting['GPOPermissionsAdministrative']['Data'].'PermissionsAnalysis'.Add($Analysis)
}
if ($Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix'] -gt 0) {
$Script:Reporting['GPOPermissionsAdministrative']['ActionRequired'] = $true
@@ -82,17 +85,22 @@
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, Salmon
New-ChartLegend -Name 'Yes', 'No' -Color SpringGreen, Salmon
New-ChartBar -Name 'Administrative Users Present' -Value $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouch'], $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix']
#New-ChartBar -Name 'Accessible Group Policies' -Value $Script:Reporting['GPOPermissionsAdministrative']['Variables']['Read'], $Script:Reporting['GPOPermissionsAdministrative']['Variables']['CouldNotRead']
} -Title 'Group Policy Permissions' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policy Administrative Users Analysis' {
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
}
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
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
New-HTMLContainer {
@@ -184,7 +192,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
@@ -0,0 +1,583 @@
$GPOZaurrPermissionsAnalysis = [ordered] @{
Name = 'Group Policy Permissions Analysis'
Enabled = $true
Action = $null
Data = $null
Execute = {
$Object = [ordered] @{
Permissions = Get-GPOZaurrPermission -ReturnSecurityWhenNoData -IncludeGPOObject -ReturnSingleObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
$Object['PermissionsPerRow'] = $Object['Permissions'] | ForEach-Object { $_ }
$Object['PermissionsAnalysis'] = Get-GPOZaurrPermissionAnalysis -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Permissions $Object.Permissions
$Object['PermissionsIssues'] = Get-GPOZaurrPermissionIssue -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
$Object
}
Processing = {
# Create Per Domain Variables
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsersPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'] = @{}
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'] = @{}
foreach ($GPO in $Script:Reporting['GPOPermissions']['Data'].PermissionsIssues) {
# Create Per Domain Variables
if (-not $Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$GPO.DomainName] = 0
}
if ($GPO.PermissionIssue) {
$Script:Reporting['GPOPermissions']['Variables']['CouldNotRead']++
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOPermissions']['Variables']['Read']++
$Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'][$GPO.DomainName]++
}
$Script:Reporting['GPOPermissions']['Variables']['Total']++
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$GPO.DomainName]++
}
foreach ($GPO in $Script:Reporting['GPOPermissions']['Data'].PermissionsAnalysis) {
# Create Per Domain Variables
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'][$GPO.DomainName] = 0
}
# Checks
if ($GPO.Administrative -eq $true) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative']++
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrative']++
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$GPO.DomainName]++
}
if ($GPO.AuthenticatedUsers -eq $true) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsers']++
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsersPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsers']++
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$GPO.DomainName]++
}
if ($GPO.System -eq $true) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystem']++
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystem']++
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$GPO.DomainName]++
}
if ($GPO.Unknown -eq $false) {
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknown']++
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknown']++
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$GPO.DomainName]++
}
if ($GPO.Status -eq $false) {
$Script:Reporting['GPOPermissions']['Variables']['WillFix']++
$Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOPermissions']['Variables']['WillNotFix']++
$Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'][$GPO.DomainName]++
}
}
if ($Script:Reporting['GPOPermissions']['Variables']['WillFix'] -gt 0 -or $Script:Reporting['GPOPermissions']['Variables']['CouldNotRead'] -gt 0) {
$Script:Reporting['GPOPermissions']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOPermissions']['ActionRequired'] = $false
}
}
Variables = @{
# Issues / Couldnt read report
Read = 0
ReadPerDomain = $null
CouldNotRead = 0
CouldNotReadPerDomain = $null
TotalPerDomain = $null
Total = 0
# Permissions analysis
WillFix = 0
WillNotFix = 0
WillFixAdministrative = 0
WillNotTouchAdministrative = 0
WillFixUnknown = 0
WillNotTouchUnknown = 0
WillNotTouchSystem = 0
WillFixSystem = 0
WillNotTouchAuthenticatedUsers = 0
WillFixAuthenticatedUsers = 0
WillNotTouchAuthenticatedUsersPerDomain = $null
WillFixAuthenticatedUsersPerDomain = $null
WillNotTouchSystemPerDomain = $null
WillFixSystemPerDomain = $null
WillFixAdministrativePerDomain = $null
WillNotTouchAdministrativePerDomain = $null
WillNotFixPerDomain = $null
WillFixPerDomain = $null
WillFixUnknownPerDomain = $null
WillNotTouchUnknownPerDomain = $null
}
Summary = {
New-HTMLText -FontSize 10pt -Text "When GPO is created it gets a handful of standard permissions. Those are:"
New-HTMLList {
New-HTMLListItem -Text "NT AUTHORITY\Authenticated Users with GpoApply permissions"
New-HTMLListItem -Text "Domain Admins and Enterprise Admins with Edit/Delete/Modify permissions"
New-HTMLListItem -Text "SYSTEM account with Edit/Delete/Modify permissions"
} -FontSize 10pt
New-HTMLText -FontSize 10pt -Text "But then IT people change those permissions to their own needs. While most changes make sense and are required to be able to target proper groups of people, some changes are not required or even bad. "
New-HTMLText -Text "First problem relates to NT AUTHORITY\Authenticated Users" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
New-HTMLText -FontSize 10pt -TextBlock {
"When GPO is created one of the permissions that are required for proper functioning of Group Policies is NT AUTHORITY\Authenticated Users. "
"Some Administrators don't follow best practices and trying to remove GpoApply permission, remove also GpoRead permission from a GPO which can have consequences. "
"On June 14th, 2016 Microsoft released [HotFix](https://support.microsoft.com/en-gb/help/3159398/ms16-072-description-of-the-security-update-for-group-policy-june-14-2) that requires Authenticated Users to be present on all Group Policies to function properly. "
"MS16-072 changes the security context with which user group policies are retrieved. "
"This by-design behavior change protects customers computers from a security vulnerability. "
}
New-HTMLList {
New-HTMLListItem -Text "Before MS16-072 is installed, user group policies were retrieved by using the users security context. "
New-HTMLListItem -Text "After MS16-072 is installed, user group policies are retrieved by using the computer's security context."
} -FontSize 10pt
New-HTMLText -FontSize 10pt -Text @(
"Unfortunetly it's not as simple as it sounds. While checking for permissions mostly works fine, it's possible a Group Policy has totally removed account permissions from being able to asses any of it. ",
"The account we're using "
"$($Env:USERDOMAIN)\$($Env:USERNAME.ToUpper())",
" may simply not have enough permisions to properly asses permissions for a GPO. "
"Therefore we're using dual assesment for this situation, where first assesment is checking for GPO visibility or lack of it, and second assesment is checking for direct permissions assignement. "
"We just were able to detect the problem, but hopefully higher level account (Domain Admin) should be able to provide full assesment. "
) -FontWeight normal, normal, bold, normal -Color None, None, BlueDiamond, none, none
New-HTMLText -FontSize 10pt -Text "First assesment results: " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text "Group Policies couldn't read at all: ", $Script:Reporting['GPOPermissions']['Variables']['CouldNotRead'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies with permissions allowing read: ", $Script:Reporting['GPOPermissions']['Variables']['Read'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'].Keys) {
New-HTMLListItem -Text @(
"$Domain requires ",
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$Domain],
" changes out of ",
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$Domain],
"."
) -FontWeight normal, bold, normal
}
} -FontSize 10pt
New-HTMLText -FontSize 10pt -Text "Second Assesment results " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies requiring Authenticated Users with GpoRead permission: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsers'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsers'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
New-HTMLText -Text "Second problem relates to Domain Admins and Enterprise Admins" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
New-HTMLText -FontSize 10pt -TextBlock {
"When GPO is created by default it gets Domain Admins and Enterprise Admins with Edit/Delete/Modify Security permissions. "
"For some reason, some Administrators remove those permissions or modify them when they shouldn't touch those at all. "
"Since having Edit/Delete/Modify Security permissions doesn't affect GPOApply permissions there's no reason to remove Domain Admins or Enterprise Admins from permissions, or limit their rights. "
"Domain Admins and Enterprise Admins have to have either GPOEditModify permissions or at the very least GPOCustom. "
"When GPOCustom is set it usually means there's a mix of Allow and Deny permission in place (for example deny GPOApply). "
"In such case we're assuming you know what you're doing. However it's always possible to review those permissions, as those are marked in the table for review. "
} -LineBreak
New-HTMLText -FontSize 10pt -Text "Assesment results " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies requiring Administrative permission fix: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrative'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
New-HTMLText -Text "Third problem relates to SYSTEM account" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
New-HTMLText -FontSize 10pt -TextBlock {
"When GPO is created by default it gets SYSTEM account with Edit/Delete/Modify Security permissions. "
"For some reason, some Administrators remove those permissions or modify them when they shouldn't touch those at all. "
"Since having Edit/Delete/Modify Security permissions doesn't affect GPOApply permissions there's no reason to remove SYSTEM from permissions, or limit their rights. "
} -LineBreak
New-HTMLText -FontSize 10pt -Text "Assesment results " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies requiring SYSTEM permission fix: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixSystem'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystem'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
New-HTMLText -Text "Fourth problem relates to UNKNOWN SID" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
New-HTMLText -FontSize 10pt -TextBlock {
"Sometimes groups or users are deleted in Active Directory and unfortunetly their permissions are not cleaned automatically. "
"Those are left in-place and stay there forever until removed. "
} -LineBreak
New-HTMLText -FontSize 10pt -Text "Assesment results " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies requiring Unknown permission removal: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknown'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknown'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt -LineBreak
# Just in case report is too big and the full file is not attached
New-HTMLText -FontSize 10pt -Text "To generate up to date report please execute: " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Install-Module GPOZaurr -Force', ' or ', ' install module manually.' -Color RoyalBlue, None, None
New-HTMLListItem -Text 'Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPermissionsBefore.html -Verbose -Type GPOPermissions' -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.'
}
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOPermissions']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Yes', 'No' -Color SpringGreen, Salmon
New-ChartBar -Name 'Visible Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['Read'], $Script:Reporting['GPOPermissions']['Variables']['CouldNotRead']
New-ChartBar -Name 'Overall Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotFix'], $Script:Reporting['GPOPermissions']['Variables']['WillFix']
New-ChartBar -Name 'Administrative Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative'], $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrative']
New-ChartBar -Name 'Authenticated Users Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative'], $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsers']
New-ChartBar -Name 'System Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystem'], $Script:Reporting['GPOPermissions']['Variables']['WillFixSystem']
New-ChartBar -Name 'Unknown Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknown'], $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknown']
} -Title 'Group Policy Permissions' -TitleAlignment center
}
}
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
}
New-HTMLSection -Name 'Group Policy Permissions Analysis' {
New-HTMLContainer {
New-HTMLText -Text 'Explanation to table columns:' -FontSize 10pt
New-HTMLList {
New-HTMLListItem -FontWeight bold, normal -Text "Status", " - means GPO has at least one problem with permissions. "
New-HTMLListItem -FontWeight bold, normal -Text "Administrative", " - means GPO has problem with either Domain Admins or Enterprise Admins not having proper permissions. "
New-HTMLListItem -FontWeight bold, normal -Text "AuthenticatedUsers", " - means GPO has Authenticated Users missing either as GPOApply or GPORead. "
New-HTMLListItem -FontWeight bold, normal -Text "System", " - means GPO has SYSTEM permission missing or lacking proper permissions. "
New-HTMLListItem -FontWeight bold, normal -Text "DomainAdmins", " - means GPO has Domain Admins missing or having wrong permissions. "
New-HTMLListItem -FontWeight bold, normal -Text "EnterpriseAdmins", " - means GPO has Enterprise Admins missing or having wrong permissions. "
} -FontSize 10pt
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'].PermissionsAnalysis -Filtering {
New-HTMLTableCondition -Name 'Status' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'Administrative' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'AuthenticatedUsers' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'System' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'Unknown' -Value 'False' -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'DomainAdmins' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
New-HTMLTableCondition -Name 'EnterpriseAdmins' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
# Mark as warning
New-HTMLTableCondition -Name 'DomainAdminsPermission' -Value 'GpoCustom' -BackgroundColor Moccasin -ComparisonType string
New-HTMLTableCondition -Name 'EnterpriseAdminsPermission' -Value 'GpoCustom' -BackgroundColor Moccasin -ComparisonType string
# Reverse
New-HTMLTableCondition -Name 'Status' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
New-HTMLTableCondition -Name 'Administrative' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
New-HTMLTableCondition -Name 'AuthenticatedUsers' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
New-HTMLTableCondition -Name 'System' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
New-HTMLTableCondition -Name 'Unknown' -Value 'False' -BackgroundColor Salmon -ComparisonType string -Operator ne
New-HTMLTableCondition -Name 'DomainAdmins' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
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
}
}
New-HTMLSection -Name 'All Permissions' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'].PermissionsPerRow -Filtering {
New-HTMLTableHeader -Names 'PrincipalNetBiosName', 'PrincipalDistinguishedName', 'PrincipalDomainName', 'PrincipalName', 'PrincipalSid', 'PrincipalSidType' -Title 'Account Information'
New-HTMLTableCondition -Name 'Permission' -Value 'GpoEditDeleteModifySecurity' -BackgroundColor HotPink -ComparisonType string -Operator eq
New-HTMLTableCondition -Name 'Permission' -Value 'GpoCustom' -BackgroundColor Moccasin -ComparisonType string
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'
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
New-HTMLContainer {
New-HTMLSpanStyle -FontSize 10pt {
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 fixing Group Policy Authenticated Users. To generate new report please use:"
New-HTMLCodeBlock -Code {
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPermissionsBefore.html -Verbose -Type GPOPermissions
}
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. "
"GPOs with problems will be those not having any value for Permission/PermissionType columns. "
"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 {
# This gets all permissions
$AllPermissions = Get-GPOZaurrPermission
$AllPermissions | Format-Table
# this analyses permissions
$PermissionsAnalysis = Get-GPOZaurrPermissionAnalysis
$PermissionsAnalysis | 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 'Make a backup (optional)' {
New-HTMLText -TextBlock {
"The process of fixing GPO Permissions does NOT touch GPO content. It simply adds permissionss on AD and SYSVOL at the same time for given GPO. "
"However, it's always good to have a backup before executing changes that may impact Active Directory. "
}
New-HTMLCodeBlock -Code {
$GPOSummary = Backup-GPOZaurr -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -Type All
$GPOSummary | Format-Table # only if you want to display output of backup
}
New-HTMLText -TextBlock {
"Above command when executed will make a backup to Desktop, create GPO folder and within it it will put all those GPOs. "
}
}
New-HTMLWizardStep -Name 'Add Authenticated Users permissions' {
New-HTMLText -Text @(
"Following command will find any GPO which doesn't have Authenticated User as GpoRead or GpoApply and will add it as GpoRead. ",
"This change doesn't change GpoApply permission, therefore it won't change to whom the GPO applies to. ",
"It ensures that COMPUTERS can read GPO properly to be able to Apply it. ",
"Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental adding of permissions."
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -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 {
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -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 changed matches expected data."
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -Verbose -LimitProcessing 2
}
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 {
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed adds Authenticated Users (GpoRead permission) only on first X non-compliant Group Policies. "
"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 'Add Administrative Groups permissions' {
New-HTMLText -Text @(
"Following command will find any GPO which doesn't have Domain Admins and Enterprise Admins added with GpoEditDeleteModifySecurity and will add it as GpoEditDeleteModifySecurity. ",
"This change doesn't change GpoApply permission, therefore it won't change to whom the GPO applies to. ",
"It ensures that Domain Admins and Enterprise Admins can manage GPO. ",
"Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental adding of permissions."
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -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 {
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -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 changed matches expected data."
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2
}
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 {
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed adds Enterprise Admins or/and Domain Admins (GpoEditDeleteModifySecurity permission) only on first X non-compliant Group Policies. "
"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 'Add SYSTEM permissions' {
New-HTMLText -Text @(
"Following command will find any GPO which doesn't have SYSTEM account added with GpoEditDeleteModifySecurity and will add it as GpoEditDeleteModifySecurity. ",
"This change doesn't change GpoApply permission, therefore it won't change to whom the GPO applies to. ",
"It ensures that SYSTEM can manage GPO. ",
"Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental adding of permissions."
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -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 {
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -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 changed matches expected data."
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2
}
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 {
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed adds SYSTEM account (GpoEditDeleteModifySecurity permission) only on first X non-compliant Group Policies. "
"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 'Remove UNKNOWN permissions' {
New-HTMLText -Text @(
"Following command will find any GPO which has an unknown SID and will remove it. ",
"This change doesn't change any other permissions. ",
"It ensures that GPOs have no unknown permissions present. ",
"Make sure when running it for the first time to run it with ",
"WhatIf",
" parameter as shown below to prevent accidental adding of permissions."
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurrPermission -Verbose -Type Unknown -WhatIf
}
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-GPOZaurrPermission -Verbose -Type Unknown -WhatIf -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 changed matches expected data."
} -LineBreak
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 2
}
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-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed removes only first X unknwon permissions from Group Policies. "
"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\GPOZaurrGPOPermissionsAfter.html -Verbose -Type GPOPermissions
}
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['GPOPermissions']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
+4 -4
View File
@@ -6,7 +6,7 @@
Execute = {
[ordered] @{
Permissions = Get-GPOZaurrPermission -Type AuthenticatedUsers -ReturnSecurityWhenNoData -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
Issues = Get-GPOZaurrPermissionIssue
Issues = Get-GPOZaurrPermissionIssue -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
}
Processing = {
@@ -93,7 +93,7 @@
} -FontStyle italic -FontSize 10pt -FontWeight bold -LineBreak
New-HTMLText -FontSize 10pt -Text @(
"There are two parts to this assesment. Reading all Group Policies Permissions that account ",
$($Env:USERNAME.ToUpper()),
"$($Env:USERDOMAIN)\$($Env:USERNAME.ToUpper())",
" has permissions to read and provide detailed assesment about permissions. ",
"Second assesment checks for permissions that this account is not able to read at all, and therefore it has no visibility about permissions set on it. "
"We just were able to detect the problem, but hopefully higher level account (Domain Admin) should be able to provide full assesment. "
@@ -142,7 +142,7 @@
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, Salmon
New-ChartLegend -Name 'Yes', 'No' -Color SpringGreen, Salmon
New-ChartBar -Name 'Authenticated Users Available' -Value $Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouch'], $Script:Reporting['GPOPermissionsRead']['Variables']['WillFix']
New-ChartBar -Name 'Accessible Group Policies' -Value $Script:Reporting['GPOPermissionsRead']['Variables']['Read'], $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotRead']
} -Title 'Group Policy Permissions' -TitleAlignment center
@@ -249,7 +249,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
@@ -164,7 +164,7 @@
}
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
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
+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
}
}
}
+31 -16
View File
@@ -1,7 +1,8 @@
function New-GPOZaurrReportConsole {
[cmdletBinding()]
param(
[System.Collections.IDictionary] $Results
[System.Collections.IDictionary] $Results,
[string] $ComputerName
)
Begin {
$GPODeny = @{
@@ -20,26 +21,40 @@
$UserWhereApplied = ($Results.UserResults.GroupPolicies | Sort-Object -Property Name).Where( { $_.Status -eq 'Applied' }, 'split')
}
Process {
Write-Color -Text 'Computer Settings' -Color White -LinesBefore 1
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.ComputerResults.Summary.ReadTime @WriteSummary
Write-Color -Text '[>] Computer Name: ', $Results.ComputerResults.Summary.ComputerName @WriteSummary
Write-Color -Text '[>] Domain Name: ', $Results.ComputerResults.Summary.DomainName @WriteSummary
Write-Color -Text '[>] Organizational Unit: ', $Results.ComputerResults.Summary.OrganizationalUnit @WriteSummary
Write-Color -Text '[>] Site: ', $Results.ComputerResults.Summary.Site @WriteSummary
Write-Color -Text '[>] GPO Types: ', ($Results.ComputerResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
Write-Color -Text '[>] Slow link: ', ($Results.ComputerResults.Summary.SlowLink) @WriteSummary
if ($Results.ComputerResults) {
Write-Color -Text 'Computer Settings' -Color Yellow -LinesBefore 1
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.ComputerResults.Summary.ReadTime @WriteSummary
Write-Color -Text '[>] Computer Name: ', $Results.ComputerResults.Summary.ComputerName @WriteSummary
Write-Color -Text '[>] Domain Name: ', $Results.ComputerResults.Summary.DomainName @WriteSummary
Write-Color -Text '[>] Organizational Unit: ', $Results.ComputerResults.Summary.OrganizationalUnit @WriteSummary
Write-Color -Text '[>] Site: ', $Results.ComputerResults.Summary.Site @WriteSummary
Write-Color -Text '[>] GPO Types: ', ($Results.ComputerResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
Write-Color -Text '[>] Slow link: ', ($Results.ComputerResults.Summary.SlowLink) @WriteSummary
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3 -LinesBefore 1
foreach ($GPO in $ComputerWhereApplied[0]) {
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
}
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3 -LinesBefore 1
foreach ($GPO in $ComputerWhereApplied[0]) {
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
}
Write-Color -Text 'Denied Group Policy Objects' -StartSpaces 3
foreach ($GPO in $ComputerWhereApplied[1]) {
Write-Color -Text '[-] [', $GPO.DomainName, '] ', $GPO.Name @GPODeny
Write-Color -Text 'Denied Group Policy Objects' -StartSpaces 3
foreach ($GPO in $ComputerWhereApplied[1]) {
Write-Color -Text '[-] [', $GPO.DomainName, '] ', $GPO.Name @GPODeny
}
} else {
Write-Color -Text 'Computer Settings' -Color Yellow -LinesBefore 1
Write-Color -Text '[>] Last time Group Policy was applied: ', 'Unable to get? No administrative permission?' @WriteSummary
Write-Color -Text '[>] Computer Name: ', $ComputerName @WriteSummary
}
Write-Color -Text 'User Settings' -Color Yellow -LinesBefore 1
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.UserResults.Summary.ReadTime @WriteSummary
Write-Color -Text '[>] Computer Name: ', $Results.UserResults.Summary.ComputerName @WriteSummary
Write-Color -Text '[>] Domain Name: ', $Results.UserResults.Summary.DomainName @WriteSummary
Write-Color -Text '[>] Organizational Unit: ', $Results.UserResults.Summary.OrganizationalUnit @WriteSummary
Write-Color -Text '[>] Site: ', $Results.UserResults.Summary.Site @WriteSummary
Write-Color -Text '[>] GPO Types: ', ($Results.UserResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
Write-Color -Text '[>] Slow link: ', ($Results.UserResults.Summary.SlowLink) @WriteSummary
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3
foreach ($GPO in $UserWhereApplied[0] ) {
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
+18 -24
View File
@@ -1,16 +1,11 @@
function New-GPOZaurrReportHTML {
function New-GPOZaurrReportHTML {
[cmdletBinding()]
param(
[System.Collections.IDictionary] $Support,
[string] $Path,
[switch] $Offline,
[switch] $Online,
[switch] $Open
)
$PSDefaultParameterValues = @{
"New-HTMLTable:WarningAction" = 'SilentlyContinue'
}
@@ -23,43 +18,42 @@ function New-GPOZaurrReportHTML {
New-HTML -TitleText "Group Policy Report - $ComputerName" {
#New-HTMLTabOptions -SlimTabs -Transition -LinearGradient -SelectorColor Akaroa
New-HTMLTableOption -DataStore JavaScript -BoolAsString
New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
New-HTMLPanelStyle -BorderRadius 0px
New-HTMLTabOptions -SlimTabs `
-BorderBottomStyleActive solid -BorderBottomColorActive LightSkyBlue -BackgroundColorActive none `
-TextColorActive Black -Align left -BorderRadius 0px -RemoveShadow -TextColor Grey -TextTransform capitalize
New-HTMLTab -Name 'Information' {
New-HTMLTable -DataTable $Support.ResultantSetPolicy -HideFooter -Transpose
New-HTMLSection {
New-HTMLSection {
#New-HTMLTable -DataTable $Support.ResultantSetPolicy -HideFooter -Transpose
New-HTMLSection -HeaderText 'General Information' {
New-HTMLTable -DataTable $Support.ComputerInformation.Time -Filtering -Transpose {
New-TableHeader -Names 'Name', 'Value' -Title 'Time Information'
}
New-HTMLTable -DataTable $Support.ComputerInformation.BIOS -Filtering -Transpose
New-HTMLTable -DataTable $Support.ComputerInformation.BIOS -Filtering -Transpose {
New-TableHeader -Names 'Name', 'Value' -Title 'BIOS Information'
}
}
New-HTMLContainer {
New-HTMLSection {
New-HTMLSection -HeaderText 'CPU Information' {
New-HTMLTable -DataTable $Support.ComputerInformation.CPU -Filtering
}
New-HTMLSection {
New-HTMLSection -HeaderText 'RAM Information' {
New-HTMLTable -DataTable $Support.ComputerInformation.RAM -Filtering
}
}
}
New-HTMLSection {
New-HTMLSection -HeaderText 'Operating System Information' {
New-HTMLTable -DataTable $Support.ComputerInformation.OperatingSystem -Filtering
New-HTMLTable -DataTable $Support.ComputerInformation.System -Filtering
}
New-HTMLSection {
New-HTMLSection -HeaderText 'Disk Information' {
New-HTMLTable -DataTable $Support.ComputerInformation.Disk -Filtering
New-HTMLTable -DataTable $Support.ComputerInformation.DiskLogical -Filtering
}
New-HTMLSection {
New-HTMLSection -HeaderText 'Services Information' {
New-HTMLTable -DataTable $Support.ComputerInformation.Services -Filtering
}
New-HTMLSection {
}
}
foreach ($Key in $Support.Keys) {
if ($Key -in 'ResultantSetPolicy', 'ComputerInformation') {
@@ -81,9 +75,9 @@ function New-GPOZaurrReportHTML {
New-HTMLTable -DataTable $Support.$Key.SummaryDownload -HideFooter
}
#>
New-HTMLSection -HeaderText 'Resultant Set Policy' {
New-HTMLTable -DataTable $Support.$Key.ResultantSetPolicy -HideFooter
}
#New-HTMLSection -HeaderText 'Resultant Set Policy' {
# New-HTMLTable -DataTable $Support.$Key.ResultantSetPolicy -HideFooter
#}
}
New-HTMLTab -Name 'Group Policies' {
New-HTMLSection -Invisible {
@@ -195,5 +189,5 @@ function New-GPOZaurrReportHTML {
}
}
}
} -Online:(-not $Offline.IsPresent) -Open:$Open.IsPresent -FilePath $Path
} -Online:$Online.IsPresent -Open:$Open.IsPresent -FilePath $Path
}
+5 -2
View File
@@ -1,11 +1,14 @@
$Script:GPOConfiguration = [ordered] @{
GPOOrphans = $GPOZaurrOrphans
GPOBroken = $GPOZaurrOrphans
GPOBrokenLink = $GPOZaurrBrokenLink
GPOOwners = $GPOZaurrOwners
GPOConsistency = $GPOZaurrConsistency
GPODuplicates = $GPOZaurrDuplicates
GPOOrganizationalUnit = $GPOZaurrOrganizationalUnit
GPOList = $GPOZaurrList
GPOLinks = $GPOZaurrLinks
GPOPassword = $GPOZaurrPassword
GPOPermissions = $GPOZaurrPermissions
GPOPermissions = $GPOZaurrPermissionsAnalysis
GPOPermissionsAdministrative = $GPOZaurrPermissionsAdministrative
GPOPermissionsRead = $GPOZaurrPermissionsRead
GPOPermissionsRoot = $GPOZaurrPermissionsRoot
+206 -80
View File
@@ -1,5 +1,5 @@
$Script:GPODitionary = [ordered] @{
AccountPolicies = [ordered] @{
AccountPolicies = [ordered] @{
Types = @(
@{
Category = 'SecuritySettings'
@@ -14,7 +14,7 @@
ConvertTo-XMLAccountPolicy -GPO $GPO -SingleObject
}
}
Audit = [ordered] @{
Audit = [ordered] @{
Types = @(
@{
Category = 'SecuritySettings'
@@ -36,7 +36,7 @@
ConvertTo-XMLAudit -GPO $GPO -SingleObject
}
}
Autologon = [ordered] @{
Autologon = [ordered] @{
# We want to process this based on other report called RegistrySettings
# This is because registry settings can be stored in Collections or nested within other registry settings
# The original function ConvertTo-XMLRegistryAutologon was processing it in limited ordered and potentially would skip some entries.
@@ -50,7 +50,7 @@
ConvertTo-XMLRegistryAutologonOnReport -GPO $GPO
}
}
AutoPlay = @{
AutoPlay = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -65,7 +65,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/AutoPlay Policies*' -SingleObject
}
}
Biometrics = @{
Biometrics = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -78,7 +78,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Biometrics*'
}
}
Bitlocker = @{
Bitlocker = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -95,7 +95,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/BitLocker Drive Encryption*' -SingleObject
}
}
ControlPanel = [ordered]@{
ControlPanel = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -110,7 +110,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel' -SingleObject
}
}
ControlPanelAddRemove = [ordered]@{
ControlPanelAddRemove = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -125,7 +125,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Add or Remove Programs' -SingleObject
}
}
ControlPanelDisplay = [ordered]@{
ControlPanelDisplay = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -140,7 +140,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Display' -SingleObject
}
}
ControlPanelPersonalization = [ordered]@{
ControlPanelPersonalization = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -155,7 +155,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Personalization' -SingleObject
}
}
ControlPanelPrinters = [ordered]@{
ControlPanelPrinters = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -170,7 +170,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Printers' -SingleObject
}
}
ControlPanelPrograms = [ordered]@{
ControlPanelPrograms = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -185,7 +185,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Programs' -SingleObject
}
}
ControlPanelRegional = [ordered]@{
ControlPanelRegional = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -200,7 +200,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Regional and Language Options' -SingleObject
}
}
CredentialsDelegation = @{
CredentialsDelegation = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -215,7 +215,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Credentials Delegation*' -SingleObject
}
}
CustomInternationalSettings = [ordered]@{
CustomInternationalSettings = [ordered]@{
Types = @(
@{
Category = 'RegistrySettings'
@@ -230,7 +230,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Custom International Settings*' -SingleObject
}
}
Desktop = @{
Desktop = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -245,7 +245,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Desktop*' -SingleObject
}
}
DnsClient = @{
DnsClient = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -260,7 +260,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Network/DNS Client*' -SingleObject
}
}
DriveMapping = [ordered] @{
DriveMapping = [ordered] @{
Types = @(
@{
Category = 'DriveMapSettings'
@@ -275,7 +275,7 @@
ConvertTo-XMLDriveMapSettings -GPO $GPO -SingleObject
}
}
EventLog = [ordered] @{
EventLog = [ordered] @{
Types = @(
@{
Category = 'SecuritySettings'
@@ -290,7 +290,7 @@
ConvertTo-XMLEventLog -GPO $GPO
}
}
EventForwarding = @{
EventForwarding = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -305,7 +305,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Event Forwarding*' -SingleObject
}
}
EventLogService = @{
EventLogService = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -320,7 +320,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Event Log Service*' -SingleObject
}
}
FileExplorer = @{
FileExplorer = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -335,7 +335,22 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/File Explorer*' -SingleObject
}
}
FolderRedirection = @{
FolderRedirection = @{
Types = @(
@{
Category = 'FolderRedirectionSettings'
Settings = 'Folder'
}
)
GPOPath = 'Windows Settings -> Folder Redirection'
Code = {
ConvertTo-XMLFolderRedirection -GPO $GPO
}
CodeSingle = {
ConvertTo-XMLFolderRedirection -GPO $GPO -SingleObject
}
}
FolderRedirectionPolicy = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -350,7 +365,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Folder Redirection' -SingleObject
}
}
FSLogix = @{
FSLogix = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -365,7 +380,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'FSLogix' -SingleObject
}
}
GoogleChrome = @{
GoogleChrome = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -384,7 +399,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Google Chrome', 'Google/Google Chrome', 'Google Chrome - Default Settings (users can override)' -SingleObject
}
}
GroupPolicy = @{
GroupPolicy = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -399,7 +414,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Group Policy*' -SingleObject
}
}
InternetCommunicationManagement = @{
InternetCommunicationManagement = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -414,7 +429,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Internet Communication Management*' -SingleObject
}
}
InternetExplorer = @{
InternetExplorer = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -429,7 +444,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Internet Explorer*', 'Composants Windows/Celle Internet Explorer' -SingleObject
}
}
InternetExplorerZones = [ordered] @{
InternetExplorerZones = [ordered] @{
ByReports = @(
@{
Report = 'RegistrySettings'
@@ -440,7 +455,7 @@
ConvertTo-XMLRegistryInternetExplorerZones -GPO $GPO
}
}
KDC = @{
KDC = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -455,7 +470,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/KDC' -SingleObject
}
}
LAPS = @{
LAPS = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -470,7 +485,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'LAPS' -SingleObject
}
}
Lithnet = @{
Lithnet = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -486,7 +501,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Lithnet/Password Protection for Active Directory*' -SingleObject
}
}
LocalUsers = [ordered] @{
LocalUsers = [ordered] @{
Types = @(
@{
Category = 'LugsSettings'
@@ -501,7 +516,7 @@
ConvertTo-XMLLocalUser -GPO $GPO -SingleObject
}
}
LocalGroups = [ordered] @{
LocalGroups = [ordered] @{
Types = @(
@{
Category = 'LugsSettings'
@@ -516,7 +531,7 @@
ConvertTo-XMLLocalGroups -GPO $GPO -SingleObject
}
}
Logon = @{
Logon = @{
Types = @(
@{ Category = 'RegistrySettings'; Settings = 'Policy' }
)
@@ -528,7 +543,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Logon*' -SingleObject
}
}
MicrosoftOutlook2002 = @{
MicrosoftOutlook2002 = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -543,7 +558,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2002*' -SingleObject
}
}
MicrosoftEdge = @{
MicrosoftEdge = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -562,7 +577,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Edge*', 'Windows Components/Microsoft Edge', 'Windows Components/Edge UI' -SingleObject
}
}
MicrosoftOutlook2003 = @{
MicrosoftOutlook2003 = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -580,7 +595,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Office Outlook 2003*', 'Outlook 2003 RPC Encryption' -SingleObject
}
}
MicrosoftOutlook2010 = @{
MicrosoftOutlook2010 = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -595,7 +610,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2010*' -SingleObject
}
}
MicrosoftOutlook2013 = @{
MicrosoftOutlook2013 = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -610,7 +625,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2013*' -SingleObject
}
}
MicrosoftOutlook2016 = @{
MicrosoftOutlook2016 = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -625,7 +640,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2016*' -SingleObject
}
}
MicrosoftManagementConsole = @{
MicrosoftManagementConsole = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -640,7 +655,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Microsoft Management Console*' -SingleObject
}
}
NetMeeting = @{
NetMeeting = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -655,7 +670,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/NetMeeting*' -SingleObject
}
}
MSSLegacy = @{
MSSLegacy = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -670,7 +685,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'MSS (Legacy)' -SingleObject
}
}
MSSecurityGuide = @{
MSSecurityGuide = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -685,7 +700,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'MS Security Guide' -SingleObject
}
}
OneDrive = @{
OneDrive = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -700,7 +715,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/OneDrive*' -SingleObject
}
}
Policies = @{
Policies = @{
Comment = "This isn't really translated"
Types = @(
@{
@@ -716,7 +731,7 @@
ConvertTo-XMLPolicies -GPO $GPO -SingleObject
}
}
Printers = @{
Printers = @{
Types = @(
@{
Category = 'PrintersSettings'
@@ -735,7 +750,7 @@
ConvertTo-XMLPrinter -GPO $GPO -SingleObject
}
}
PrintersPolicies = @{
PrintersPolicies = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -753,7 +768,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Printers*', 'Control Panel/Printers*' -SingleObject
}
}
PublicKeyPoliciesCertificates = [ordered] @{
PublicKeyPoliciesCertificates = [ordered] @{
Types = @(
@{
Category = 'PublicKeySettings'
@@ -774,10 +789,10 @@
)
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Public Key Policies'
Code = {
ConvertTo-XMLGenericPublicKey -GPO $GPO
ConvertTo-XMLCertificates -GPO $GPO
}
CodeSingle = {
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
ConvertTo-XMLCertificates -GPO $GPO -SingleObject
}
}
<#
@@ -805,7 +820,7 @@
}
}
#>
PublicKeyPoliciesAutoEnrollment = [ordered] @{
PublicKeyPoliciesAutoEnrollment = [ordered] @{
Types = @(
@{
Category = 'PublicKeySettings'
@@ -820,7 +835,7 @@
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
}
}
PublicKeyPoliciesEFS = [ordered] @{
PublicKeyPoliciesEFS = [ordered] @{
Types = @(
@{
Category = 'PublicKeySettings'
@@ -835,7 +850,7 @@
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
}
}
PublicKeyPoliciesRootCA = [ordered] @{
PublicKeyPoliciesRootCA = [ordered] @{
Types = @(
@{
Category = 'PublicKeySettings'
@@ -850,7 +865,7 @@
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
}
}
PublicKeyPoliciesEnrollmentPolicy = @{
PublicKeyPoliciesEnrollmentPolicy = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -867,7 +882,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Internet Communication Management*' -SingleObject
}
}
RegistrySetting = [ordered] @{
RegistrySetting = [ordered] @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -882,7 +897,7 @@
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
}
}
RegistrySettings = [ordered] @{
RegistrySettings = [ordered] @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -897,7 +912,7 @@
ConvertTo-XMLRegistrySettings -GPO $GPO -SingleObject
}
}
OnlineAssistance = @{
OnlineAssistance = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -912,7 +927,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Online Assistance*' -SingleObject
}
}
RemoteAssistance = @{
RemoteAssistance = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -927,7 +942,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Remote Assistance*' -SingleObject
}
}
RemoteDesktopServices = @{
RemoteDesktopServices = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -942,7 +957,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Remote Desktop Services*' -SingleObject
}
}
RSSFeeds = @{
RSSFeeds = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -957,7 +972,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/RSS Feeds*' -SingleObject
}
}
Scripts = [ordered] @{
Scripts = [ordered] @{
Types = @(
@{
Category = 'Scripts'
@@ -972,7 +987,7 @@
ConvertTo-XMLScripts -GPO $GPO -SingleObject
}
}
SecurityOptions = [ordered] @{
SecurityOptions = [ordered] @{
Types = @(
@{
Category = 'SecuritySettings'
@@ -987,7 +1002,7 @@
ConvertTo-XMLSecurityOptions -GPO $GPO -SingleObject
}
}
SoftwareInstallation = [ordered] @{
SoftwareInstallation = [ordered] @{
Types = @(
@{
Category = 'SoftwareInstallationSettings'
@@ -1002,7 +1017,7 @@
ConvertTo-XMLSoftwareInstallation -GPO $GPO -SingleObject
}
}
SystemServices = [ordered] @{
SystemServices = [ordered] @{
Types = @(
@{
Category = 'SecuritySettings'
@@ -1018,7 +1033,7 @@
ConvertTo-XMLSystemServices -GPO $GPO -SingleObject
}
}
SystemServicesNT = [ordered] @{
SystemServicesNT = [ordered] @{
Types = @(
@{
Category = 'ServiceSettings'
@@ -1052,7 +1067,7 @@
}
}
#>
TaskScheduler = [ordered] @{
TaskScheduler = [ordered] @{
Types = @(
@{
Category = 'ScheduledTasksSettings'
@@ -1068,7 +1083,7 @@
ConvertTo-XMLTaskScheduler -GPO $GPO -SingleObject
}
}
TaskSchedulerPolicies = @{
TaskSchedulerPolicies = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1101,7 +1116,7 @@
}
}
#>
UserRightsAssignment = [ordered] @{
UserRightsAssignment = [ordered] @{
Types = @(
@{
Category = 'SecuritySettings'
@@ -1116,7 +1131,7 @@
ConvertTo-XMLUserRightsAssignment -GPO $GPO -SingleObject
}
}
WindowsDefender = @{
WindowsDefender = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1131,7 +1146,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Defender*' -SingleObject
}
}
WindowsDefenderExploitGuard = @{
WindowsDefenderExploitGuard = @{
# this needs improvements because of DropDownList
Types = @(
@{
@@ -1147,7 +1162,103 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Microsoft Defender Antivirus/Microsoft Defender Exploit Guard*' -SingleObject
}
}
WindowsHelloForBusiness = @{
# WindowsFirewall = @{
# # Contains only one setting showing version
# Types = @(
# @{
# Category = 'WindowsFirewallSettings'
# Settings = 'GlobalSettings'
# }
# )
# GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
# Code = {
# ConvertTo-XMLWindowsFirewall -GPO $GPO
# }
# CodeSingle = {
# ConvertTo-XMLWindowsFirewall -GPO $GPO -SingleObject
# }
# }
WindowsFirewallConnectionSecurityRules = @{
Types = @(
@{
Category = 'WindowsFirewallSettings'
Settings = 'ConnectionSecurityRules'
}
)
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
Code = {
ConvertTo-XMLWindowsFirewallSecurityRules -GPO $GPO
}
CodeSingle = {
ConvertTo-XMLWindowsFirewallSecurityRules -GPO $GPO -SingleObject
}
}
WindowsFirewallConnectionSecurityAuthentication = @{
Types = @(
@{
Category = 'WindowsFirewallSettings'
Settings = 'Phase1AuthenticationSets'
}
@{
Category = 'WindowsFirewallSettings'
Settings = 'Phase2AuthenticationSets'
}
#@{
# Category = 'WindowsFirewallSettings'
# Settings = 'DefaultPhase1CryptoSet'
#}
)
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
Code = {
ConvertTo-XMLWindowsFirewallConnectionSecurityAuthentiation -GPO $GPO
}
CodeSingle = {
ConvertTo-XMLWindowsFirewallConnectionSecurityAuthentiation -GPO $GPO -SingleObject
}
}
WindowsFirewallProfiles = @{
Types = @(
@{
Category = 'WindowsFirewallSettings'
Settings = 'DomainProfile'
}
@{
Category = 'WindowsFirewallSettings'
Settings = 'PublicProfile'
}
@{
Category = 'WindowsFirewallSettings'
Settings = 'PrivateProfile'
}
)
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
Code = {
ConvertTo-XMLWindowsFirewallProfile -GPO $GPO
}
CodeSingle = {
ConvertTo-XMLWindowsFirewallProfile -GPO $GPO -SingleObject
}
}
WindowsFirewallRules = @{
Types = @(
@{
Category = 'WindowsFirewallSettings'
Settings = 'InboundFirewallRules'
}
@{
Category = 'WindowsFirewallSettings'
Settings = 'OutboundFirewallRules'
}
)
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security -> '
Code = {
ConvertTo-XMLWindowsFirewallRules -GPO $GPO
}
CodeSingle = {
ConvertTo-XMLWindowsFirewallRules -GPO $GPO -SingleObject
}
}
WindowsHelloForBusiness = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1162,7 +1273,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Hello For Business*' -SingleObject
}
}
WindowsInstaller = @{
WindowsInstaller = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1177,7 +1288,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Installer*' -SingleObject
}
}
WindowsLogon = @{
WindowsLogon = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1192,7 +1303,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Logon Options*' -SingleObject
}
}
WindowsMediaPlayer = @{
WindowsMediaPlayer = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1207,7 +1318,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Media Player*' -SingleObject
}
}
WindowsMessenger = @{
WindowsMessenger = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1222,7 +1333,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Messenger*' -SingleObject
}
}
WindowsPowerShell = @{
WindowsPowerShell = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1237,7 +1348,7 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows PowerShell*' -SingleObject
}
}
WindowsRemoteManagement = @{
WindowsRemoteManagement = @{
Types = @(
@{
Category = 'RegistrySettings'
@@ -1252,7 +1363,22 @@
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Remote Management (WinRM)*' -SingleObject
}
}
WindowsUpdate = @{
WindowsTimeService = @{
Types = @(
@{
Category = 'RegistrySettings'
Settings = 'Policy'
}
)
GPOPath = 'Policies -> Administrative Templates -> System/Windows Time Service'
Code = {
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Windows Time Service*'
}
CodeSingle = {
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Windows Time Service*' -SingleObject
}
}
WindowsUpdate = @{
Types = @(
@{
Category = 'RegistrySettings'
+35 -57
View File
@@ -9,8 +9,7 @@
)
$Differences = @{ }
$SysvolHash = @{ }
$GPOGUIDS = $GPOs.ID.GUID
$GPOGUIDS = ConvertFrom-DistinguishedName -DistinguishedName $GPOs.DistinguishedName
$SysVolPath = "\\$($Server)\SYSVOL\$Domain\Policies"
Write-Verbose "Get-GPOZaurrBroken - Processing SYSVOL from \\$($Server)\SYSVOL\$Domain\Policies"
try {
@@ -19,10 +18,10 @@
$Sysvol = $Null
}
foreach ($_ in $SYSVOL) {
$GUID = $_.Name -replace '{' -replace '}'
$GUID = $_.Name
$SysvolHash[$GUID] = $_
}
$Files = $SYSVOL.Name -replace '{' -replace '}'
$Files = $SYSVOL.Name
if ($Files) {
$Comparing = Compare-Object -ReferenceObject $GPOGUIDS -DifferenceObject $Files -IncludeEqual
foreach ($_ in $Comparing) {
@@ -30,8 +29,10 @@
# we skip policy definitions
continue
}
$ADStatus = $PoliciesAD[$_.InputObject]
if ($_.SideIndicator -eq '==') {
$Found = 'Exists'
#$Found = 'Exists'
$Found = $ADStatus
} elseif ($_.SideIndicator -eq '<=') {
$Found = 'Not available on SYSVOL'
} elseif ($_.SideIndicator -eq '=>') {
@@ -41,8 +42,10 @@
$Found = 'Not available in AD'
}
} else {
# This shouldn't happen at all
$Found = 'Orphaned GPO'
}
$Differences[$_.InputObject] = $Found
}
}
@@ -50,85 +53,60 @@
$Count = 0
foreach ($GPO in $GPOS) {
$Count++
Write-Verbose "Get-GPOZaurrBroken - Processing [$($GPO.DomainName)]($Count/$($GPOS.Count)) $($GPO.DisplayName)"
if ($null -ne $SysvolHash[$GPO.Id.GUID].FullName) {
$FullPath = $SysvolHash[$GPO.Id.GUID].FullName
try {
$ACL = Get-Acl -Path $SysvolHash[$GPO.Id.GUID].FullName -ErrorAction Stop -Verbose:$false
$Owner = $ACL.Owner
$ErrorMessage = ''
} catch {
Write-Warning "Get-GPOZaurrBroken - ACL reading (1) failed for $FullPath with error: $($_.Exception.Message)"
$ACL = $null
$Owner = ''
$ErrorMessage = $_.Exception.Message
}
$GPOGuid = ConvertFrom-DistinguishedName -DistinguishedName $GPO.DistinguishedName
if ($GPO.DisplayName) {
$GPODisplayName = $GPO.DisplayName
$GPOName = $GPO.Name
Write-Verbose "Get-GPOZaurrBroken - Processing [$($Domain)]($Count/$($GPOS.Count)) $($GPO.DisplayName)"
} else {
$FullPath = -join ($SysVolPath, "\{$($GPO.Id.Guid)}")
$ACL = $null
$Owner = ''
$GPOName = $GPOGuid
$GPODisplayName = $GPOGuid
Write-Verbose "Get-GPOZaurrBroken - Processing [$($Domain)]($Count/$($GPOS.Count)) $($GPOGuid)"
}
if ($null -ne $SysvolHash[$GPOGuid].FullName) {
$FullPath = $SysvolHash[$GPOGuid].FullName
$ErrorMessage = ''
} else {
$FullPath = -join ($SysVolPath, "\$($GPOGuid)")
$ErrorMessage = 'Not found on SYSVOL'
}
if ($null -eq $Differences[$GPO.Id.Guid]) {
$SysVolStatus = 'Unknown Issue'
if ($null -eq $Differences[$GPOGuid]) {
$SysVolStatus = 'Unknown issue'
} else {
$SysVolStatus = $Differences[$GPO.Id.Guid]
$SysVolStatus = $Differences[$GPOGuid]
}
[PSCustomObject] @{
DisplayName = $GPO.DisplayName
DisplayName = $GPODisplayName
Status = $SysVolStatus
DomainName = $GPO.DomainName
DomainName = $Domain
SysvolServer = $Server
SysvolStatus = $SysVolStatus
GpoStatus = $GPO.GpoStatus
Owner = $GPO.Owner
FileOwner = $Owner
Id = $GPO.Id.Guid
ObjectClass = $GPO.ObjectClass
Id = $GPOName
Path = $FullPath
DistinguishedName = -join ("CN={", $GPO.Id.Guid, "},", $PoliciesSearchBase)
DistinguishedName = -join ("CN=", $GPOGuid, ",", $PoliciesSearchBase)
Description = $GPO.Description
CreationTime = $GPO.CreationTime
ModificationTime = $GPO.ModificationTime
UserVersion = $GPO.UserVersion
ComputerVersion = $GPO.ComputerVersion
WmiFilter = $GPO.WmiFilter
CreationTime = $GPO.Created
ModificationTime = $GPO.Modified
Error = $ErrorMessage
}
}
# Now we need to list thru Sysvol files and fine those that do not exists as GPO and create dummy GPO objects to show orphaned gpos
Write-Verbose "Get-GPOZaurrBroken - Processing SYSVOL differences"
foreach ($_ in $Differences.Keys) {
if ($Differences[$_] -in 'Not available in AD', 'Permissions issue') {
if ($Differences[$_] -in 'Not available in AD') {
$FullPath = $SysvolHash[$_].FullName
try {
$ACL = Get-Acl -Path $FullPath -ErrorAction Stop
$Owner = $ACL.Owner
$ErrorMessage = ''
} catch {
Write-Warning "Get-GPOZaurrBroken - ACL reading (2) failed for $FullPath with error: $($_.Exception.Message)"
$ACL = $null
$Owner = $null
$ErrorMessage = $_.Exception.Message
}
[PSCustomObject] @{
DisplayName = $SysvolHash[$_].BaseName
Status = $Differences[$_]
DomainName = $Domain
SysvolServer = $Server
SysvolStatus = 'Exists' #$Differences[$GPO.Id.Guid]
GpoStatus = $Differences[$_]
Owner = ''
FileOwner = $Owner
ObjectClass = ''
Id = $_
Path = $FullPath
DistinguishedName = -join ("CN={", $_, "},", $PoliciesSearchBase)
DistinguishedName = -join ("CN=", $_, ",", $PoliciesSearchBase)
Description = $null
CreationTime = $SysvolHash[$_].CreationTime
ModificationTime = $SysvolHash[$_].LastWriteTime
UserVersion = $null
ComputerVersion = $null
WmiFilter = $null
Error = $ErrorMessage
}
}
+3 -3
View File
@@ -108,7 +108,7 @@
}
}
#>
if (-not $PermissionsAnalysis['Skip']) {
if (-not $PermissionsAnalysis.'Skip') {
if (-not $GPOPermissions) {
# This is bad - things went wrong
Write-Warning "Add-GPOZaurrPermission - Couldn't get permissions for GPO. Things aren't what they should be. Skipping!"
@@ -118,7 +118,7 @@
# We asked, we got response, now we need to check if maybe we're missing one of the two administrative groups
if ($Type -eq 'Administrative') {
# this is a case where something was returned. Be it Domain Admins or Enterprise Admins or both. But we still need to check because it may have been Domain Admins from other domain or just one of the two required groups
if ($PermissionsAnalysis['DomainAdmins'] -eq $false) {
if ($PermissionsAnalysis.'DomainAdmins' -eq $false) {
$Principal = $ADAdministrativeGroups[$GPO.DomainName]['DomainAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
@@ -132,7 +132,7 @@
}
}
}
if ($PermissionsAnalysis['EnterpriseAdmins'] -eq $false) {
if ($PermissionsAnalysis.'EnterpriseAdmins' -eq $false) {
$Principal = $ADAdministrativeGroups[$ForestInformation.Forest.RootDomain]['EnterpriseAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
+1 -1
View File
@@ -1,4 +1,4 @@
function Clear-GPOZaurrSysvolDFSR {
function Clear-GPOZaurrSysvolDFSR {
[cmdletBinding(SupportsShouldProcess)]
param(
[alias('ForestName')][string] $Forest,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertFrom-CSExtension {
function ConvertFrom-CSExtension {
[cmdletBinding()]
param(
[string[]] $CSE,
+1 -1
View File
@@ -1,4 +1,4 @@
function Find-CSExtension {
function Find-CSExtension {
[cmdletBinding()]
param(
[string[]] $CSE,
+41 -52
View File
@@ -5,7 +5,7 @@
[string] $GPOName,
[alias('GUID', 'GPOID')][string] $GPOGuid,
[validateset('Empty', 'Unlinked', 'Disabled', 'All')][string[]] $Type,
[validateset('Empty', 'Unlinked', 'Disabled', 'NoApplyPermission', 'All')][string[]] $Type,
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
@@ -47,6 +47,10 @@
if ($OwnerOnly -or $PermissionsOnly -and $Type) {
Write-Warning "Get-GPOZaurr - Using PermissionOnly or OwnerOnly with Type is not supported. "
}
if (-not $GPOPath) {
# This is needed, because Get-GPOReport doesn't deliver full scope of links, just some of it. It doesn't cover OUs with blocked inheritance, sites or crosslinked
$LinksSummaryCache = Get-GPOZaurrLink -AsHashTable -Summary -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
}
}
Process {
if (-not $GPOPath) {
@@ -54,68 +58,53 @@
$QueryServer = $ForestInformation.QueryServers[$Domain]['HostName'][0]
$Count = 0
if ($GPOName) {
$GroupPolicies = Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue
$GroupPolicies | ForEach-Object {
$Count++
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
if (-not $Limited) {
try {
$XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
} catch {
Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping."
continue
}
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
} else {
$_
}
$getGPOSplat = @{
Name = $GPOName
Domain = $Domain
Server = $QueryServer
ErrorAction = 'SilentlyContinue'
}
} elseif ($GPOGuid) {
$GroupPolicies = Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue
$GroupPolicies | ForEach-Object {
$Count++
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
if (-not $Limited) {
try {
$XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
} catch {
Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping."
continue
}
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
} else {
$_
}
$getGPOSplat = @{
Guid = $GPOGuid
Domain = $Domain
Server = $QueryServer
ErrorAction = 'SilentlyContinue'
}
} else {
$GroupPolicies = Get-GPO -All -Server $QueryServer -Domain $Domain -ErrorAction SilentlyContinue
$GroupPolicies | ForEach-Object {
$Count++
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
if (-not $Limited) {
try {
$XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
} catch {
Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping."
continue
}
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
} else {
$_
$getGPOSplat = @{
All = $true
Server = $QueryServer
Domain = $Domain
ErrorAction = 'SilentlyContinue'
}
}
$GroupPolicies = Get-GPO @getGPOSplat
foreach ($GPO in $GroupPolicies) {
$Count++
Write-Verbose "Get-GPOZaurr - Processing [$($GPO.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
if (-not $Limited) {
try {
$XMLContent = Get-GPOReport -ID $GPO.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
} catch {
Write-Warning "Get-GPOZaurr - Failed to get [$($GPO.DomainName)]($Count/$($GroupPolicies.Count)) $($GPO.DisplayName) GPOReport: $($_.Exception.Message). Skipping."
continue
}
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $GPO -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type -LinksSummaryCache $LinksSummaryCache
} else {
$GPO
}
}
}
} else {
foreach ($Path in $GPOPath) {
Write-Verbose "Get-GPOZaurr - Getting GPO content from XML files"
Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml | ForEach-Object {
$XMLContent = [XML]::new()
$XMLContent.Load($_.FullName)
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml -ErrorAction SilentlyContinue | ForEach-Object {
if ($_.Name -ne 'GPOList.xml') {
$XMLContent = [XML]::new()
$XMLContent.Load($_.FullName)
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
}
}
Write-Verbose "Get-GPOZaurr - Finished GPO content from XML files"
}
+22 -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', 'Last7Days', 'Last3Days', 'Last1Days')][string] $DateRange,
[ValidateSet('WhenCreated', 'WhenChanged')][string] $DateProperty = 'WhenCreated',
[System.Collections.IDictionary] $ExtendedForestInformation
)
Begin {
@@ -48,7 +53,21 @@
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)
$Splat['Filter'] = -join ($Splat['Filter'], '-and ($DateProperty -ge $DateFrom -and $DateProperty -le $DateTo)')
} 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)')
} else {
# not needed
}
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 +79,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
+58 -16
View File
@@ -1,4 +1,47 @@
function Get-GPOZaurrBroken {
<#
.SYNOPSIS
Detects broken or otherwise damaged Group Policies
.DESCRIPTION
Detects broken or otherwise damaged Group Policies providing insight whether GPO exists in both AD and SYSVOL.
It provides few statuses:
- Permissions issue - means account couldn't read GPO due to permissions
- ObjectClass issue - means that ObjectClass is of type Container, rather than expected groupPolicyContainer
- Not available on SYSVOL - means SYSVOL data is missing, yet AD metadata is available
- Not available in AD - means AD metadata is missing, yet SYSVOL data is available
- Exists - means AD metadata and SYSVOL data are available
.PARAMETER Forest
Target different Forest, by default current forest is used
.PARAMETER ExcludeDomains
Exclude domain from search, by default whole forest is scanned
.PARAMETER ExcludeDomainControllers
Exclude specific domain controllers, by default there are no exclusions, as long as VerifyDomainControllers switch is enabled. Otherwise this parameter is ignored.
.PARAMETER IncludeDomains
Include only specific domains, by default whole forest is scanned
.PARAMETER IncludeDomainControllers
Include only specific domain controllers, by default all domain controllers are included, as long as VerifyDomainControllers switch is enabled. Otherwise this parameter is ignored.
.PARAMETER SkipRODC
Skip Read-Only Domain Controllers. By default all domain controllers are included.
.PARAMETER ExtendedForestInformation
Ability to provide Forest Information from another command to speed up processing
.PARAMETER VerifyDomainControllers
Forces cmdlet to check GPO Existance on Domain Controllers rather then per domain
.EXAMPLE
Get-GPOZaurrBroken -Verbose | Format-Table
.NOTES
General notes
#>
[alias('Get-GPOZaurrSysvol')]
[cmdletBinding()]
param(
@@ -8,7 +51,6 @@
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[alias('DomainControllers')][string[]] $IncludeDomainControllers,
[switch] $SkipRODC,
[Array] $GPOs,
[System.Collections.IDictionary] $ExtendedForestInformation,
[switch] $VerifyDomainControllers
)
@@ -21,31 +63,31 @@
$PoliciesAD = @{}
if ($SystemsContainer) {
$PoliciesSearchBase = -join ("CN=Policies,", $SystemsContainer)
$PoliciesInAD = Get-ADObject -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer
$PoliciesInAD = Get-ADObject -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer -Properties Name, gPCFileSysPath, DisplayName, DistinguishedName, Description, Created, Modified, ObjectClass, ObjectGUID
foreach ($Policy in $PoliciesInAD) {
$GUIDFromDN = ConvertFrom-DistinguishedName -DistinguishedName $Policy.DistinguishedName
$GUIDFromDN = $GUIDFromDN -replace '{' -replace '}'
$GUID = $Policy.Name -replace '{' -replace '}'
if ($GUID -and $GUIDFromDN) {
$PoliciesAD[$GUIDFromDN] = 'Exists'
if ($Policy.ObjectClass -eq 'Container') {
# This usually means GPO deletion process somehow failed and while object itself stayed it isn't groupPolicyContainer anymore
$PoliciesAD[$GUIDFromDN] = 'ObjectClass issue'
} else {
$PoliciesAD[$GUIDFromDN] = 'Permissions issue'
$GUID = $Policy.Name
if ($GUID -and $GUIDFromDN) {
$PoliciesAD[$GUIDFromDN] = 'Exists'
} else {
$PoliciesAD[$GUIDFromDN] = 'Permissions issue'
}
}
}
} else {
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Skipping"
}
Try {
[Array]$GPOs = Get-GPO -All -Domain $Domain -Server $QueryServer
} catch {
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Error: $($_.Exception.Message)"
continue
}
if ($GPOs.Count -ge 2) {
if ($PoliciesInAD.Count -ge 2) {
if (-not $VerifyDomainControllers) {
Test-SysVolFolders -GPOs $GPOs -Server $Domain -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
Test-SysVolFolders -GPOs $PoliciesInAD -Server $Domain -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
} else {
foreach ($Server in $ForestInformation['DomainDomainControllers']["$Domain"]) {
Write-Verbose "Get-GPOZaurrBroken - Processing $Domain \ $($Server.HostName.Trim())"
Test-SysVolFolders -GPOs $GPOs -Server $Server.Hostname -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
Test-SysVolFolders -GPOs $PoliciesInAD -Server $Server.Hostname -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
}
}
} else {
+85
View File
@@ -0,0 +1,85 @@
function Get-GPOZaurrBrokenLink {
<#
.SYNOPSIS
Finds any GPO link that doesn't have a matching GPO (already removed GPO).
.DESCRIPTION
Finds any GPO link that doesn't have a matching GPO (already removed GPO).
.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 ExtendedForestInformation
Ability to provide Forest Information from another command to speed up processing
.EXAMPLE
Get-GPOZaurrBrokenLink -Verbose | Format-Table -AutoSize *
.EXAMPLE
Get-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl | Format-Table -AutoSize *
.NOTES
General notes
#>
[cmdletBinding()]
param(
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation
)
$ErrorFound = $false
$PoliciesAD = @{}
# We need to request all GPOS from Forest. Requesting just for any domain won't be enough
$ForestInformation = Get-WinADForestDetails -Forest $Forest -Extended # -Extended
foreach ($Domain in $ForestInformation.Domains) {
$QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0]
$SystemsContainer = $ForestInformation['DomainsExtended'][$Domain].SystemsContainer
if ($SystemsContainer) {
$PoliciesSearchBase = -join ("CN=Policies,", $SystemsContainer)
try {
$PoliciesInAD = Get-ADObject -ErrorAction Stop -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer -Properties Name, gPCFileSysPath, DisplayName, DistinguishedName, Description, Created, Modified, ObjectClass, ObjectGUID
} catch {
Write-Warning "Get-GPOZaurrBrokenLink - An error occured while searching $PoliciesSearchBase. Error $($_.Exception.Message). Please resolve this before continuing."
$ErrorFound = $true
break
}
foreach ($Policy in $PoliciesInAD) {
$GUIDFromDN = ConvertFrom-DistinguishedName -DistinguishedName $Policy.DistinguishedName
# $Key = "$($Domain)$($GuidFromDN)"
$Key = $Policy.DistinguishedName
if ($Policy.ObjectClass -eq 'Container') {
# This usually means GPO deletion process somehow failed and while object itself stayed it isn't groupPolicyContainer anymore
$PoliciesAD[$Key] = 'ObjectClass issue'
} else {
$GUID = $Policy.Name
if ($GUID -and $GUIDFromDN) {
$PoliciesAD[$Key] = 'Exists'
} else {
$PoliciesAD[$Key] = 'Permissions issue'
}
}
}
} else {
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Skipping"
}
}
if ($ErrorFound) {
return
}
# In case of links we can request here whatever user requested.
# This will search for broken links in domain user requested
$ForestInformation = Get-WinADForestDetails -Forest $Forest -Extended -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
$Links = Get-GPOZaurrLinkLoop -Linked 'All' -ForestInformation $ForestInformation
foreach ($Link in $Links) {
if (-not $PoliciesAD[$Link.GPODistinguishedName]) {
$Link
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
function Get-GPOZaurrFilesPolicyDefinition {
function Get-GPOZaurrFilesPolicyDefinition {
[alias('Get-GPOZaurrFilesPolicyDefinitions')]
[cmdletbinding()]
param(

Some files were not shown because too many files have changed in this diff Show More