├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── General.md │ ├── Resource_proposal.md │ └── Problem_with_resource.md ├── stale.yml └── PULL_REQUEST_TEMPLATE.md ├── DSCResources ├── MSFT_AuditPolicyCsv │ ├── MSFT_AuditPolicyCsv.schema.mof │ ├── en-US │ │ └── MSFT_AuditPolicyCsv.strings.psd1 │ └── MSFT_AuditPolicyCsv.psm1 ├── MSFT_AuditPolicyOption │ ├── en-US │ │ └── MSFT_AuditPolicyOption.strings.psd1 │ ├── MSFT_AuditPolicyOption.schema.mof │ └── MSFT_AuditPolicyOption.psm1 ├── MSFT_AuditPolicySubcategory │ ├── en-US │ │ └── MSFT_AuditPolicySubcategory.strings.psd1 │ ├── MSFT_AuditPolicySubcategory.schema.mof │ └── MSFT_AuditPolicySubcategory.psm1 ├── MSFT_AuditPolicyGUID │ ├── MSFT_AuditPolicyGUID.schema.mof │ ├── en-US │ │ └── MSFT_AuditPolicyGUID.strings.psd1 │ └── MSFT_AuditPolicyGUID.psm1 └── AuditPolicyResourceHelper │ ├── en-US │ └── AuditPolicyResourceHelper.strings.psd1 │ └── AuditPolicyResourceHelper.psm1 ├── Tests ├── Integration │ ├── MSFT_AuditPolicyCsv.config.ps1 │ ├── MSFT_AuditPolicyOption.config.ps1 │ ├── MSFT_AuditPolicyGUID.config.ps1 │ ├── MSFT_AuditPolicySubcategory.config.ps1 │ ├── MSFT_AuditPolicyOption.Integration.tests.ps1 │ ├── MSFT_AuditPolicyCsv.integration.tests.ps1 │ ├── AuditPolicyResourceHelper.Integration.Tests.ps1 │ ├── MSFT_AuditPolicyGUID.Integration.tests.ps1 │ └── MSFT_AuditPolicySubcategory.Integration.tests.ps1 └── Unit │ ├── audit.csv │ ├── MSFT_AuditPolicyOption.tests.ps1 │ ├── MSFT_AuditPolicyCsv.tests.ps1 │ └── MSFT_AuditPolicySubcategory.tests.ps1 ├── Examples ├── Sample_AuditPolicyOption.ps1 ├── Sample_AuditPolicyCsv.ps1 ├── Sample_AuditPolicyGuid.ps1 └── Sample_AuditPolicySubcategory.ps1 ├── .codecov.yml ├── appveyor.yml ├── LICENSE ├── AuditPolicyDsc.psd1 └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | DSCResource.Tests 2 | .vscode/ 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/General.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General question or documentation update 3 | about: If you have a general question or documentation update suggestion around the resource module. 4 | --- 5 | 8 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyCsv/MSFT_AuditPolicyCsv.schema.mof: -------------------------------------------------------------------------------- 1 | [ClassVersion("1.0.0.0"), FriendlyName("AuditPolicyCsv")] 2 | class MSFT_AuditPolicyCsv : OMI_BaseResource 3 | { 4 | [Key, Description("Specifies the resource is a single instance, the value must be 'Yes'"), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; 5 | [Required, Description("Path to a CSV backup of Auditing settings")] String CsvPath; 6 | }; 7 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicyCsv.config.ps1: -------------------------------------------------------------------------------- 1 | 2 | configuration 'MSFT_AuditPolicyCsv_config' 3 | { 4 | param 5 | ( 6 | [Parameter(Mandatory = $true)] 7 | [System.String] 8 | $CsvPath 9 | ) 10 | 11 | Import-DscResource -ModuleName 'AuditPolicyDsc' 12 | 13 | node localhost 14 | { 15 | AuditPolicyCsv Integration_Test 16 | { 17 | IsSingleInstance = 'Yes' 18 | CsvPath = $CsvPath 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyOption/en-US/MSFT_AuditPolicyOption.strings.psd1: -------------------------------------------------------------------------------- 1 | ConvertFrom-StringData -StringData @' 2 | GetAuditpolOptionSucceed = (GET) '{0}' 3 | GetAuditpolOptionFailed = (ERROR) getting '{0}' 4 | SetAuditpolOptionSucceed = (SET) '{0}' to '{1}' 5 | SetAuditpolOptionFailed = (ERROR) setting '{0}' to value '{1}' 6 | TestAuditpolOptionCorrect = '{0}' is '{1}' 7 | TestAuditpolOptionIncorrect = '{0}' is NOT '{1}' 8 | '@ 9 | 10 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyCsv/en-US/MSFT_AuditPolicyCsv.strings.psd1: -------------------------------------------------------------------------------- 1 | ConvertFrom-StringData -StringData @' 2 | BackupFilePath = Exporting to {0} 3 | ExportFailed = Failed export to {0} 4 | ImportFailed = Failed import of {0} 5 | ExportSucceeded = Succeeded export to {0} 6 | ImportSucceeded = Succeeded import of {0} 7 | testCsvFailed = {0} not in desired state 8 | testCsvSucceed = {0} in desired state 9 | FileNotFound = {0} not found 10 | RemoveFile = Removing {0} 11 | CmdletsNotFound = Security cmdlets not found, switching to auditpol.exe 12 | '@ 13 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyOption/MSFT_AuditPolicyOption.schema.mof: -------------------------------------------------------------------------------- 1 | 2 | [ClassVersion("1.0.0.0"), FriendlyName("AuditPolicyOption")] 3 | class MSFT_AuditPolicyOption : OMI_BaseResource 4 | { 5 | [Key, Description("The name of the audit policy option to set."), ValueMap{"CrashOnAuditFail","FullPrivilegeAuditing","AuditBaseObjects","AuditBaseDirectories"}, Values{"CrashOnAuditFail","FullPrivilegeAuditing","AuditBaseObjects","AuditBaseDirectories"}] String Name; 6 | [Key, Description("The value to set the audit policy option to."), ValueMap{"Enabled","Disabled"}, Values{"Enabled","Disabled"}] String Value; 7 | }; 8 | -------------------------------------------------------------------------------- /Examples/Sample_AuditPolicyOption.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This example will enable Base Directory auditing on the localhost. 3 | To use this example, run it using PowerShell. 4 | #> 5 | Configuration Sample_AuditOption 6 | { 7 | param 8 | ( 9 | [String] $NodeName = 'localhost' 10 | ) 11 | 12 | Import-DscResource -ModuleName AuditPolicyDsc 13 | 14 | Node $NodeName 15 | { 16 | AuditPolicyOption AuditBaseDirectories 17 | { 18 | Name = 'AuditBaseDirectories' 19 | Value = 'Enabled' 20 | } 21 | } 22 | } 23 | 24 | Sample_AuditOption 25 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicyOption.config.ps1: -------------------------------------------------------------------------------- 1 | 2 | configuration 'MSFT_AuditPolicyOption_config' 3 | { 4 | param 5 | ( 6 | [Parameter(Mandatory = $true)] 7 | [System.String] 8 | $OptionName, 9 | 10 | [Parameter(Mandatory = $true)] 11 | [System.String] 12 | $OptionValue 13 | ) 14 | 15 | Import-DscResource -ModuleName 'AuditPolicyDsc' 16 | 17 | node localhost 18 | { 19 | AuditPolicyOption Integration_Test 20 | { 21 | Name = $OptionName 22 | Value = $OptionValue 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | notify: 3 | require_ci_to_pass: no 4 | 5 | comment: 6 | layout: "reach, diff" 7 | behavior: default 8 | 9 | coverage: 10 | range: 50..80 11 | round: down 12 | precision: 0 13 | 14 | status: 15 | project: 16 | default: 17 | # Set the overall project code coverage requirement to 70% 18 | target: 70 19 | patch: 20 | default: 21 | # Set the pull request requirement to not regress overall coverage by more than 5% 22 | # and let codecov.io set the goal for the code changed in the patch. 23 | target: auto 24 | threshold: 5 25 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicySubcategory/en-US/MSFT_AuditPolicySubcategory.strings.psd1: -------------------------------------------------------------------------------- 1 | ConvertFrom-StringData -StringData @' 2 | InvalidSubcategory = {0} is not a valid Subcategory 3 | GetAuditpolSubcategorySucceed = (GET) '{0}':'{1}' 4 | GetAuditPolSubcategoryFailed = (ERROR) getting '{0}':'{1}' 5 | SetAuditpolSubcategorySucceed = (SET) '{0}' audit '{1}' to '{2}' 6 | SetAuditpolSubcategoryFailed = (ERROR) setting '{0}' audit '{1}' to '{2}' 7 | TestAuditpolSubcategoryCorrect = '{0}':'{1}' is '{2}' 8 | TestAuditpolSubcategoryIncorrect = '{0}':'{1}' is NOT '{2}' 9 | '@ 10 | 11 | -------------------------------------------------------------------------------- /Examples/Sample_AuditPolicyCsv.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This example will apply the audit policy settings in the CSV located at 3 | C:\data\AuditPolBackup.csv to the localhost. 4 | To use this example, run it using PowerShell. 5 | #> 6 | Configuration Sample_AuditPolicyCsv 7 | { 8 | param 9 | ( 10 | [String] $NodeName = 'localhost' 11 | ) 12 | 13 | Import-DscResource -ModuleName AuditPolicyDsc 14 | 15 | Node $NodeName 16 | { 17 | AuditPolicyCsv auditPolicy 18 | { 19 | IsSingleInstance = 'Yes' 20 | CsvPath = "C:\data\AuditPolBackup.csv" 21 | } 22 | } 23 | } 24 | 25 | Sample_AuditPolicyCsv 26 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicySubcategory/MSFT_AuditPolicySubcategory.schema.mof: -------------------------------------------------------------------------------- 1 | 2 | [ClassVersion("1.0.0.0"), FriendlyName("AuditPolicySubcategory")] 3 | class MSFT_AuditPolicySubcategory : OMI_BaseResource 4 | { 5 | [Key, Description("The name of the Subcategory to be configured.")] String Name; 6 | [Key, Description("The audit flag to be configured."), ValueMap{"Success","Failure"}, Values{"Success","Failure"}] String AuditFlag; 7 | [Write, Description("Specifies whether the flag should be enabled or disabled. To enable the flag, set this property to Present. To disable the flag, set this property to Absent."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicyGUID.config.ps1: -------------------------------------------------------------------------------- 1 | configuration 'MSFT_AuditPolicyGUID_Config' 2 | { 3 | param 4 | ( 5 | [Parameter(Mandatory = $true)] 6 | [String] 7 | $Name, 8 | 9 | [Parameter(Mandatory = $true)] 10 | [String] 11 | $AuditFlag, 12 | 13 | [Parameter(Mandatory = $true)] 14 | [String] 15 | $AuditFlagEnsure 16 | ) 17 | 18 | Import-DscResource -ModuleName 'AuditPolicyDsc' 19 | 20 | node localhost 21 | { 22 | AuditPolicyGUID Integration_Test 23 | { 24 | Name = $Name 25 | AuditFlag = $AuditFlag 26 | Ensure = $AuditFlagEnsure 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Resource_proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New resource proposal 3 | about: If you have a new resource proposal that you think should be added to this resource module. 4 | --- 5 | 17 | ### Description 18 | 19 | ### Proposed properties 20 | 21 | ### Special considerations or limitations 22 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyGUID/MSFT_AuditPolicyGUID.schema.mof: -------------------------------------------------------------------------------- 1 | [ClassVersion("1.0.0.0"), FriendlyName("AuditPolicyGUID")] 2 | class MSFT_AuditPolicyGUID : OMI_BaseResource 3 | { 4 | [Key, Description("The name of the Subcategory to be configured.")] String Name; 5 | [Key, Description("The audit flag to be configured."), ValueMap{"Success","Failure", "Success And Failure", "No Auditing"}, Values{"Success","Failure","Success And Failure", "No Auditing"}] String AuditFlag; 6 | [Write, Description("Specifies whether the flag should be enabled or disabled. To enable the flag, set this property to Present. To disable the flag, set this property to Absent."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; 7 | }; 8 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicySubcategory.config.ps1: -------------------------------------------------------------------------------- 1 | 2 | configuration 'MSFT_AuditPolicySubcategory_Config' 3 | { 4 | param 5 | ( 6 | [Parameter(Mandatory = $true)] 7 | [System.String] 8 | $Name, 9 | 10 | [Parameter(Mandatory = $true)] 11 | [System.String] 12 | $AuditFlag, 13 | 14 | [Parameter(Mandatory = $true)] 15 | [System.String] 16 | $AuditFlagEnsure 17 | ) 18 | 19 | Import-DscResource -ModuleName 'AuditPolicyDsc' 20 | 21 | node localhost 22 | { 23 | AuditPolicySubcategory Integration_Test 24 | { 25 | Name = $Name 26 | AuditFlag = $AuditFlag 27 | Ensure = $AuditFlagEnsure 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Examples/Sample_AuditPolicyGuid.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This example will set the Logon Success and Failure flags on the localhost. 3 | To use this example, run it using PowerShell. 4 | #> 5 | Configuration Sample_AuditPolicyGuid 6 | { 7 | param 8 | ( 9 | [String] $NodeName = 'localhost' 10 | ) 11 | 12 | Import-DscResource -ModuleName AuditPolicyDsc 13 | 14 | Node $NodeName 15 | { 16 | AuditPolicyGuid LogonSuccess 17 | { 18 | Name = 'Logon' 19 | AuditFlag = 'Success' 20 | Ensure = 'Absent' 21 | } 22 | 23 | AuditPolicyGuid LogonFailure 24 | { 25 | Name = 'Logon' 26 | AuditFlag = 'Failure' 27 | Ensure = 'Present' 28 | } 29 | } 30 | } 31 | 32 | Sample_AuditPolicyGuid 33 | -------------------------------------------------------------------------------- /Examples/Sample_AuditPolicySubcategory.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This example will set the Logon Success and Failure flags on the localhost. 3 | To use this example, run it using PowerShell. 4 | #> 5 | Configuration Sample_AuditSubcategory 6 | { 7 | param 8 | ( 9 | [String] $NodeName = 'localhost' 10 | ) 11 | 12 | Import-DscResource -ModuleName AuditPolicyDsc 13 | 14 | Node $NodeName 15 | { 16 | AuditPolicySubcategory LogonSuccess 17 | { 18 | Name = 'Logon' 19 | AuditFlag = 'Success' 20 | Ensure = 'Absent' 21 | } 22 | 23 | AuditPolicySubcategory LogonFailure 24 | { 25 | Name = 'Logon' 26 | AuditFlag = 'Failure' 27 | Ensure = 'Present' 28 | } 29 | } 30 | } 31 | 32 | Sample_AuditSubcategory 33 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyGUID/en-US/MSFT_AuditPolicyGUID.strings.psd1: -------------------------------------------------------------------------------- 1 | ConvertFrom-StringData -StringData @' 2 | InvalidSubcategory = {0} is not a valid Subcategory 3 | GetAuditpolSubcategorySucceed = (GET) '{0}':'{1}' 4 | GetAuditPolSubcategoryFailed = (ERROR) getting '{0}':'{1}' 5 | SetAuditpolSubcategorySucceed = (SET) '{0}' audit '{1}' to '{2}' 6 | SetAuditpolSubcategoryFailed = (ERROR) setting '{0}' audit '{1}' to '{2}' 7 | TestAuditpolSubcategoryCorrect = '{0}':'{1}' is '{2}' 8 | TestAuditpolSubcategoryIncorrect = '{0}':'{1}' is NOT '{2}' 9 | AuditSubCategoryGUIDFound = Audit Subcategory '{0}' was found with GUID: '{1}' 10 | AuditSubCategoryGUIDNotFound = Audit Subcategory '{0}' was NOT found with '{0}' 11 | RetrieveSettingFailure = Could not retrieve current setting for {0} 12 | '@ 13 | 14 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | #---------------------------------# 2 | # environment configuration # 3 | #---------------------------------# 4 | 5 | version: 1.1.{build}.0 6 | install: 7 | - git clone https://github.com/PowerShell/DscResource.Tests 8 | - ps: Write-Verbose -Message "PowerShell version $($PSVersionTable.PSVersion)" -Verbose 9 | - ps: Import-Module "$env:APPVEYOR_BUILD_FOLDER\DscResource.Tests\AppVeyor.psm1" 10 | - ps: Invoke-AppveyorInstallTask 11 | 12 | #---------------------------------# 13 | # build configuration # 14 | #---------------------------------# 15 | 16 | build: false 17 | 18 | #---------------------------------# 19 | # test configuration # 20 | #---------------------------------# 21 | 22 | test_script: 23 | - ps: | 24 | Invoke-AppveyorTestScriptTask -CodeCoverage -CodeCovIo 25 | 26 | #---------------------------------# 27 | # deployment configuration # 28 | #---------------------------------# 29 | 30 | # scripts to run before deployment 31 | deploy_script: 32 | - ps: | 33 | Invoke-AppveyorAfterTestTask 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /DSCResources/AuditPolicyResourceHelper/en-US/AuditPolicyResourceHelper.strings.psd1: -------------------------------------------------------------------------------- 1 | ConvertFrom-StringData -StringData @' 2 | AuditpolNotFound = (ERROR) auditpol.exe was not found on the system 3 | RequiredPrivilegeMissing = (ERROR) A required privilege is not held by the client 4 | IncorrectParameter = (ERROR) The parameter is incorrect 5 | UnknownError = (ERROR) An unknown error has occured: {0} 6 | ExecuteAuditpolCommand = Executing 'auditpol.exe {0}' 7 | FileNotFound = {0} Not found 8 | WriteStagedCSV = Audit Subcategory '{1}' was written with flag: '{1}' 9 | RestoredAuditCSV = Audit CSV was successfully restored with auditpol 10 | AuditCSVNotFound = Could not find Audit CSV at '{0}' 11 | AuditCSVOutdated = Audit CSV at '{0}' is outdated ('{1}') 12 | AuditCSVLocked = Audit CSV at '{0}' is LOCKED 13 | AuditCSVDeleted = Audit CSV at '{0}' was DELETED 14 | AuditCSVCreated = Audit CSV at '{0}' was CREATED 15 | CurrentCSVValueMissing = Cannot find current audit value for '{0}' will assume 'No Auditing' 16 | SubCategoryTranlationFailed = Cannot find Subcategory translation for {0} 17 | SaveAuditCSVFailure = Unable to save audit.csv at {0} 18 | '@ 19 | 20 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | limitPerRun: 30 4 | 5 | pulls: 6 | daysUntilStale: 14 7 | daysUntilClose: false 8 | exemptProjects: true 9 | exemptMilestones: true 10 | staleLabel: abandoned 11 | exemptLabels: 12 | - needs review 13 | - on hold 14 | - waiting for CLA pass 15 | 16 | markComment: > 17 | Labeling this pull request (PR) as abandoned since it has gone 14 days or more 18 | since the last update. An abandoned PR can be continued by another contributor. 19 | The abandoned label will be removed if work on this PR is taken up again. 20 | 21 | issues: 22 | daysUntilStale: 30 23 | daysUntilClose: 40 24 | exemptProjects: true 25 | exemptMilestones: true 26 | staleLabel: stale 27 | exemptLabels: 28 | - bug 29 | - enhancement 30 | - tests 31 | - documentation 32 | - resource proposal 33 | - on hold 34 | 35 | markComment: > 36 | This issue has been automatically marked as stale because 37 | it has not had activity from the community in the last 30 days. It will be 38 | closed if no further activity occurs within 10 days. If the issue is labelled 39 | with any of the work labels (e.g bug, enhancement, documentation, or tests) 40 | then the issue will not auto-close. 41 | 42 | closeComment: > 43 | This issue has been automatically closed because it is has not had activity 44 | from the community in the last 40 days. 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Problem_with_resource.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Problem with a resource 3 | about: If you have a problem, bug, or enhancement with a resource in this resource module. 4 | --- 5 | 24 | #### Details of the scenario you tried and the problem that is occurring 25 | 26 | #### Verbose logs showing the problem 27 | 28 | #### Suggested solution to the issue 29 | 30 | #### The DSC configuration that is used to reproduce the issue (as detailed as possible) 31 | ```powershell 32 | # insert configuration here 33 | ``` 34 | 35 | #### The operating system the target node is running 36 | 50 | 51 | #### Version and build of PowerShell the target node is running 52 | 56 | 57 | #### Version of the DSC module that was used ('dev' if using current dev branch) 58 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 14 | #### Pull Request (PR) description 15 | 18 | 19 | #### This Pull Request (PR) fixes the following issues 20 | 27 | 28 | #### Task list 29 | 37 | - [ ] Added an entry under the Unreleased section of the change log in the README.md. 38 | Entry should say what was changed, and how that affects users (if applicable). 39 | - [ ] Resource documentation added/updated in README.md. 40 | - [ ] Resource parameter descriptions added/updated in README.md, schema.mof 41 | and comment-based help. 42 | - [ ] Comment-based help added/updated. 43 | - [ ] Localization strings added/updated in all localization files as appropriate. 44 | - [ ] Examples appropriately added/updated. 45 | - [ ] Unit tests added/updated. See [DSC Resource Testing Guidelines](https://github.com/PowerShell/DscResources/blob/master/TestsGuidelines.md). 46 | - [ ] Integration tests added/updated (where possible). See [DSC Resource Testing Guidelines](https://github.com/PowerShell/DscResources/blob/master/TestsGuidelines.md). 47 | - [ ] New/changed code adheres to [DSC Resource Style Guidelines](https://github.com/PowerShell/DscResources/blob/master/StyleGuidelines.md) and [Best Practices](https://github.com/PowerShell/DscResources/blob/master/BestPractices.md). 48 | -------------------------------------------------------------------------------- /AuditPolicyDsc.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'AuditPolicyDsc' 3 | # 4 | # Generated by: Adam Haynes 5 | # 6 | # Generated on: 12/17/2015 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | # RootModule = '' 13 | 14 | # Version number of this module. 15 | moduleVersion = '1.4.0.0' 16 | 17 | # ID used to uniquely identify this module 18 | GUID = '644501e3-ebc7-451e-9155-366a4f8d4a9a' 19 | 20 | # Author of this module 21 | Author = 'Microsoft Corporation' 22 | 23 | # Company or vendor of this module 24 | CompanyName = 'Microsoft Corporation' 25 | 26 | # Copyright statement for this module 27 | Copyright = '(c) 2016 Microsoft Corporation. All rights reserved.' 28 | 29 | # Description of the functionality provided by this module 30 | Description = 'The AuditPolicyDsc module allows you to configure and manage the advanced audit policy on all currently supported versions of Windows.' 31 | 32 | # Minimum version of the Windows PowerShell engine required by this module 33 | PowerShellVersion = '4.0' 34 | 35 | # Name of the Windows PowerShell host required by this module 36 | # PowerShellHostName = '' 37 | 38 | # Minimum version of the Windows PowerShell host required by this module 39 | # PowerShellHostVersion = '' 40 | 41 | # Minimum version of Microsoft .NET Framework required by this module 42 | # DotNetFrameworkVersion = '' 43 | 44 | # Minimum version of the common language runtime (CLR) required by this module 45 | # CLRVersion = '' 46 | 47 | # Processor architecture (None, X86, Amd64) required by this module 48 | # ProcessorArchitecture = '' 49 | 50 | # Modules that must be imported into the global environment prior to importing this module 51 | # RequiredModules = @() 52 | 53 | # Assemblies that must be loaded prior to importing this module 54 | # RequiredAssemblies = @() 55 | 56 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 57 | # ScriptsToProcess = @() 58 | 59 | # Type files (.ps1xml) to be loaded when importing this module 60 | # TypesToProcess = @() 61 | 62 | # Format files (.ps1xml) to be loaded when importing this module 63 | # FormatsToProcess = @() 64 | 65 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 66 | # NestedModules = @() 67 | 68 | # Functions to export from this module 69 | # FunctionsToExport = '*' 70 | 71 | # Cmdlets to export from this module 72 | # CmdletsToExport = '*' 73 | 74 | # Variables to export from this module 75 | # VariablesToExport = '*' 76 | 77 | # Aliases to export from this module 78 | # AliasesToExport = '*' 79 | 80 | # DSC resources to export from this module 81 | # DscResourcesToExport = @() 82 | 83 | # List of all modules packaged with this module 84 | # ModuleList = @() 85 | 86 | # List of all files packaged with this module 87 | # FileList = @() 88 | 89 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 90 | PrivateData = @{ 91 | 92 | PSData = @{ 93 | 94 | # Tags applied to this module. These help with module discovery in online galleries. 95 | Tags = @( 'DSC','DesiredStateConfiguration','DSCResourceKit','DSCResource','AuditPolicy' ) 96 | 97 | # A URL to the license for this module. 98 | LicenseUri = 'https://github.com/PowerShell/AuditPolicyDsc/blob/master/LICENSE' 99 | 100 | # A URL to the main website for this project. 101 | ProjectUri = 'https://github.com/PowerShell/AuditPolicyDsc' 102 | 103 | # A URL to an icon representing this module. 104 | # IconUri = '' 105 | 106 | # ReleaseNotes of this module 107 | ReleaseNotes = '* Explicitly removed extra hidden files from release package 108 | 109 | ' 110 | 111 | } # End of PSData hashtable 112 | 113 | } # End of PrivateData hashtable 114 | 115 | # HelpInfo URI of this module 116 | # HelpInfoURI = '' 117 | 118 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 119 | # DefaultCommandPrefix = '' 120 | 121 | } 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicyOption.Integration.tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $script:DSCModuleName = 'AuditPolicyDsc' 3 | $script:DSCResourceName = 'MSFT_AuditPolicyOption' 4 | 5 | #region HEADER 6 | # Integration Test Template Version: 1.1.1 7 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) 8 | if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 9 | (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) 10 | { 11 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath '\DSCResource.Tests\')) 12 | } 13 | 14 | Import-Module (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 15 | $TestEnvironment = Initialize-TestEnvironment ` 16 | -DSCModuleName $script:DSCModuleName ` 17 | -DSCResourceName $script:DSCResourceName ` 18 | -TestType Integration 19 | #endregion 20 | 21 | # Set the option details being tested 22 | $optionName = 'AuditBaseDirectories' 23 | 24 | # Using try/finally to always cleanup even if something awful happens. 25 | try 26 | { 27 | #region Integration Tests 28 | $ConfigFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DSCResourceName).config.ps1" 29 | . $ConfigFile 30 | 31 | Describe "$($script:DSCResourceName)_Integration" { 32 | 33 | Context 'Should set option to Enabled' { 34 | 35 | #region DEFAULT TESTS 36 | 37 | # Set the option value to test 38 | $optionValue = 'Enabled' 39 | # Set the test system value to an incorrect state to ensure a valid test. 40 | & 'auditpol' '/set' "/option:$optionName" '/value:disable' 41 | 42 | It 'Should compile and apply the MOF without throwing' { 43 | { 44 | & "$($script:DSCResourceName)_Config" -OptionName $optionName ` 45 | -OptionValue $optionValue ` 46 | -OutputPath $TestDrive 47 | Start-DscConfiguration -Path $TestDrive ` 48 | -ComputerName localhost -Wait -Verbose -Force 49 | } | Should not throw 50 | } 51 | 52 | It 'Should be able to call Get-DscConfiguration without throwing' { 53 | { $script:currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop } | 54 | Should Not throw 55 | } 56 | 57 | #endregion 58 | 59 | It 'Should return the correct option name' { 60 | $script:currentConfig.Name | Should Be $optionName 61 | } 62 | 63 | It 'Should return the correct option value' { 64 | $script:currentConfig.Value | Should Be $optionValue 65 | } 66 | 67 | It 'Should return $true' { 68 | (Test-DscConfiguration -Path $TestDrive).InDesiredState | Should Be $true 69 | } 70 | } 71 | 72 | Context 'Should set option to Disabled' { 73 | 74 | #region DEFAULT TESTS 75 | 76 | # Set the option value to test 77 | $optionValue = 'Disabled' 78 | # Set the system value to an incorrect state to ensure a valid test. 79 | & 'auditpol' '/set' "/option:$optionName" '/value:enable' 80 | 81 | It 'Should compile and apply the MOF without throwing' { 82 | { 83 | & "$($script:DSCResourceName)_Config" -OptionName $optionName ` 84 | -OptionValue $optionValue ` 85 | -OutputPath $TestDrive 86 | Start-DscConfiguration -Path $TestDrive ` 87 | -ComputerName localhost -Wait -Verbose -Force 88 | } | Should not throw 89 | } 90 | 91 | It 'Should be able to call Get-DscConfiguration without throwing' { 92 | { $script:currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop } | 93 | Should Not throw 94 | } 95 | 96 | #endregion 97 | 98 | It 'Should return the correct option name' { 99 | $script:currentConfig.Name | Should Be $optionName 100 | } 101 | 102 | It 'Should return the correct option value' { 103 | $script:currentConfig.Value | Should Be $optionValue 104 | } 105 | 106 | It 'Should return $true' { 107 | (Test-DscConfiguration -Path $TestDrive).InDesiredState | Should Be $true 108 | } 109 | } 110 | } 111 | #endregion 112 | } 113 | finally 114 | { 115 | #region FOOTER 116 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 117 | #endregion 118 | } 119 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicyCsv.integration.tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $script:DSCModuleName = 'AuditPolicyDsc' 3 | $script:DSCResourceName = 'MSFT_AuditPolicyCsv' 4 | 5 | #region HEADER 6 | # Integration Test Template Version: 1.1.1 7 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) 8 | if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 9 | (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) 10 | { 11 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath '\DSCResource.Tests\')) 12 | } 13 | 14 | Import-Module (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 15 | $TestEnvironment = Initialize-TestEnvironment ` 16 | -DSCModuleName $script:DSCModuleName ` 17 | -DSCResourceName $script:DSCResourceName ` 18 | -TestType Integration 19 | #endregion 20 | 21 | # Using try/finally to always cleanup even if something awful happens. 22 | try 23 | { 24 | #region Integration Tests 25 | $ConfigFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DSCResourceName).config.ps1" 26 | . $ConfigFile 27 | 28 | Describe "$($script:DSCResourceName)_Integration" { 29 | 30 | Context 'Should set policy' { 31 | 32 | # set the system Subcategories to the incorect state to ensure a valid test. 33 | & 'auditpol' '/set' "/subcategory:Credential Validation" '/failure:disable' '/Success:enable' 34 | & 'auditpol' '/set' "/subcategory:Other Account Management Events" '/failure:enable' '/Success:disable' 35 | & 'auditpol' '/set' "/subcategory:Logoff" '/failure:enable' '/Success:disable' 36 | & 'auditpol' '/set' "/subcategory:Logon" '/failure:enable' '/Success:enable' 37 | & 'auditpol' '/set' "/subcategory:Special Logon" '/failure:disable' '/Success:enable' 38 | <# 39 | Since the tests read in CSV files, they are stored in a subfolder for the user and 40 | system context to both access. 41 | #> 42 | $csvPath = ([system.IO.Path]::GetTempFileName()).Replace('.tmp','.csv') 43 | 44 | # Create the desired auditpol backup file to test with. 45 | @(@("Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value") 46 | @(",System,Credential Validation,{0cce923f-69ae-11d9-bed3-505054503030},Success and Failure,,3") 47 | @(",System,Other Account Management Events,{0cce923a-69ae-11d9-bed3-505054503030},Success and Failure,,3") 48 | @(",System,Logoff,{0cce9216-69ae-11d9-bed3-505054503030},Success,,1") 49 | @(",System,Logon,{0cce9215-69ae-11d9-bed3-505054503030},Success and Failure,,3") 50 | @(",System,Special Logon,{0cce921b-69ae-11d9-bed3-505054503030},Failure,,2")) | 51 | Out-File $csvPath -Encoding utf8 -Force 52 | #region DEFAULT TESTS 53 | 54 | It 'Should compile and apply the MOF without throwing' { 55 | { 56 | & "$($script:DSCResourceName)_Config" -CsvPath $csvPath ` 57 | -OutputPath $TestDrive 58 | 59 | Start-DscConfiguration -Path $TestDrive ` 60 | -ComputerName localhost -Wait -Verbose -Force 61 | } | Should not throw 62 | } 63 | 64 | It 'Should be able to call Get-DscConfiguration without throwing' { 65 | { $script:currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop } | 66 | Should Not throw 67 | } 68 | 69 | It 'Should have added Failure flag when configured for Success only' { 70 | $auditpolReturn = (& 'auditpol' '/get' '/subcategory:Credential Validation' '/r')[2] 71 | ($auditpolReturn -split ",")[4] | Should Be "Success and Failure" 72 | } 73 | 74 | It 'Should have added Success flag when configured for Failure only' { 75 | $auditpolReturn = (& 'auditpol' '/get' '/subcategory:Other Account Management Events' '/r')[2] 76 | ($auditpolReturn -split ",")[4] | Should Be "Success and Failure" 77 | } 78 | 79 | It 'Should have removed Failure flag and added Success flag' { 80 | $auditpolReturn = (& 'auditpol' '/get' '/subcategory:Logoff' '/r')[2] 81 | ($auditpolReturn -split ",")[4] | Should Be "Success" 82 | } 83 | 84 | It 'Should have removed Success flag and added Failure flag' { 85 | $auditpolReturn = (& 'auditpol' '/get' '/subcategory:Special Logon' '/r')[2] 86 | ($auditpolReturn -split ",")[4] | Should Be "Failure" 87 | } 88 | 89 | It 'Should have not made any changes when configured correctly' { 90 | $auditpolReturn = (& 'auditpol' '/get' '/subcategory:Logon' '/r')[2] 91 | ($auditpolReturn -split ",")[4] | Should Be "Success and Failure" 92 | } 93 | #endregion 94 | } 95 | } 96 | #endregion 97 | } 98 | finally 99 | { 100 | #region FOOTER 101 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 102 | #endregion 103 | } 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AuditPolicyDsc 2 | 3 | The **AuditPolicyDsc** module allows you to configure and manage the advanced audit policy on all 4 | currently supported versions of Windows. 5 | 6 | This project has adopted the [Microsoft Open Source Code of Conduct]( 7 | https://opensource.microsoft.com/codeofconduct/). 8 | For more information see the [Code of Conduct FAQ]( 9 | https://opensource.microsoft.com/codeofconduct/faq/) 10 | or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions 11 | or comments. 12 | 13 | ## Branches 14 | 15 | ### master 16 | 17 | [![Build status](https://ci.appveyor.com/api/projects/status/9nsi30ladk1jaax5/branch/master?svg=true)](https://ci.appveyor.com/project/PowerShell/AuditPolicyDsc/branch/master) 18 | [![codecov](https://codecov.io/gh/PowerShell/AuditPolicyDsc/branch/master/graph/badge.svg)](https://codecov.io/gh/PowerShell/AuditPolicyDsc/branch/master) 19 | 20 | This is the branch containing the latest release - 21 | no contributions should be made directly to this branch. 22 | 23 | ### dev 24 | 25 | [![Build status](https://ci.appveyor.com/api/projects/status/9nsi30ladk1jaax5/branch/master?svg=true)](https://ci.appveyor.com/project/PowerShell/AuditPolicyDsc/branch/dev) 26 | [![codecov](https://codecov.io/gh/PowerShell/AuditPolicyDsc/branch/dev/graph/badge.svg)](https://codecov.io/gh/PowerShell/AuditPolicyDsc/branch/dev) 27 | 28 | This is the development branch 29 | to which contributions should be proposed by contributors as pull requests. 30 | This development branch will periodically be merged to the master branch, 31 | and be released to [PowerShell Gallery](https://www.powershellgallery.com/). 32 | 33 | ## Contributing 34 | 35 | Please check out common DSC Resources [contributing guidelines]( 36 | https://github.com/PowerShell/DscResources/blob/master/CONTRIBUTING.md). 37 | 38 | ## Resources 39 | 40 | * [AuditPolicySubcategory](#AuditPolicySubcategory): Provides a mechanism to manage advanced auditpolicy subcategory audit flags. 41 | 42 | * [AuditPolicyOption](#AuditPolicyOption): Provides a mechanism to manage audit policy options. 43 | 44 | * [AuditPolicyCsv](#AuditPolicyCsv): Provides a mechanism to restore an audit policy backup from a CSV file. 45 | 46 | * [AuditPolicyGUID](#AuditPolicyGuid): Provides a version of AuditPolicySubcategory that works around localization issues with auditpol. 47 | 48 | ### AuditPolicySubcategory 49 | 50 | Provides a mechanism to manage advanced audit policy subcategory audit flags. 51 | This resource works on Nano Server. 52 | 53 | #### Requirements 54 | 55 | None 56 | 57 | #### Parameters 58 | 59 | * **[String] Name _(Key)_**: The name of the subcategory in the advanced audit policy to manage. 60 | 61 | * **[String] AuditFlag _(Key)_**: The name of the audit flag to apply to the subcategory. { Success | Failure }. 62 | 63 | * **[String] Ensure _(Write)_**: Indicates whether the service is present or absent. Defaults to Present. { *Present* | Absent }. 64 | 65 | #### Read-Only Properties from Get-TargetResource 66 | 67 | None 68 | 69 | #### Examples 70 | 71 | * [Set Audit Policy Subcategory Audit Flags]( 72 | https://github.com/PowerShell/AuditPolicyDsc/blob/master/Examples/Sample_AuditPolicySubcategory.ps1) 73 | 74 | ### AuditPolicyOption 75 | 76 | Provides a mechanism to manage audit policy options. 77 | This resource works on Nano Server. 78 | 79 | #### Requirements 80 | 81 | None 82 | 83 | #### Parameters 84 | 85 | * **[String] Name _(Key)_**: The name of the option to configure. 86 | 87 | * **[String] Value _(Key)_**: The value to apply to the option. { Enabled | Disabled }. 88 | 89 | #### Read-Only Properties from Get-TargetResource 90 | 91 | None 92 | 93 | #### Examples 94 | 95 | * [Set Audit Policy Option]( 96 | https://github.com/PowerShell/AuditPolicyDsc/blob/master/Examples/Sample_AuditPolicyOption.ps1) 97 | 98 | ### AuditPolicyCsv 99 | 100 | Provides a mechanism to restore an audit policy backup. 101 | This resource works on Nano Server. 102 | 103 | #### Requirements 104 | 105 | None 106 | 107 | #### Parameters 108 | 109 | * **[String] CsvPath _(Required)_**: The path to the CSV file to apply to the node. 110 | 111 | * **[String] IsSingleInstance _(Key)_**: Specifies if the resource is a single instance, the value must be 'Yes'. 112 | 113 | #### Read-Only Properties from Get-TargetResource 114 | 115 | None 116 | 117 | #### Examples 118 | 119 | * [Apply audit policy backup from a CSV file]( 120 | https://github.com/PowerShell/AuditPolicyDsc/blob/master/Examples/Sample_AuditPolicyCsv.ps1) 121 | 122 | ### AuditPolicyGuid 123 | 124 | Provides a version of AuditPolicySubcategory that works around localization issues with auditpol. 125 | 126 | #### Requirements 127 | 128 | None 129 | 130 | #### Parameters 131 | 132 | * **[String] Name _(Key)_**: The name of the subcategory in the advanced audit policy to manage. 133 | 134 | * **[String] AuditFlag _(Key)_**: The name of the audit flag to apply to the subcategory. { Success | Failure }. 135 | 136 | * **[String] Ensure _(Write)_**: Indicates whether the service is present or absent. Defaults to Present. { *Present* | Absent }. 137 | 138 | #### Read-Only Properties from Get-TargetResource 139 | 140 | None 141 | 142 | #### Examples 143 | 144 | * [Set Audit Policy Subcategory Audit Flags]( 145 | https://github.com/PowerShell/AuditPolicyDsc/blob/master/Examples/Sample_AuditPolicyGuid.ps1) 146 | 147 | ## Versions 148 | 149 | ### Unreleased 150 | 151 | ### 1.4.0.0 152 | 153 | * Explicitly removed extra hidden files from release package 154 | 155 | ### 1.3.0.0 156 | 157 | * Update LICENSE file to match the Microsoft Open Source Team standard. 158 | * Added the AuditPolicyGuid resource. 159 | 160 | ### 1.2.0.0 161 | 162 | * Moved auditpol call in the helper module to an external process to better control output 163 | * auditpol output is now converted to CSV to remove the need to parse the text output 164 | * All resources have been updated to use the new helper module functionality 165 | * Added the Ensure parameter default value of Present to the AuditPolicySubcategory resource Test-TargetResource function 166 | 167 | ### 1.1.0.0 168 | 169 | * Added the AuditPolicyCsv resource. 170 | 171 | ### 1.0.0.0 172 | 173 | * Initial release with the following resources: 174 | 175 | * AuditPolicySubcategory 176 | * AuditPolicyOption 177 | -------------------------------------------------------------------------------- /Tests/Unit/audit.csv: -------------------------------------------------------------------------------- 1 | Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value 2 | BIRDSOFPRAY,System,IPsec Driver,{0CCE9213-69AE-11D9-BED3-505054503030},No Auditing,,0 3 | BIRDSOFPRAY,System,System Integrity,{0CCE9212-69AE-11D9-BED3-505054503030},Success and Failure,,3 4 | BIRDSOFPRAY,System,Security System Extension,{0CCE9211-69AE-11D9-BED3-505054503030},Success and Failure,,3 5 | BIRDSOFPRAY,System,Security State Change,{0CCE9210-69AE-11D9-BED3-505054503030},Success and Failure,,3 6 | BIRDSOFPRAY,System,Other System Events,{0CCE9214-69AE-11D9-BED3-505054503030},Success and Failure,,3 7 | BIRDSOFPRAY,System,Group Membership,{0CCE9249-69AE-11D9-BED3-505054503030},No Auditing,,0 8 | BIRDSOFPRAY,System,User / Device Claims,{0CCE9247-69AE-11D9-BED3-505054503030},No Auditing,,0 9 | BIRDSOFPRAY,System,Network Policy Server,{0CCE9243-69AE-11D9-BED3-505054503030},No Auditing,,0 10 | BIRDSOFPRAY,System,Other Logon/Logoff Events,{0CCE921C-69AE-11D9-BED3-505054503030},Success and Failure,,3 11 | BIRDSOFPRAY,System,Special Logon,{0CCE921B-69AE-11D9-BED3-505054503030},Success and Failure,,3 12 | BIRDSOFPRAY,System,IPsec Extended Mode,{0CCE921A-69AE-11D9-BED3-505054503030},Success and Failure,,3 13 | BIRDSOFPRAY,System,IPsec Quick Mode,{0CCE9219-69AE-11D9-BED3-505054503030},Success and Failure,,3 14 | BIRDSOFPRAY,System,IPsec Main Mode,{0CCE9218-69AE-11D9-BED3-505054503030},Success and Failure,,3 15 | BIRDSOFPRAY,System,Account Lockout,{0CCE9217-69AE-11D9-BED3-505054503030},No Auditing,,0 16 | BIRDSOFPRAY,System,Logoff,{0CCE9216-69AE-11D9-BED3-505054503030},Success,,1 17 | BIRDSOFPRAY,System,Logon,{0CCE9215-69AE-11D9-BED3-505054503030},Success and Failure,,3 18 | BIRDSOFPRAY,System,Handle Manipulation,{0CCE9223-69AE-11D9-BED3-505054503030},No Auditing,,0 19 | BIRDSOFPRAY,System,Central Policy Staging,{0CCE9246-69AE-11D9-BED3-505054503030},No Auditing,,0 20 | BIRDSOFPRAY,System,Removable Storage,{0CCE9245-69AE-11D9-BED3-505054503030},No Auditing,,0 21 | BIRDSOFPRAY,System,Detailed File Share,{0CCE9244-69AE-11D9-BED3-505054503030},No Auditing,,0 22 | BIRDSOFPRAY,System,Other Object Access Events,{0CCE9227-69AE-11D9-BED3-505054503030},Success and Failure,,3 23 | BIRDSOFPRAY,System,Filtering Platform Connection,{0CCE9226-69AE-11D9-BED3-505054503030},No Auditing,,0 24 | BIRDSOFPRAY,System,Filtering Platform Packet Drop,{0CCE9225-69AE-11D9-BED3-505054503030},No Auditing,,0 25 | BIRDSOFPRAY,System,File Share,{0CCE9224-69AE-11D9-BED3-505054503030},Success and Failure,,3 26 | BIRDSOFPRAY,System,Application Generated,{0CCE9222-69AE-11D9-BED3-505054503030},Success and Failure,,3 27 | BIRDSOFPRAY,System,Certification Services,{0CCE9221-69AE-11D9-BED3-505054503030},Success and Failure,,3 28 | BIRDSOFPRAY,System,SAM,{0CCE9220-69AE-11D9-BED3-505054503030},Success and Failure,,3 29 | BIRDSOFPRAY,System,Kernel Object,{0CCE921F-69AE-11D9-BED3-505054503030},Success and Failure,,3 30 | BIRDSOFPRAY,System,Registry,{0CCE921E-69AE-11D9-BED3-505054503030},Success and Failure,,3 31 | BIRDSOFPRAY,System,File System,{0CCE921D-69AE-11D9-BED3-505054503030},Success and Failure,,3 32 | BIRDSOFPRAY,System,Other Privilege Use Events,{0CCE922A-69AE-11D9-BED3-505054503030},No Auditing,,0 33 | BIRDSOFPRAY,System,Non Sensitive Privilege Use,{0CCE9229-69AE-11D9-BED3-505054503030},No Auditing,,0 34 | BIRDSOFPRAY,System,Sensitive Privilege Use,{0CCE9228-69AE-11D9-BED3-505054503030},Success,,1 35 | BIRDSOFPRAY,System,RPC Events,{0CCE922E-69AE-11D9-BED3-505054503030},Success and Failure,,3 36 | BIRDSOFPRAY,System,Token Right Adjusted Events,{0CCE924A-69AE-11D9-BED3-505054503030},No Auditing,,0 37 | BIRDSOFPRAY,System,Process Creation,{0CCE922B-69AE-11D9-BED3-505054503030},Success and Failure,,3 38 | BIRDSOFPRAY,System,Process Termination,{0CCE922C-69AE-11D9-BED3-505054503030},Success and Failure,,3 39 | BIRDSOFPRAY,System,Plug and Play Events,{0CCE9248-69AE-11D9-BED3-505054503030},No Auditing,,0 40 | BIRDSOFPRAY,System,DPAPI Activity,{0CCE922D-69AE-11D9-BED3-505054503030},No Auditing,,0 41 | BIRDSOFPRAY,System,Other Policy Change Events,{0CCE9234-69AE-11D9-BED3-505054503030},Failure,,2 42 | BIRDSOFPRAY,System,Authentication Policy Change,{0CCE9230-69AE-11D9-BED3-505054503030},Success and Failure,,3 43 | BIRDSOFPRAY,System,Audit Policy Change,{0CCE922F-69AE-11D9-BED3-505054503030},Success and Failure,,3 44 | BIRDSOFPRAY,System,Filtering Platform Policy Change,{0CCE9233-69AE-11D9-BED3-505054503030},No Auditing,,0 45 | BIRDSOFPRAY,System,Authorization Policy Change,{0CCE9231-69AE-11D9-BED3-505054503030},Success and Failure,,3 46 | BIRDSOFPRAY,System,MPSSVC Rule-Level Policy Change,{0CCE9232-69AE-11D9-BED3-505054503030},Success and Failure,,3 47 | BIRDSOFPRAY,System,Other Account Management Events,{0CCE923A-69AE-11D9-BED3-505054503030},Success and Failure,,3 48 | BIRDSOFPRAY,System,Application Group Management,{0CCE9239-69AE-11D9-BED3-505054503030},Success and Failure,,3 49 | BIRDSOFPRAY,System,Distribution Group Management,{0CCE9238-69AE-11D9-BED3-505054503030},Success and Failure,,3 50 | BIRDSOFPRAY,System,Security Group Management,{0CCE9237-69AE-11D9-BED3-505054503030},Success and Failure,,3 51 | BIRDSOFPRAY,System,Computer Account Management,{0CCE9236-69AE-11D9-BED3-505054503030},Success and Failure,,3 52 | BIRDSOFPRAY,System,User Account Management,{0CCE9235-69AE-11D9-BED3-505054503030},Success and Failure,,3 53 | BIRDSOFPRAY,System,Directory Service Replication,{0CCE923D-69AE-11D9-BED3-505054503030},No Auditing,,0 54 | BIRDSOFPRAY,System,Directory Service Access,{0CCE923B-69AE-11D9-BED3-505054503030},No Auditing,,0 55 | BIRDSOFPRAY,System,Detailed Directory Service Replication,{0CCE923E-69AE-11D9-BED3-505054503030},No Auditing,,0 56 | BIRDSOFPRAY,System,Directory Service Changes,{0CCE923C-69AE-11D9-BED3-505054503030},No Auditing,,0 57 | BIRDSOFPRAY,System,Other Account Logon Events,{0CCE9241-69AE-11D9-BED3-505054503030},Success and Failure,,3 58 | BIRDSOFPRAY,System,Kerberos Service Ticket Operations,{0CCE9240-69AE-11D9-BED3-505054503030},Success and Failure,,3 59 | BIRDSOFPRAY,System,Credential Validation,{0CCE923F-69AE-11D9-BED3-505054503030},Success and Failure,,3 60 | BIRDSOFPRAY,System,Kerberos Authentication Service,{0CCE9242-69AE-11D9-BED3-505054503030},Success and Failure,,3 61 | BIRDSOFPRAY,,Option:CrashOnAuditFail,,Disabled,,0 62 | BIRDSOFPRAY,,Option:FullPrivilegeAuditing,,Disabled,,0 63 | BIRDSOFPRAY,,Option:AuditBaseObjects,,Disabled,,0 64 | BIRDSOFPRAY,,Option:AuditBaseDirectories,,Disabled,,0 65 | BIRDSOFPRAY,,FileGlobalSacl,,,, 66 | BIRDSOFPRAY,,RegistryGlobalSacl,,,, 67 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyOption/MSFT_AuditPolicyOption.psm1: -------------------------------------------------------------------------------- 1 | Import-Module -Name (Join-Path -Path ( Split-Path $PSScriptRoot -Parent ) ` 2 | -ChildPath 'AuditPolicyResourceHelper\AuditPolicyResourceHelper.psm1') ` 3 | -Force 4 | 5 | # Localized messages for Write-Verbose statements in this resource 6 | $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_AuditPolicyOption' 7 | 8 | <# 9 | .SYNOPSIS 10 | Gets the value of the audit policy option. 11 | .PARAMETER Name 12 | Specifies the option to get. 13 | .PARAMETER Value 14 | Not used in Get-TargetResource. 15 | #> 16 | function Get-TargetResource 17 | { 18 | [CmdletBinding()] 19 | [OutputType([Hashtable])] 20 | param 21 | ( 22 | [Parameter(Mandatory = $true)] 23 | [ValidateSet('CrashOnAuditFail', 'FullPrivilegeAuditing', 'AuditBaseObjects', 24 | 'AuditBaseDirectories')] 25 | [String] 26 | $Name, 27 | 28 | [Parameter(Mandatory = $true)] 29 | [ValidateSet('Enabled', 'Disabled')] 30 | [String] 31 | $Value 32 | ) 33 | 34 | # Get the option's current value 35 | $optionValue = Get-AuditOption -Name $Name 36 | 37 | Write-Verbose -Message ( $localizedData.GetAuditpolOptionSucceed -f $Name ) 38 | 39 | return @{ 40 | Name = $Name 41 | Value = $optionValue 42 | } 43 | } 44 | 45 | <# 46 | .SYNOPSIS 47 | Sets the value of the audit policy option. 48 | .PARAMETER Name 49 | Specifies the option to set. 50 | .PARAMETER Value 51 | Specifies the value to set the option to. 52 | #> 53 | function Set-TargetResource 54 | { 55 | [CmdletBinding()] 56 | param 57 | ( 58 | [Parameter(Mandatory = $true)] 59 | [ValidateSet('CrashOnAuditFail', 'FullPrivilegeAuditing', 'AuditBaseObjects', 60 | 'AuditBaseDirectories')] 61 | [String] 62 | $Name, 63 | 64 | [Parameter(Mandatory = $true)] 65 | [ValidateSet('Enabled', 'Disabled')] 66 | [String] 67 | $Value 68 | ) 69 | 70 | try 71 | { 72 | Set-AuditOption -Name $Name -Value $Value 73 | Write-Verbose -Message ( $localizedData.SetAuditpolOptionSucceed -f $Name, $Value ) 74 | } 75 | catch 76 | { 77 | Write-Verbose -Message ( $localizedData.SetAuditpolOptionFailed -f $Name, $Value ) 78 | } 79 | } 80 | 81 | <# 82 | .SYNOPSIS 83 | Tests that the audit policy option is in the desired state 84 | .PARAMETER Name 85 | Specifies the option to test. 86 | .PARAMETER Value 87 | Specifies the value to test against the option. 88 | #> 89 | function Test-TargetResource 90 | { 91 | [CmdletBinding()] 92 | [OutputType([System.Boolean])] 93 | param 94 | ( 95 | [Parameter(Mandatory = $true)] 96 | [ValidateSet('CrashOnAuditFail', 'FullPrivilegeAuditing', 'AuditBaseObjects', 97 | 'AuditBaseDirectories')] 98 | [String] 99 | $Name, 100 | 101 | [Parameter(Mandatory = $true)] 102 | [ValidateSet('Enabled', 'Disabled')] 103 | [String] 104 | $Value 105 | ) 106 | 107 | if ( ( Get-AuditOption -Name $Name ) -eq $Value ) 108 | { 109 | Write-Verbose -Message ( $localizedData.TestAuditpolOptionCorrect -f $Name, $value ) 110 | return $true 111 | } 112 | else 113 | { 114 | Write-Verbose -Message ( $localizedData.TestAuditpolOptionIncorrect -f $Name, $value ) 115 | return $false 116 | } 117 | } 118 | 119 | #--------------------------------------------------------------------------------------------------- 120 | # Support functions to handle auditpol I/O 121 | 122 | <# 123 | .SYNOPSIS 124 | Gets the audit policy option state. 125 | .DESCRIPTION 126 | Ths is one of the public functions that calls into Get-AuditOptionCommand. 127 | This function enforces parameters that will be passed through to the 128 | Get-AuditOptionCommand function and aligns to a specifc parameterset. 129 | .PARAMETER Option 130 | The name of an audit option. 131 | .OUTPUTS 132 | A string that is the state of the option (Enabled|Disables). 133 | #> 134 | function Get-AuditOption 135 | { 136 | [CmdletBinding()] 137 | [OutputType([String])] 138 | param 139 | ( 140 | [Parameter(Mandatory = $true)] 141 | [String] 142 | $Name 143 | ) 144 | <# 145 | When PowerShell cmdlets are released for individual audit policy settings a condition 146 | will be placed here to use native PowerShell cmdlets to set the option details. 147 | #> 148 | # Get the converted auditpol csv object 149 | $auditOption = Invoke-AuditPol -Command "Get" -SubCommand "Option:$Name" 150 | 151 | # The option value is stored in the 'Inclusion Setting' property of the output CSV. 152 | return $auditOption.'Inclusion Setting' 153 | } 154 | 155 | <# 156 | .SYNOPSIS 157 | Sets an audit policy option to enabled or disabled. 158 | .DESCRIPTION 159 | This public function calls Set-AuditOptionCommand and enforces parameters 160 | that will be passed to Set-AuditOptionCommand and aligns to a specifc parameterset. 161 | .PARAMETER Name 162 | The specific option to set. 163 | .PARAMETER Value 164 | The value to set the provided option to. 165 | #> 166 | function Set-AuditOption 167 | { 168 | [CmdletBinding(SupportsShouldProcess = $true)] 169 | param 170 | ( 171 | [Parameter(Mandatory = $true)] 172 | [String] 173 | $Name, 174 | 175 | [Parameter(Mandatory = $true)] 176 | [String] 177 | $Value 178 | ) 179 | 180 | <# 181 | When PowerShell cmdlets are released for individual audit policy settings a condition 182 | will be placed here to use native PowerShell cmdlets to set the option details. 183 | #> 184 | if ( $pscmdlet.ShouldProcess( "$Name","Set $Value" ) ) 185 | { 186 | <# 187 | The output text of auditpol is in simple past tense, but the input is in simple 188 | present tense, so the hashtable converts the input accordingly. 189 | #> 190 | $pastToPresentValues = @{ 191 | 'Enabled' = 'enable' 192 | 'Disabled' = 'disable' 193 | } 194 | 195 | [String[]] $subCommand = @( "Option:$Name", "/value:$($pastToPresentValues[$value])" ) 196 | 197 | Invoke-AuditPol -Command 'Set' -SubCommand $subCommand | Out-Null 198 | } 199 | } 200 | 201 | Export-ModuleMember -Function *-TargetResource 202 | -------------------------------------------------------------------------------- /Tests/Integration/AuditPolicyResourceHelper.Integration.Tests.ps1: -------------------------------------------------------------------------------- 1 | #requires -RunAsAdministrator 2 | 3 | # Get the root path of the resourse 4 | [String] $script:moduleRoot = Split-Path -Parent ( Split-Path -Parent $PSScriptRoot ) 5 | 6 | Import-Module -Name (Join-Path -Path $moduleRoot ` 7 | -ChildPath 'DSCResources\AuditPolicyResourceHelper\AuditPolicyResourceHelper.psm1' ) ` 8 | -Force 9 | #region Generate data 10 | 11 | <# 12 | The auditpol utility outputs the list of categories and subcategories in a couple of different 13 | ways. Using the /list flag only returns the categories without the associated audit setting, 14 | so it is easier to filter later on. 15 | #> 16 | 17 | $script:subcategories = auditpol /get /category:* /R | ConvertFrom-Csv 18 | 19 | #endregion 20 | 21 | Describe 'Prerequisites' { 22 | 23 | # There are several dependencies for both Pester and AuditPolicyDsc that need to be validated. 24 | It "Should be running as admin" { 25 | # The tests need to run as admin to have access to the auditpol data 26 | ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(` 27 | [Security.Principal.WindowsBuiltInRole] "Administrator") | Should Be $true 28 | } 29 | 30 | It "Should find auditpol.exe in System32" { 31 | # If the auditpol is not located on the system, the entire module will fail 32 | Test-Path "$env:SystemRoot\system32\auditpol.exe" | Should Be $true 33 | } 34 | } 35 | 36 | Describe 'auditpol.exe output' { 37 | 38 | # Verify the raw auditpol output format has not changed across different OS versions and types. 39 | It 'Should get auditpol default return with no parameters' { 40 | ( auditpol.exe )[0] | Should BeExactly 'Usage: AuditPol command []' 41 | } 42 | 43 | It 'Should get CSV format with the /r switch' { 44 | ( auditpol.exe /get /subcategory:logon /r )[0] | 45 | Should BeExactly "Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting" 46 | } 47 | 48 | foreach ( $subcategory in $script:subcategories ) 49 | { 50 | Context "Subcategory: $($subcategory.subcategory)" { 51 | 52 | $auditpolSubcategory = auditpol.exe /get /subcategory:$($subcategory.subcategory) /r | ConvertFrom-Csv 53 | 54 | It 'Should return the subcategory name' { 55 | $auditpolSubcategory.subcategory | Should Be $subcategory.subcategory 56 | } 57 | It 'Should return the subcategory GUID' { 58 | $auditpolSubcategory.'subcategory GUID' | Should Be $subcategory.'subcategory GUID' 59 | } 60 | It 'Should return the Inclusion Setting' { 61 | $auditpolSubcategory.'Inclusion Setting' | Should Be $subcategory.'Inclusion Setting' 62 | } 63 | } 64 | } 65 | } 66 | 67 | Describe "Function Invoke-Auditpol" { 68 | 69 | InModuleScope AuditPolicyResourceHelper { 70 | 71 | Context 'Subcategory and Option' { 72 | 73 | # These tests verify that an object is returned from Invoke-Auditpol 74 | It 'Should return an object when a single word subcategory is passed in' { 75 | $subcategory = Invoke-Auditpol -Command "Get" -SubCommand "Subcategory:Logoff" 76 | $subcategory.Subcategory | Should Be 'Logoff' 77 | $subcategory.'Subcategory GUID' | Should Not BeNullOrEmpty 78 | $subcategory.'Inclusion Setting' | Should Not BeNullOrEmpty 79 | } 80 | 81 | It 'Should return an object when a multi-word subcategory is passed in' { 82 | $subcategory = Invoke-Auditpol -Command "Get" -SubCommand "Subcategory:""Credential Validation""" 83 | $subcategory.Subcategory | Should Be 'Credential Validation' 84 | $subcategory.'Subcategory GUID' | Should Not BeNullOrEmpty 85 | $subcategory.'Inclusion Setting' | Should Not BeNullOrEmpty 86 | } 87 | 88 | It 'Should return an object when an option is passed in' { 89 | $option = Invoke-Auditpol -Command "Get" -SubCommand "option:CrashOnAuditFail" 90 | $option.Subcategory | Should Be 'option:CrashOnAuditFail' 91 | $option.'Subcategory GUID' | Should BeNullOrEmpty 92 | $option.'Inclusion Setting' | Should Not BeNullOrEmpty 93 | } 94 | } 95 | 96 | Context 'Backup' { 97 | 98 | $script:path = ([system.IO.Path]::GetTempFileName()).Replace('tmp','csv') 99 | 100 | It 'Should be able to call Invoke-Audtipol with backup and not throw' { 101 | {$script:auditpolBackupReturn = Invoke-AuditPol -Command 'Backup' ` 102 | -SubCommand "file:$script:path"} | 103 | Should Not Throw 104 | } 105 | 106 | It 'Should not return anything when a backup is requested' { 107 | $script:auditpolBackupReturn | Should BeNullOrEmpty 108 | } 109 | 110 | It 'Should produce a valid CSV in a temp file when the backup switch is used' { 111 | (Get-Content -Path $script:path)[0] | 112 | Should BeExactly "Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value" 113 | } 114 | } 115 | 116 | Context 'Restore' { 117 | 118 | It 'Should be able to call Invoke-Audtipol with backup and not throw' { 119 | {$script:auditpolRestoreReturn = Invoke-AuditPol -Command 'Restore' ` 120 | -SubCommand "file:$script:path"} | 121 | Should Not Throw 122 | } 123 | 124 | It 'Should not return anything when a restore is requested' { 125 | $script:auditpolRestoreReturn | Should BeNullOrEmpty 126 | } 127 | } 128 | } 129 | } 130 | 131 | Describe 'Test-ValidSubcategory' { 132 | 133 | InModuleScope AuditPolicyResourceHelper { 134 | 135 | Context 'Invalid Input' { 136 | 137 | It 'Should not throw an exception' { 138 | { $script:testValidSubcategoryResult = Test-ValidSubcategory -Name 'Invalid' } | 139 | Should Not Throw 140 | } 141 | 142 | It 'Should return false when an invalid Subcategory is passed ' { 143 | $script:testValidSubcategoryResult | Should Be $false 144 | } 145 | } 146 | 147 | Context 'Valid Input' { 148 | 149 | It 'Should not throw an exception' { 150 | { $script:testValidSubcategoryResult = Test-ValidSubcategory -Name 'logon' } | 151 | Should Not Throw 152 | } 153 | 154 | It 'Should return true when a valid Subcategory is passed ' { 155 | $script:testValidSubcategoryResult | Should Be $true 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicyGUID.Integration.tests.ps1: -------------------------------------------------------------------------------- 1 | $script:DSCModuleName = 'AuditPolicyDsc' 2 | $script:DSCResourceName = 'MSFT_AuditPolicyGUID' 3 | 4 | #region HEADER 5 | # Integration Test Template Version: 1.1.1 6 | 7 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) 8 | if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 9 | (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1')))) 10 | { 11 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath '\DSCResource.Tests\')) 12 | } 13 | 14 | Import-Module (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 15 | $TestEnvironment = Initialize-TestEnvironment ` 16 | -DSCModuleName $script:DSCModuleName ` 17 | -DSCResourceName $script:DSCResourceName ` 18 | -TestType Integration 19 | #endregion 20 | 21 | # set the subcategory details being tested 22 | $script:subCategory = 'Credential Validation' 23 | # Using try/finally to always cleanup even if something awful happens. 24 | try 25 | { 26 | #region Integration Tests 27 | $ConfigFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DSCResourceName).config.ps1" 28 | . $ConfigFile 29 | 30 | Describe "$($script:DSCResourceName)_Integration" { 31 | 32 | Context 'Should enable failure audit flag' { 33 | #region DEFAULT TESTS 34 | 35 | $auditFlag = 'Failure' 36 | $auditFlagEnsure = 'Present' 37 | 38 | # set the system Subcategory to the incorrect state to ensure a valid test. 39 | & 'auditpol' '/set' "/subcategory:$subCategory" '/failure:disable' 40 | 41 | It 'Should compile without throwing' { 42 | { 43 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 44 | -AuditFlag $auditFlag ` 45 | -AuditFlagEnsure $auditFlagEnsure ` 46 | -OutputPath $TestDrive 47 | Start-DscConfiguration -Path $TestDrive ` 48 | -ComputerName localhost -Wait -Verbose -Force 49 | } | Should Not Throw 50 | } 51 | 52 | It 'Should be able to call Get-DscConfiguration without throwing' { 53 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not Throw 54 | } 55 | #endregion 56 | 57 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 58 | 59 | It 'Should return the correct configuration' { 60 | 61 | $currentConfig.Name | Should Be $subCategory 62 | $currentConfig.AuditFlag | Should Be $auditFlag 63 | $currentConfig.Ensure | Should Be $auditFlagEnsure 64 | } 65 | } 66 | 67 | Context 'Should disable failure audit flag' { 68 | #region DEFAULT TESTS 69 | 70 | $auditFlag = 'Failure' 71 | $auditFlagEnsure = 'Absent' 72 | 73 | # set the system Subcategory to the incorrect state to ensure a valid test. 74 | & 'auditpol' '/set' "/subcategory:$subCategory" '/failure:enable' 75 | 76 | It 'Should compile without throwing' { 77 | { 78 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 79 | -AuditFlag $auditFlag ` 80 | -AuditFlagEnsure $auditFlagEnsure ` 81 | -OutputPath $TestDrive 82 | Start-DscConfiguration -Path $TestDrive ` 83 | -ComputerName localhost -Wait -Verbose -Force 84 | } | Should not throw 85 | } 86 | 87 | It 'Should be able to call Get-DscConfiguration without throwing' { 88 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw 89 | } 90 | #endregion 91 | 92 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 93 | 94 | It 'Should return the correct configuration' { 95 | 96 | $currentConfig.Name | Should Be $subCategory 97 | $currentConfig.AuditFlag | Should Not Be $auditFlag 98 | $currentConfig.Ensure | Should Be $auditFlagEnsure 99 | } 100 | } 101 | 102 | Context 'Should enable success audit flag' { 103 | #region DEFAULT TESTS 104 | 105 | $auditFlag = 'Success' 106 | $auditFlagEnsure = 'Present' 107 | 108 | # set the system Subcategory to the incorrect state to ensure a valid test. 109 | & 'auditpol' '/set' "/subcategory:$subCategory" '/success:disable' 110 | 111 | It 'Should compile without throwing' { 112 | { 113 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 114 | -AuditFlag $auditFlag ` 115 | -AuditFlagEnsure $auditFlagEnsure ` 116 | -OutputPath $TestDrive 117 | Start-DscConfiguration -Path $TestDrive ` 118 | -ComputerName localhost -Wait -Verbose -Force 119 | } | Should not throw 120 | } 121 | 122 | It 'Should be able to call Get-DscConfiguration without throwing' { 123 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw 124 | } 125 | #endregion 126 | 127 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 128 | 129 | It 'Should return the correct configuration' { 130 | 131 | $currentConfig.Name | Should Be $subCategory 132 | $currentConfig.AuditFlag | Should Be $auditFlag 133 | $currentConfig.Ensure | Should Be $auditFlagEnsure 134 | } 135 | } 136 | 137 | Context 'Should disable success audit flag' { 138 | #region DEFAULT TESTS 139 | 140 | $auditFlag = 'Success' 141 | $auditFlagEnsure = 'Absent' 142 | 143 | # set the system Subcategory to the incorrect state to ensure a valid test. 144 | & 'auditpol' '/set' "/subcategory:$subCategory" '/success:enable' 145 | 146 | It 'Should compile without throwing' { 147 | { 148 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 149 | -AuditFlag $auditFlag ` 150 | -AuditFlagEnsure $auditFlagEnsure ` 151 | -OutputPath $TestDrive 152 | Start-DscConfiguration -Path $TestDrive ` 153 | -ComputerName localhost -Wait -Verbose -Force 154 | } | Should not throw 155 | } 156 | 157 | It 'Should be able to call Get-DscConfiguration without throwing' { 158 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw 159 | } 160 | #endregion 161 | 162 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 163 | 164 | It 'Should return the correct configuration' { 165 | 166 | $currentConfig.Name | Should Be $subCategory 167 | $currentConfig.AuditFlag | Should Not Be $auditFlag 168 | $currentConfig.Ensure | Should Be $auditFlagEnsure 169 | } 170 | } 171 | } 172 | #endregion 173 | } 174 | finally 175 | { 176 | #region FOOTER 177 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 178 | #endregion 179 | } 180 | -------------------------------------------------------------------------------- /Tests/Integration/MSFT_AuditPolicySubcategory.Integration.tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $script:DSCModuleName = 'AuditPolicyDsc' 3 | $script:DSCResourceName = 'MSFT_AuditPolicySubcategory' 4 | 5 | #region HEADER 6 | # Integration Test Template Version: 1.1.1 7 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) 8 | if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 9 | (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) 10 | { 11 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath '\DSCResource.Tests\')) 12 | } 13 | 14 | Import-Module (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 15 | $TestEnvironment = Initialize-TestEnvironment ` 16 | -DSCModuleName $script:DSCModuleName ` 17 | -DSCResourceName $script:DSCResourceName ` 18 | -TestType Integration 19 | #endregion 20 | 21 | # set the subcategory details being tested 22 | $script:subCategory = 'Credential Validation' 23 | 24 | # Using try/finally to always cleanup even if something awful happens. 25 | try 26 | { 27 | #region Integration Tests 28 | $ConfigFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DSCResourceName).config.ps1" 29 | . $ConfigFile 30 | 31 | Describe "$($script:DSCResourceName)_Integration" { 32 | 33 | Context 'Should enable failure audit flag' { 34 | #region DEFAULT TESTS 35 | 36 | $auditFlag = 'Failure' 37 | $auditFlagEnsure = 'Present' 38 | 39 | # set the system Subcategory to the incorrect state to ensure a valid test. 40 | & 'auditpol' '/set' "/subcategory:$subCategory" '/failure:disable' 41 | 42 | It 'Should compile without throwing' { 43 | { 44 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 45 | -AuditFlag $auditFlag ` 46 | -AuditFlagEnsure $auditFlagEnsure ` 47 | -OutputPath $TestDrive 48 | Start-DscConfiguration -Path $TestDrive ` 49 | -ComputerName localhost -Wait -Verbose -Force 50 | } | Should Not Throw 51 | } 52 | 53 | It 'Should be able to call Get-DscConfiguration without throwing' { 54 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not Throw 55 | } 56 | #endregion 57 | 58 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 59 | 60 | It 'Should return the correct configuration' { 61 | 62 | $currentConfig.Name | Should Be $subCategory 63 | $currentConfig.AuditFlag | Should Match $auditFlag 64 | $currentConfig.Ensure | Should Be $auditFlagEnsure 65 | } 66 | } 67 | 68 | Context 'Should disable failure audit flag' { 69 | #region DEFAULT TESTS 70 | 71 | $auditFlag = 'Failure' 72 | $auditFlagEnsure = 'Absent' 73 | 74 | # set the system Subcategory to the incorrect state to ensure a valid test. 75 | & 'auditpol' '/set' "/subcategory:$subCategory" '/failure:enable' 76 | 77 | It 'Should compile without throwing' { 78 | { 79 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 80 | -AuditFlag $auditFlag ` 81 | -AuditFlagEnsure $auditFlagEnsure ` 82 | -OutputPath $TestDrive 83 | Start-DscConfiguration -Path $TestDrive ` 84 | -ComputerName localhost -Wait -Verbose -Force 85 | } | Should not throw 86 | } 87 | 88 | It 'Should be able to call Get-DscConfiguration without throwing' { 89 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw 90 | } 91 | #endregion 92 | 93 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 94 | 95 | It 'Should return the correct configuration' { 96 | 97 | $currentConfig.Name | Should Be $subCategory 98 | $currentConfig.AuditFlag | Should Not Match $auditFlag 99 | $currentConfig.Ensure | Should Be $auditFlagEnsure 100 | } 101 | } 102 | 103 | Context 'Should enable success audit flag' { 104 | #region DEFAULT TESTS 105 | 106 | $auditFlag = 'Success' 107 | $auditFlagEnsure = 'Present' 108 | 109 | # set the system Subcategory to the incorrect state to ensure a valid test. 110 | & 'auditpol' '/set' "/subcategory:$subCategory" '/success:disable' 111 | 112 | It 'Should compile without throwing' { 113 | { 114 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 115 | -AuditFlag $auditFlag ` 116 | -AuditFlagEnsure $auditFlagEnsure ` 117 | -OutputPath $TestDrive 118 | Start-DscConfiguration -Path $TestDrive ` 119 | -ComputerName localhost -Wait -Verbose -Force 120 | } | Should not throw 121 | } 122 | 123 | It 'Should be able to call Get-DscConfiguration without throwing' { 124 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw 125 | } 126 | #endregion 127 | 128 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 129 | 130 | It 'Should return the correct configuration' { 131 | 132 | $currentConfig.Name | Should Be $subCategory 133 | $currentConfig.AuditFlag | Should Match $auditFlag 134 | $currentConfig.Ensure | Should Be $auditFlagEnsure 135 | } 136 | } 137 | 138 | Context 'Should disable success audit flag' { 139 | #region DEFAULT TESTS 140 | 141 | $auditFlag = 'Success' 142 | $auditFlagEnsure = 'Absent' 143 | 144 | # set the system Subcategory to the incorrect state to ensure a valid test. 145 | & 'auditpol' '/set' "/subcategory:$subCategory" '/success:enable' 146 | 147 | It 'Should compile without throwing' { 148 | { 149 | & "$($script:DSCResourceName)_Config" -Name $subCategory ` 150 | -AuditFlag $auditFlag ` 151 | -AuditFlagEnsure $auditFlagEnsure ` 152 | -OutputPath $TestDrive 153 | Start-DscConfiguration -Path $TestDrive ` 154 | -ComputerName localhost -Wait -Verbose -Force 155 | } | Should not throw 156 | } 157 | 158 | It 'Should be able to call Get-DscConfiguration without throwing' { 159 | { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw 160 | } 161 | #endregion 162 | 163 | $currentConfig = Get-DscConfiguration -Verbose -ErrorAction Stop 164 | 165 | It 'Should return the correct configuration' { 166 | 167 | $currentConfig.Name | Should Be $subCategory 168 | $currentConfig.AuditFlag | Should Not Match $auditFlag 169 | $currentConfig.Ensure | Should Be $auditFlagEnsure 170 | } 171 | } 172 | } 173 | #endregion 174 | } 175 | finally 176 | { 177 | #region FOOTER 178 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 179 | #endregion 180 | } 181 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyCsv/MSFT_AuditPolicyCsv.psm1: -------------------------------------------------------------------------------- 1 | Import-Module -Name (Join-Path -Path ( Join-Path -Path ( Split-Path $PSScriptRoot -Parent ) ` 2 | -ChildPath 'AuditPolicyResourceHelper' ) ` 3 | -ChildPath 'AuditPolicyResourceHelper.psm1') 4 | 5 | # Localized messages for Write-Verbose statements in this resource 6 | $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_AuditPolicyCsv' 7 | 8 | <# 9 | .SYNOPSIS 10 | Gets the current audit policy for the node. 11 | .PARAMETER CsvPath 12 | This parameter is ignored in the Get operation, but does return the path to the 13 | backup of the current audit policy settings. 14 | #> 15 | function Get-TargetResource 16 | { 17 | [CmdletBinding()] 18 | [OutputType([Hashtable])] 19 | param 20 | ( 21 | [Parameter(Mandatory = $true)] 22 | [ValidateSet('Yes')] 23 | [String] 24 | $IsSingleInstance, 25 | 26 | [Parameter(Mandatory = $true)] 27 | [String] 28 | $CsvPath 29 | ) 30 | 31 | [String] $tempFile = ([system.IO.Path]::GetTempFileName()).Replace('.tmp','.csv') 32 | 33 | try 34 | { 35 | Write-Verbose -Message ($localizedData.BackupFilePath -f $tempFile) 36 | Invoke-SecurityCmdlet -Action "Export" -CsvPath $tempFile 37 | } 38 | catch 39 | { 40 | Write-Verbose -Message ($localizedData.ExportFailed -f $tempFile) 41 | } 42 | 43 | return @{ 44 | CsvPath = $tempFile 45 | IsSingleInstance = 'Yes' 46 | } 47 | } 48 | 49 | <# 50 | .SYNOPSIS 51 | Sets the current audit policy for the node. 52 | .PARAMETER CsvPath 53 | Specifies the path to desired audit policy settings to apply to the node. 54 | #> 55 | function Set-TargetResource 56 | { 57 | [CmdletBinding()] 58 | param 59 | ( 60 | [Parameter(Mandatory = $true)] 61 | [ValidateSet('Yes')] 62 | [String] 63 | $IsSingleInstance, 64 | 65 | [Parameter(Mandatory = $true)] 66 | [String] 67 | $CsvPath 68 | ) 69 | 70 | if ( Test-Path -Path $CsvPath ) 71 | { 72 | try 73 | { 74 | Invoke-SecurityCmdlet -Action "Import" -CsvPath $CsvPath | Out-Null 75 | Write-Verbose -Message ($localizedData.ImportSucceeded -f $CsvPath) 76 | } 77 | catch 78 | { 79 | Write-Verbose -Message ($localizedData.ImportFailed -f $CsvPath) 80 | } 81 | } 82 | else 83 | { 84 | Write-Verbose -Message ($localizedData.FileNotFound -f $CsvPath) 85 | } 86 | } 87 | 88 | <# 89 | .SYNOPSIS 90 | Tests the current audit policy against the desired policy. 91 | .PARAMETER CsvPath 92 | Specifies the path to desired audit policy settings to test against the node. 93 | #> 94 | function Test-TargetResource 95 | { 96 | [CmdletBinding()] 97 | [OutputType([Boolean])] 98 | param 99 | ( 100 | [Parameter(Mandatory = $true)] 101 | [ValidateSet('Yes')] 102 | [String] 103 | $IsSingleInstance, 104 | 105 | [Parameter(Mandatory = $true)] 106 | [String] 107 | $CsvPath 108 | ) 109 | 110 | if ( Test-Path -Path $CsvPath ) 111 | { 112 | # The CsvPath in Get-TargetResource is ignored and a temp file is returned for comparison. 113 | $currentAuditPolicyBackupPath = (Get-TargetResource -CsvPath $CsvPath ` 114 | -IsSingleInstance $IsSingleInstance).CsvPath 115 | 116 | $currentAuditPolicy = Import-Csv -Path $currentAuditPolicyBackupPath | 117 | Select-Object -Property Subcategory, @{ 118 | 'Name' = 'Value'; 119 | 'Expression' = {$_.'Setting Value'} 120 | } 121 | 122 | $desiredAuditPolicy = Import-Csv -Path $CsvPath | 123 | Select-Object -Property Subcategory, @{ 124 | 'Name' = 'Value'; 125 | 'Expression' = {$_.'Setting Value'} 126 | } 127 | 128 | # Assume the node is in the desired state until proven false. 129 | [Boolean] $inDesiredState = $true 130 | 131 | foreach ( $desiredAuditPolicySetting in $desiredAuditPolicy ) 132 | { 133 | # Get the current setting name that mathches the desired setting name 134 | $currentAuditPolicySetting = $currentAuditPolicy.Where({ 135 | $_.Subcategory -eq $desiredAuditPolicySetting.Subcategory 136 | }) 137 | 138 | # If the current and desired setting do not match, set the flag to $false 139 | if ($desiredAuditPolicySetting.Value -ne $currentAuditPolicySetting.Value) 140 | { 141 | Write-Warning -Message ($localizedData.testCsvFailed -f 142 | $desiredAuditPolicySetting.Subcategory) 143 | 144 | $inDesiredState = $false 145 | } 146 | else 147 | { 148 | Write-Verbose -Message ($localizedData.testCsvSucceed -f 149 | $desiredAuditPolicySetting.Subcategory) 150 | } 151 | } 152 | 153 | # Cleanup the temp file, since it is no longer needed. 154 | Remove-BackupFile -CsvPath $currentAuditPolicyBackupPath -Verbose 155 | 156 | return $inDesiredState 157 | } 158 | else 159 | { 160 | Write-Verbose -Message ($localizedData.FileNotFound -f $CsvPath) 161 | return $false 162 | } 163 | } 164 | 165 | <# 166 | .SYNOPSIS 167 | Helper function to use SecurityCmdlet modules if present. If not, go through AuditPol.exe. 168 | .PARAMETER Action 169 | The action to take, either Import or Export. Import will clear existing policy before writing. 170 | .PARAMETER CsvPath 171 | The path to a CSV file to either create or import. 172 | .EXAMPLE 173 | Invoke-SecurityCmdlet -Action Import -CsvPath .\test.csv 174 | #> 175 | function Invoke-SecurityCmdlet 176 | { 177 | [CmdletBinding()] 178 | param 179 | ( 180 | [Parameter(Mandatory = $true)] 181 | [ValidateSet('Import','Export')] 182 | [String] 183 | $Action, 184 | 185 | [Parameter(Mandatory = $true)] 186 | [String] 187 | $CsvPath 188 | ) 189 | 190 | # Use the security cmdlets if present. If not, use Invoke-AuditPol to call auditpol.exe. 191 | if ($null -eq (Get-Module -ListAvailable -Name "SecurityCmdlets")) 192 | { 193 | Write-Verbose -Message ($localizedData.CmdletsNotFound) 194 | 195 | if ($Action -ieq "Import") 196 | { 197 | Invoke-AuditPol -Command Restore -SubCommand "file:$CsvPath" 198 | } 199 | else 200 | { 201 | # No force option on Backup, manually check for file and delete it so we can write back again 202 | if (Test-Path -Path $CsvPath) 203 | { 204 | Remove-Item -Path $CsvPath -Force 205 | } 206 | 207 | Invoke-AuditPol -Command Backup -SubCommand "file:$CsvPath" 208 | } 209 | } 210 | else 211 | { 212 | Import-Module -Name SecurityCmdlets 213 | 214 | if ($Action -ieq "Import") 215 | { 216 | Restore-AuditPolicy -Path $CsvPath | Out-Null 217 | } 218 | elseif ($Action -ieq "Export") 219 | { 220 | # No force option on Backup, manually check for file and delete it so we can write back again 221 | if (Test-Path -Path $CsvPath) 222 | { 223 | Remove-Item -Path $CsvPath -Force 224 | } 225 | Backup-AuditPolicy -Path $CsvPath | Out-Null 226 | } 227 | } 228 | } 229 | 230 | <# 231 | .SYNOPSIS 232 | Removes the temporary file that is created by the Get\Test functions. 233 | .PARAMETER CsvPath 234 | Specifies the path of the temp file to remove. 235 | #> 236 | function Remove-BackupFile 237 | { 238 | [CmdletBinding()] 239 | param 240 | ( 241 | [Parameter(Mandatory = $true)] 242 | [String] 243 | $CsvPath 244 | ) 245 | 246 | try 247 | { 248 | Remove-Item -Path $CsvPath 249 | Write-Verbose -Message ($localizedData.RemoveFile -f $CsvPath) 250 | } 251 | catch 252 | { 253 | Write-Error $error[0] 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicySubcategory/MSFT_AuditPolicySubcategory.psm1: -------------------------------------------------------------------------------- 1 | Import-Module -Name (Join-Path -Path ( Split-Path $PSScriptRoot -Parent ) ` 2 | -ChildPath 'AuditPolicyResourceHelper\AuditPolicyResourceHelper.psm1') ` 3 | -Force 4 | 5 | # Localized messages for Write-Verbose statements in this resource 6 | $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_AuditPolicySubcategory' 7 | 8 | <# 9 | .SYNOPSIS 10 | Returns the current audit flag for the given subcategory. 11 | .PARAMETER Name 12 | Specifies the subcategory to retrieve. 13 | .PARAMETER AuditFlag 14 | Specifies the audit flag to retrieve. 15 | #> 16 | function Get-TargetResource 17 | { 18 | [CmdletBinding()] 19 | [OutputType([Hashtable])] 20 | param 21 | ( 22 | [Parameter(Mandatory = $true)] 23 | [String] 24 | $Name, 25 | 26 | [Parameter(Mandatory = $true)] 27 | [ValidateSet('Success', 'Failure')] 28 | [String] 29 | $AuditFlag 30 | ) 31 | 32 | try 33 | { 34 | $currentAuditFlag = Get-AuditSubCategory -Name $Name 35 | Write-Verbose -Message ( $localizedData.GetAuditpolSubcategorySucceed -f $Name, $AuditFlag ) 36 | } 37 | catch 38 | { 39 | Write-Verbose -Message ( $localizedData.GetAuditPolSubcategoryFailed -f $Name, $AuditFlag ) 40 | } 41 | 42 | <# 43 | The auditType property returned from Get-AuditSubCategory can be 'None','Success', 44 | 'Failure', or 'Success and Failure'. Using the match operator will return the correct 45 | state if both are set. 46 | #> 47 | if ( $currentAuditFlag -match $AuditFlag ) 48 | { 49 | $currentAuditFlag = $AuditFlag 50 | $ensure = 'Present' 51 | } 52 | else 53 | { 54 | $ensure = 'Absent' 55 | } 56 | 57 | return @{ 58 | Name = $Name 59 | AuditFlag = $currentAuditFlag 60 | Ensure = $ensure 61 | } 62 | } 63 | 64 | <# 65 | .SYNOPSIS 66 | Sets the audit flag for the given subcategory. 67 | .PARAMETER Name 68 | Specifies the subcategory to set. 69 | .PARAMETER AuditFlag 70 | Specifies the audit flag to set. 71 | .PARAMETER Ensure 72 | Specifies the state of the audit flag provided. By default this is set to Present. 73 | #> 74 | function Set-TargetResource 75 | { 76 | [CmdletBinding()] 77 | param 78 | ( 79 | [Parameter(Mandatory = $true)] 80 | [String] 81 | $Name, 82 | 83 | [Parameter(Mandatory = $true)] 84 | [ValidateSet('Success', 'Failure')] 85 | [String] 86 | $AuditFlag, 87 | 88 | [Parameter()] 89 | [ValidateSet('Present', 'Absent')] 90 | [String] 91 | $Ensure = 'Present' 92 | ) 93 | 94 | if ( -Not ( Test-ValidSubcategory -Name $Name ) ) 95 | { 96 | Throw ( $localizedData.InvalidSubcategory -f $Name ) 97 | } 98 | 99 | try 100 | { 101 | Set-AuditSubcategory -Name $Name -AuditFlag $AuditFlag -Ensure $Ensure 102 | Write-Verbose -Message ( $localizedData.SetAuditpolSubcategorySucceed ` 103 | -f $Name, $AuditFlag, $Ensure ) 104 | } 105 | catch 106 | { 107 | Write-Verbose -Message ( $localizedData.SetAuditpolSubcategoryFailed ` 108 | -f $Name, $AuditFlag, $Ensure ) 109 | } 110 | } 111 | 112 | <# 113 | .SYNOPSIS 114 | Tests the audit flag state for the given subcategory. 115 | .PARAMETER Name 116 | Specifies the subcategory to test. 117 | .PARAMETER AuditFlag 118 | Specifies the audit flag to test. 119 | .PARAMETER Ensure 120 | Specifies the state of the audit flag should be in. 121 | #> 122 | function Test-TargetResource 123 | { 124 | [CmdletBinding()] 125 | [OutputType([System.Boolean])] 126 | param 127 | ( 128 | [Parameter(Mandatory = $true)] 129 | [String] 130 | $Name, 131 | 132 | [Parameter(Mandatory = $true)] 133 | [ValidateSet('Success', 'Failure')] 134 | [String] 135 | $AuditFlag, 136 | 137 | [Parameter()] 138 | [ValidateSet('Present', 'Absent')] 139 | [String] 140 | $Ensure = 'Present' 141 | ) 142 | 143 | [Boolean] $isInDesiredState = $false 144 | 145 | if ( -Not ( Test-ValidSubcategory -Name $Name ) ) 146 | { 147 | Throw ( $localizedData.InvalidSubcategory -f $Name ) 148 | } 149 | 150 | try 151 | { 152 | [String] $currentAuditFlag = Get-AuditSubCategory -Name $Name 153 | Write-Verbose -Message ( $localizedData.GetAuditpolSubcategorySucceed -f $Name, $AuditFlag ) 154 | } 155 | catch 156 | { 157 | Write-Verbose -Message ( $localizedData.GetAuditPolSubcategoryFailed -f $Name, $AuditFlag ) 158 | } 159 | 160 | # If the setting should be present look for a match, otherwise look for a notmatch 161 | if ( $Ensure -eq 'Present' ) 162 | { 163 | $isInDesiredState = $currentAuditFlag -match $AuditFlag 164 | } 165 | else 166 | { 167 | $isInDesiredState = $currentAuditFlag -notmatch $AuditFlag 168 | } 169 | 170 | <# 171 | The audit type can be true in either a match or non-match state. If the audit type 172 | matches the ensure property return the setting correct message, else return the 173 | setting incorrect message 174 | #> 175 | if ( $isInDesiredState ) 176 | { 177 | Write-Verbose -Message ( $localizedData.TestAuditpolSubcategoryCorrect ` 178 | -f $Name, $AuditFlag, $Ensure ) 179 | } 180 | else 181 | { 182 | Write-Verbose -Message ( $localizedData.TestAuditpolSubcategoryIncorrect ` 183 | -f $Name, $AuditFlag, $Ensure ) 184 | } 185 | 186 | $isInDesiredState 187 | } 188 | 189 | #--------------------------------------------------------------------------------------------------- 190 | # Support functions to handle auditpol I/O 191 | 192 | <# 193 | .SYNOPSIS 194 | Gets the audit flag state for a specifc subcategory. 195 | .DESCRIPTION 196 | This function enforces parameters that will be passed to Invoke-Auditpol. 197 | .PARAMETER Name 198 | The name of the subcategory to get the audit flags from. 199 | .OUTPUTS 200 | A string with the flags that are set for the specificed subcategory 201 | .EXAMPLE 202 | Get-AuditSubCategory -Name 'Logon' 203 | #> 204 | function Get-AuditSubCategory 205 | { 206 | [CmdletBinding()] 207 | [OutputType([String])] 208 | param 209 | ( 210 | [Parameter(Mandatory = $true)] 211 | [String] 212 | $Name 213 | ) 214 | <# 215 | When PowerShell cmdlets are released for individual audit policy settings a condition 216 | will be placed here to use native PowerShell cmdlets to set the subcategory flags. 217 | #> 218 | # get the auditpol raw csv output 219 | $subcategory = Invoke-AuditPol -Command 'Get' -SubCommand "Subcategory:""$Name""" 220 | 221 | # The subcategory flag is stored in the 'Inclusion Setting' property of the output CSV. 222 | return $subcategory.'Inclusion Setting' 223 | } 224 | 225 | <# 226 | .SYNOPSIS 227 | Sets the audit flag state for a specifc subcategory. 228 | .DESCRIPTION 229 | Calls the private function to execute a set operation on the given subcategory 230 | .PARAMETER Name 231 | The name of the audit subcategory to set 232 | .PARAMETER AuditFlag 233 | The specifc flag to set (Success|Failure) 234 | .PARAMETER Ensure 235 | The action to take on the flag 236 | .EXAMPLE 237 | Set-AuditSubcategory -Name 'Logon' -AuditFlag 'Success' -Ensure 'Present' 238 | #> 239 | function Set-AuditSubcategory 240 | { 241 | [CmdletBinding(SupportsShouldProcess = $true)] 242 | param 243 | ( 244 | [Parameter(Mandatory = $true)] 245 | [String] 246 | $Name, 247 | 248 | [Parameter(Mandatory = $true)] 249 | [ValidateSet( 'Success','Failure' )] 250 | [String] 251 | $AuditFlag, 252 | 253 | [Parameter(Mandatory = $true)] 254 | [String] 255 | $Ensure 256 | ) 257 | <# 258 | When PowerShell cmdlets are released for individual audit policy settings a condition 259 | will be placed here to use native PowerShell cmdlets to set the option details. 260 | #> 261 | if ( $pscmdlet.ShouldProcess( "$Name","Set AuditFlag '$AuditFlag'" ) ) 262 | { 263 | # translate $ensure=present to enable and $ensure=absent to disable 264 | $auditState = @{ 265 | 'Present' = 'enable' 266 | 'Absent' = 'disable' 267 | } 268 | 269 | # Create the line needed for auditpol to set the category flag 270 | if ( $AuditFlag -eq 'Success' ) 271 | { 272 | [String[]] $subcommand = @( "Subcategory:""$Name""", "/success:$($auditState[$Ensure])" ) 273 | } 274 | else 275 | { 276 | [String[]] $subcommand = @( "Subcategory:""$Name""", "/failure:$($auditState[$Ensure])" ) 277 | } 278 | 279 | Invoke-AuditPol -Command 'Set' -subCommand $subcommand | Out-Null 280 | } 281 | } 282 | 283 | Export-ModuleMember -Function *-TargetResource 284 | -------------------------------------------------------------------------------- /DSCResources/MSFT_AuditPolicyGUID/MSFT_AuditPolicyGUID.psm1: -------------------------------------------------------------------------------- 1 | 2 | Import-Module -Name (Join-Path -Path ( Split-Path $PSScriptRoot -Parent ) ` 3 | -ChildPath 'AuditPolicyResourceHelper\AuditPolicyResourceHelper.psm1') ` 4 | -Force 5 | 6 | # Localized messages for Write-Verbose statements in this resource 7 | $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_AuditPolicyGUID' 8 | 9 | <# 10 | .SYNOPSIS 11 | Returns the current audit flag for the given subcategory. 12 | .PARAMETER Name 13 | Specifies the subcategory to retrieve. 14 | .PARAMETER AuditFlag 15 | Specifies the audit flag to retrieve. 16 | #> 17 | function Get-TargetResource 18 | { 19 | [CmdletBinding()] 20 | [OutputType([System.Collections.Hashtable])] 21 | param 22 | ( 23 | [Parameter(Mandatory = $true)] 24 | [String] 25 | $Name, 26 | 27 | [Parameter(Mandatory = $true)] 28 | [ValidateSet('Success', 'Failure', 'No Auditing', 'Success And Failure')] 29 | [String] 30 | $AuditFlag 31 | ) 32 | 33 | # Work in GUIDS and Setting Values the rest of the way 34 | $GUID = Get-AuditSubCategoryGuid -Name $Name 35 | $SettingValue = $AuditFlagToSettingValue[$AuditFlag] 36 | 37 | try 38 | { 39 | $currentAuditSetting = Get-AuditSubCategory -GUID $GUID 40 | Write-Verbose -Message ( $localizedData.GetAuditpolSubcategorySucceed -f $Name, $AuditFlag ) 41 | } 42 | catch 43 | { 44 | Write-Verbose -Message ( $localizedData.GetAuditPolSubcategoryFailed -f $Name, $AuditFlag ) 45 | } 46 | 47 | <# 48 | The auditType property returned from Get-AuditSubCategory can be 'None','Success', 49 | 'Failure', or 'Success and Failure'. Using the match operator will return the correct 50 | state if both are set. 51 | #> 52 | $currentAuditFlag = $AuditSettingValueToFlag[$currentAuditSetting] 53 | if ( $currentAuditSetting -eq $SettingValue ) 54 | { 55 | $ensure = 'Present' 56 | } 57 | else 58 | { 59 | $ensure = 'Absent' 60 | } 61 | 62 | return @{ 63 | Name = $Name 64 | AuditFlag = $currentAuditFlag 65 | Ensure = $ensure 66 | } 67 | } 68 | 69 | <# 70 | .SYNOPSIS 71 | Sets the audit flag for the given subcategory. 72 | .PARAMETER Name 73 | Specifies the subcategory to set. 74 | .PARAMETER AuditFlag 75 | Specifies the audit flag to set. 76 | .PARAMETER Ensure 77 | Specifies the state of the audit flag provided. By default this is set to Present. 78 | #> 79 | function Set-TargetResource 80 | { 81 | [CmdletBinding()] 82 | param 83 | ( 84 | [Parameter(Mandatory = $true)] 85 | [String] 86 | $Name, 87 | 88 | [Parameter(Mandatory = $true)] 89 | [ValidateSet('Success', 'Failure', 'No Auditing', 'Success And Failure')] 90 | [String] 91 | $AuditFlag, 92 | 93 | [Parameter()] 94 | [ValidateSet('Present', 'Absent')] 95 | [String] 96 | $Ensure = 'Present' 97 | ) 98 | 99 | # Work in GUIDS and Setting Values the rest of the way 100 | $GUID = Get-AuditSubCategoryGuid -Name $Name 101 | $SettingValue = $AuditFlagToSettingValue[$AuditFlag] 102 | 103 | try 104 | { 105 | Set-AuditSubcategory -GUID $GUID -SettingValue $SettingValue -Ensure $Ensure 106 | Write-Verbose -Message ( $localizedData.SetAuditpolSubcategorySucceed ` 107 | -f $Name, $AuditFlag, $Ensure ) 108 | } 109 | catch 110 | { 111 | Write-Verbose -Message ( $localizedData.SetAuditpolSubcategoryFailed ` 112 | -f $Name, $AuditFlag, $Ensure ) 113 | } 114 | } 115 | 116 | <# 117 | .SYNOPSIS 118 | Tests the audit flag state for the given subcategory. 119 | .PARAMETER Name 120 | Specifies the subcategory to test. 121 | .PARAMETER AuditFlag 122 | Specifies the audit flag to test. 123 | .PARAMETER Ensure 124 | Specifies the state of the audit flag should be in. 125 | #> 126 | function Test-TargetResource 127 | { 128 | [CmdletBinding()] 129 | [OutputType([System.Boolean])] 130 | param 131 | ( 132 | [Parameter(Mandatory = $true)] 133 | [String] 134 | $Name, 135 | 136 | [Parameter(Mandatory = $true)] 137 | [ValidateSet('Success', 'Failure', 'No Auditing', 'Success And Failure')] 138 | [String] 139 | $AuditFlag, 140 | 141 | [Parameter()] 142 | [ValidateSet('Present', 'Absent')] 143 | [String] 144 | $Ensure="Present" 145 | ) 146 | 147 | [System.Boolean] $isInDesiredState = $false 148 | 149 | # Work in GUIDS and Setting Values the rest of the way 150 | $GUID = Get-AuditSubCategoryGuid -Name $Name 151 | [int]$SettingValue = $AuditFlagToSettingValue[$AuditFlag] 152 | 153 | try 154 | { 155 | [int]$currentAuditSetting = Get-AuditSubCategory -GUID $GUID 156 | Write-Verbose -Message ( $localizedData.GetAuditpolSubcategorySucceed -f $Name, $AuditFlag ) 157 | } 158 | catch 159 | { 160 | Write-Verbose -Message ( $localizedData.GetAuditPolSubcategoryFailed -f $Name, $AuditFlag ) 161 | } 162 | 163 | # If the setting should be present look for a match, otherwise look for a notmatch 164 | if ( $Ensure -eq 'Present' ) 165 | { 166 | $isInDesiredState = $currentAuditSetting -eq $SettingValue 167 | } 168 | else 169 | { 170 | $isInDesiredState = $currentAuditSetting -ne $SettingValue 171 | } 172 | 173 | <# 174 | The audit type can be true in either a match or non-match state. If the audit type 175 | matches the ensure property return the setting correct message, else return the 176 | setting incorrect message 177 | #> 178 | if ( $isInDesiredState ) 179 | { 180 | # TODO: Change back to normal 181 | Write-Verbose -Message ( $localizedData.TestAuditpolSubcategoryCorrect ` 182 | -f $Name, $AuditFlag, $Ensure ) 183 | Write-Verbose $Ensure 184 | } 185 | else 186 | { 187 | Write-Verbose -Message ( $localizedData.TestAuditpolSubcategoryIncorrect ` 188 | -f $Name, $AuditFlag, $Ensure ) 189 | } 190 | 191 | $isInDesiredState 192 | } 193 | 194 | #--------------------------------------------------------------------------------------------------- 195 | # Support functions to handle auditpol I/O 196 | 197 | <# 198 | .SYNOPSIS 199 | Gets the audit flag state for a specifc subcategory. 200 | .DESCRIPTION 201 | This function enforces parameters that will be passed to Invoke-Auditpol. 202 | .PARAMETER GUID 203 | The GUID of the subcategory to get the audit flags from. 204 | .OUTPUTS 205 | A string with the flags that are set for the specificed subcategory 206 | .EXAMPLE 207 | Get-AuditSubCategory -Name 'Logon' 208 | #> 209 | function Get-AuditSubCategory 210 | { 211 | [CmdletBinding()] 212 | [OutputType([System.Int32])] 213 | param 214 | ( 215 | [Parameter(Mandatory = $true)] 216 | [GUID] 217 | $GUID 218 | ) 219 | <# 220 | When PowerShell cmdlets are released for individual audit policy settings a condition 221 | will be placed here to use native PowerShell cmdlets to set the option details. 222 | #> 223 | # get the auditpol raw csv output 224 | $returnCsv = Get-StagedAuditPolicyCSV | Where-Object {$_.'SubCategory GUID' -eq "{$($GUID.guid)}"} 225 | 226 | if ($returnCsv) 227 | { 228 | return $returnCsv.'Setting Value' 229 | } 230 | else 231 | { 232 | Throw ($localizedData.RetrieveSettingFailure -f $GUID) 233 | } 234 | } 235 | 236 | <# 237 | .SYNOPSIS 238 | Sets the audit flag state for a specifc subcategory. 239 | .DESCRIPTION 240 | Calls the private function to execute a set operation on the given subcategory 241 | .PARAMETER GUID 242 | The GUID of the audit subcategory to set 243 | .PARAMETER SettingValue 244 | The Flag to set as an integer 245 | .PARAMETER Ensure 246 | The action to take on the flag 247 | .EXAMPLE 248 | Set-AuditSubcategory -GUID {0CCE923A-69AE-11D9-BED3-505054503030} -SettingValue 3 -Ensure 'Present' 249 | #> 250 | function Set-AuditSubcategory 251 | { 252 | [CmdletBinding()] 253 | param 254 | ( 255 | [Parameter( Mandatory = $true )] 256 | [GUID] 257 | $GUID, 258 | 259 | [Parameter( Mandatory = $true )] 260 | [ValidateRange(0, 3)] 261 | [Int] 262 | $SettingValue, 263 | 264 | [Parameter( Mandatory = $true )] 265 | [String] 266 | $Ensure 267 | ) 268 | 269 | <# 270 | When PowerShell cmdlets are released for individual audit policy settings a condition 271 | will be placed here to use native PowerShell cmdlets to set the option details. 272 | #> 273 | 274 | Write-StagedAuditCSV -Guid $GUID -SettingValue $SettingValue -Ensure $Ensure 275 | } 276 | 277 | <# 278 | .SYNOPSIS 279 | Gets the guild for a specified subcategory 280 | .DESCRIPTION 281 | Uses an imported hashtable of static values 282 | .PARAMETER Name 283 | The Subcategory to retrieve the GUID for. 284 | .EXAMPLE 285 | Get-AuditSubCategoryGUID -Name 'Process Creation' 286 | #> 287 | Function Get-AuditSubCategoryGuid 288 | { 289 | [CmdletBinding()] 290 | [OutputType([System.String])] 291 | param 292 | ( 293 | [Parameter(Mandatory = $true)] 294 | [String]$Name 295 | ) 296 | 297 | if ($AuditSubCategoryToGUIDHash.ContainsKey($Name)) 298 | { 299 | $GUID = $AuditSubCategorytoGUIDHash[$Name] 300 | Write-Verbose -Message ( $localizedData.AuditSubCategoryGUIDFound -f $Name, $GUID ) 301 | return $GUID 302 | } 303 | else 304 | { 305 | Throw ( $localizedData.AuditSubCategoryGUIDNotFound -f $Name ) 306 | } 307 | } 308 | 309 | Export-ModuleMember -Function *-TargetResource 310 | -------------------------------------------------------------------------------- /Tests/Unit/MSFT_AuditPolicyOption.tests.ps1: -------------------------------------------------------------------------------- 1 | $script:DSCModuleName = 'AuditPolicyDsc' 2 | $script:DSCResourceName = 'MSFT_AuditPolicyOption' 3 | 4 | #region HEADER 5 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $script:MyInvocation.MyCommand.Path)) 6 | if ( (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 7 | (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) 8 | { 9 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\')) 10 | } 11 | else 12 | { 13 | & git @('-C',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\'),'pull') 14 | } 15 | Import-Module (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 16 | $TestEnvironment = Initialize-TestEnvironment ` 17 | -DSCModuleName $script:DSCModuleName ` 18 | -DSCResourceName $script:DSCResourceName ` 19 | -TestType Unit 20 | #endregion 21 | 22 | # Begin Testing 23 | try 24 | { 25 | #region Pester Tests 26 | 27 | InModuleScope $script:DSCResourceName { 28 | 29 | # The script scope does not pierce the InModuleScope 30 | $script:DSCResourceName = 'MSFT_AuditPolicyOption' 31 | 32 | #region Pester Test Initialization 33 | 34 | # set the audit option test strings to Mock 35 | $testParameters = @{ 36 | Name = 'CrashOnAuditFail' 37 | Value = 'Enabled' 38 | } 39 | 40 | #endregion 41 | 42 | #region Function Get-TargetResource 43 | Describe "$($script:DSCResourceName)\Get-TargetResource" { 44 | 45 | Context 'Option Enabled' { 46 | 47 | Mock -CommandName Get-AuditOption -MockWith { 48 | return 'Enabled' } -ModuleName MSFT_AuditPolicyOption -Verifiable 49 | 50 | It 'Should not throw an exception' { 51 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 52 | Should Not Throw 53 | } 54 | 55 | It 'Should return the correct hashtable properties' { 56 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 57 | $script:getTargetResourceResult.Value | Should Be $testParameters.Value 58 | } 59 | 60 | It 'Should call expected Mocks' { 61 | Assert-VerifiableMock 62 | Assert-MockCalled -CommandName Get-AuditOption -Exactly 1 63 | } 64 | } 65 | 66 | Context 'Option Disabled' { 67 | 68 | $testParameters.Value = 'Disabled' 69 | Mock -CommandName Get-AuditOption -MockWith { 70 | return 'Disabled' } -ModuleName MSFT_AuditPolicyOption -Verifiable 71 | 72 | It 'Should not throw an exception' { 73 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 74 | Should Not Throw 75 | } 76 | 77 | It 'Should return the correct hashtable properties' { 78 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 79 | $script:getTargetResourceResult.Value | Should Be $testParameters.Value 80 | } 81 | 82 | It 'Should call expected Mocks' { 83 | Assert-VerifiableMock 84 | Assert-MockCalled -CommandName Get-AuditOption -Exactly 1 85 | } 86 | } 87 | } 88 | #endregion 89 | 90 | #region Function Test-TargetResource 91 | Describe "$($script:DSCResourceName)\Test-TargetResource" { 92 | 93 | $testParameters.Value = 'Enabled' 94 | 95 | Context 'Option set to enabled and should be' { 96 | 97 | Mock -CommandName Get-AuditOption -MockWith { 98 | return 'Enabled' } -ModuleName MSFT_AuditPolicyOption -Verifiable 99 | 100 | It 'Should not throw an exception' { 101 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 102 | Should Not Throw 103 | } 104 | 105 | It 'Should return true' { 106 | $script:testTargetResourceResult | Should Be $true 107 | } 108 | 109 | It 'Should call expected Mocks' { 110 | Assert-VerifiableMock 111 | Assert-MockCalled -CommandName Get-AuditOption -Exactly 1 112 | } 113 | } 114 | 115 | Context 'Option set to enabled and should not be' { 116 | 117 | Mock -CommandName Get-AuditOption -MockWith { 118 | return 'Disabled' } -ModuleName MSFT_AuditPolicyOption -Verifiable 119 | 120 | It 'Should not throw an exception' { 121 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 122 | Should Not Throw 123 | } 124 | 125 | It 'Should return false' { 126 | $script:testTargetResourceResult | Should Be $false 127 | } 128 | 129 | It 'Should call expected Mocks' { 130 | Assert-VerifiableMock 131 | Assert-MockCalled -CommandName Get-AuditOption -Exactly 1 132 | } 133 | } 134 | 135 | $testParameters.Value = 'Disabled' 136 | 137 | Context 'Option set to disabled and should be' { 138 | 139 | Mock -CommandName Get-AuditOption -MockWith { 140 | return 'Disabled' } -ModuleName MSFT_AuditPolicyOption -Verifiable 141 | 142 | It 'Should not throw an exception' { 143 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 144 | Should Not Throw 145 | } 146 | 147 | It 'Should return true' { 148 | $script:testTargetResourceResult | Should Be $true 149 | } 150 | 151 | It 'Should call expected Mocks' { 152 | Assert-VerifiableMock 153 | Assert-MockCalled -CommandName Get-AuditOption -Exactly 1 154 | } 155 | } 156 | 157 | Context 'Option set to disabled and should not be' { 158 | 159 | Mock -CommandName Get-AuditOption -MockWith { 160 | return 'Enabled' } -ModuleName MSFT_AuditPolicyOption -Verifiable 161 | 162 | It 'Should not throw an exception' { 163 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 164 | Should Not Throw 165 | } 166 | 167 | It 'Should return false' { 168 | $script:testTargetResourceResult | Should Be $false 169 | } 170 | 171 | It 'Should call expected Mocks' { 172 | Assert-VerifiableMock 173 | Assert-MockCalled -CommandName Get-AuditOption -Exactly 1 174 | } 175 | } 176 | } 177 | #endregion 178 | 179 | #region Function Set-TargetResource 180 | Describe "$($script:DSCResourceName)\Set-TargetResource" { 181 | 182 | $testParameters.Value = 'Enabled' 183 | 184 | Context 'Option to Enabled' { 185 | 186 | Mock -CommandName Set-AuditOption -MockWith { } ` 187 | -ModuleName MSFT_AuditPolicyOption -Verifiable 188 | 189 | It 'Should not throw an exception' { 190 | { Set-TargetResource @testParameters } | Should Not Throw 191 | } 192 | 193 | It 'Should call expected Mocks' { 194 | Assert-VerifiableMock 195 | Assert-MockCalled -CommandName Set-AuditOption -Exactly 1 196 | } 197 | } 198 | 199 | $testParameters.Value = 'Disabled' 200 | 201 | Context 'Option to Disabled' { 202 | 203 | Mock -CommandName Set-AuditOption -MockWith { } ` 204 | -ModuleName MSFT_AuditPolicyOption -Verifiable 205 | 206 | It 'Should not throw an exception' { 207 | { Set-TargetResource @testParameters } | Should Not Throw 208 | } 209 | 210 | It 'Should call expected Mocks' { 211 | Assert-VerifiableMock 212 | Assert-MockCalled -CommandName Set-AuditOption -Exactly 1 213 | } 214 | } 215 | } 216 | #endregion 217 | 218 | #region Helper Cmdlets 219 | Describe 'Private function Get-AuditOption' { 220 | 221 | [String] $name = 'CrashOnAuditFail' 222 | 223 | Context 'Get audit policy option enabled' { 224 | 225 | [String] $value = 'Enabled' 226 | 227 | Mock -CommandName Invoke-Auditpol -MockWith { 228 | @{ 229 | 'Machine Name'= $env:COMPUTERNAME 230 | 'Policy Target' = '' 231 | 'Subcategory' = "Option:$name" 232 | 'Subcategory GUID' = '' 233 | 'Inclusion Setting' = $value 234 | 'Exclusion Setting' = '' 235 | } 236 | } -ParameterFilter { $Command -eq 'Get' } -Verifiable 237 | 238 | It 'Should not throw an exception' { 239 | { $script:getAuditOptionResult = Get-AuditOption -Name $name } | 240 | Should Not Throw 241 | } 242 | 243 | It 'Should return the correct value' { 244 | $script:getAuditOptionResult | Should Be $value 245 | } 246 | 247 | It 'Should call expected Mocks' { 248 | Assert-VerifiableMock 249 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 250 | } 251 | } 252 | 253 | Context 'Get audit policy option disabled' { 254 | 255 | [String] $value = 'Disabled' 256 | 257 | Mock -CommandName Invoke-Auditpol -MockWith { 258 | @{ 259 | 'Machine Name'= $env:COMPUTERNAME 260 | 'Policy Target' = '' 261 | 'Subcategory' = "Option:$name" 262 | 'Subcategory GUID' = '' 263 | 'Inclusion Setting' = $value 264 | 'Exclusion Setting' = '' 265 | } 266 | } -ParameterFilter { $Command -eq 'Get' } -Verifiable 267 | 268 | It 'Should not throw an exception' { 269 | { $script:getAuditOptionResult = Get-AuditOption -Name $name } | 270 | Should Not Throw 271 | } 272 | 273 | It 'Should return the correct value' { 274 | $script:getAuditOptionResult | Should Be $value 275 | } 276 | 277 | It 'Should call expected Mocks' { 278 | Assert-VerifiableMock 279 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 280 | } 281 | } 282 | } 283 | 284 | Describe 'Private function Set-AuditOption' { 285 | 286 | [String] $name = "CrashOnAuditFail" 287 | 288 | Context "Set audit poliy option to enabled" { 289 | 290 | [String] $value = "Enabled" 291 | 292 | Mock -CommandName Invoke-Auditpol -MockWith { } -ParameterFilter { 293 | $Command -eq 'Set' } -Verifiable 294 | 295 | It 'Should not throw an exception' { 296 | { Set-AuditOption -Name $name -Value $value } | Should Not Throw 297 | } 298 | 299 | It 'Should call expected Mocks' { 300 | Assert-VerifiableMock 301 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 302 | } 303 | } 304 | 305 | Context "Set audit policy option to disabled" { 306 | 307 | [String] $value = "Disabled" 308 | 309 | Mock -CommandName Invoke-Auditpol -MockWith { } -ParameterFilter { 310 | $Command -eq 'Set' } -Verifiable 311 | 312 | It 'Should not throw an exception' { 313 | { Set-AuditOption -Name $name -Value $value } | Should Not Throw 314 | } 315 | 316 | It 'Should call expected Mocks' { 317 | Assert-VerifiableMock 318 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 319 | } 320 | } 321 | } 322 | #endregion 323 | } 324 | #endregion 325 | } 326 | finally 327 | { 328 | #region FOOTER 329 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 330 | #endregion 331 | } 332 | -------------------------------------------------------------------------------- /Tests/Unit/MSFT_AuditPolicyCsv.tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $script:DSCModuleName = 'AuditPolicyDsc' 3 | $script:DSCResourceName = 'MSFT_AuditPolicyCsv' 4 | 5 | #region HEADER 6 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $script:MyInvocation.MyCommand.Path)) 7 | if ( (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 8 | (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) 9 | { 10 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\')) 11 | } 12 | else 13 | { 14 | & git @('-C',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\'),'pull') 15 | } 16 | Import-Module (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 17 | $TestEnvironment = Initialize-TestEnvironment ` 18 | -DSCModuleName $script:DSCModuleName ` 19 | -DSCResourceName $script:DSCResourceName ` 20 | -TestType Unit 21 | #endregion 22 | 23 | # Begin Testing 24 | try 25 | { 26 | #region Pester Tests 27 | 28 | InModuleScope $script:DSCResourceName { 29 | 30 | # The script scope does not pierce the InModuleScope 31 | $script:DSCResourceName = 'MSFT_AuditPolicyCsv' 32 | 33 | # Create temporary files to hold the test data. 34 | $script:currentAuditpolicyCsv = ([system.IO.Path]::GetTempFileName()).Replace('.tmp','.csv') 35 | $script:desiredAuditpolicyCsv = ([system.IO.Path]::GetTempFileName()).Replace('.tmp','.csv') 36 | 37 | $script:csvPath = $script:desiredAuditpolicyCsv 38 | 39 | # Create the current auditpol backup file to test against. 40 | @(@("Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value") 41 | @(",System,IPsec Driver,{0CCE9213-69AE-11D9-BED3-505054503030},Failure,,2") 42 | @(",System,System Integrity,{0CCE9212-69AE-11D9-BED3-505054503030},Success,,1") 43 | @(",System,Security System Extension,{0CCE9211-69AE-11D9-BED3-505054503030},No Auditing,,0") 44 | @(",,Option:CrashOnAuditFail,,Disabled,,0") 45 | @(",,RegistryGlobalSacl,,,,")) | Out-File $script:currentAuditpolicyCsv -Encoding utf8 -Force 46 | 47 | Describe "$($script:DSCResourceName)\Get-TargetResource" { 48 | 49 | Mock -CommandName Invoke-SecurityCmdlet -ParameterFilter { $Action -eq 'Export' } ` 50 | -MockWith { } -Verifiable 51 | 52 | It 'Should not throw an exception' { 53 | { 54 | $script:getTargetResourceResult = Get-TargetResource -CsvPath $script:csvPath ` 55 | -IsSingleInstance 'Yes' 56 | } | Should Not Throw 57 | } 58 | 59 | It 'Should return the correct hashtable property' { 60 | $script:getTargetResourceResult.CSVPath | Should Not Be $script:csvPath 61 | } 62 | 63 | It 'Should call expected Mocks' { 64 | Assert-VerifiableMock 65 | Assert-MockCalled -CommandName Invoke-SecurityCmdlet -Exactly 1 66 | } 67 | } 68 | 69 | Describe "$($script:DSCResourceName)\Test-TargetResource" { 70 | 71 | # Create the desired auditpol backup file to test against. 72 | @(@("Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value") 73 | @(",System,IPsec Driver,{0CCE9213-69AE-11D9-BED3-505054503030},Success,,1") 74 | @(",System,System Integrity,{0CCE9212-69AE-11D9-BED3-505054503030},Failure,,2") 75 | @(",System,Security System Extension,{0CCE9211-69AE-11D9-BED3-505054503030},No Auditing,,0") 76 | @(",,Option:CrashOnAuditFail,,Enabled,,1") 77 | @(",,RegistryGlobalSacl,,,,")) | Out-File $script:desiredAuditpolicyCsv -Encoding utf8 -Force 78 | 79 | Context 'CSVs are different' { 80 | 81 | Mock -CommandName Get-TargetResource -MockWith { 82 | return @{CsvPath=$script:currentAuditpolicyCsv} 83 | } -Verifiable 84 | 85 | Mock -CommandName Remove-BackupFile -MockWith { } -Verifiable 86 | 87 | It 'Should not throw an exception' { 88 | { 89 | $script:testTargetResourceResult = Test-TargetResource -CsvPath $script:csvPath ` 90 | -IsSingleInstance 'Yes' 91 | } | Should Not Throw 92 | } 93 | 94 | It 'Should return false' { 95 | $script:testTargetResourceResult | Should Be $false 96 | } 97 | 98 | It 'Should call expected Mocks' { 99 | Assert-VerifiableMock 100 | Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 101 | Assert-MockCalled -CommandName Remove-BackupFile -Exactly 1 102 | } 103 | } 104 | 105 | Context 'CSVs are the same' { 106 | 107 | Mock -CommandName Get-TargetResource -MockWith { 108 | return @{CsvPath=$script:desiredAuditpolicyCsv} 109 | } -Verifiable 110 | 111 | Mock -CommandName Remove-BackupFile -MockWith { } -Verifiable 112 | 113 | It 'Should not throw an exception' { 114 | { 115 | $script:testTargetResourceResult = Test-TargetResource -CsvPath $script:csvPath ` 116 | -IsSingleInstance 'Yes' 117 | } | Should Not Throw 118 | } 119 | 120 | It 'Should return true' { 121 | $script:testTargetResourceResult | Should Be $true 122 | } 123 | 124 | It 'Should call expected Mocks' { 125 | Assert-VerifiableMock 126 | Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 127 | Assert-MockCalled -CommandName Remove-BackupFile -Exactly 1 128 | } 129 | } 130 | } 131 | 132 | Describe "$($script:DSCResourceName)\Set-TargetResource" { 133 | 134 | Mock -CommandName Invoke-SecurityCmdlet -ParameterFilter { $Action -eq 'Import' } ` 135 | -MockWith { } -Verifiable 136 | 137 | It 'Should not throw an exception' { 138 | { 139 | $script:setTargetResourceResult = Set-TargetResource -CsvPath $script:csvPath ` 140 | -IsSingleInstance 'Yes' 141 | } | Should Not Throw 142 | } 143 | 144 | It 'Should not return anything' { 145 | $script:setTargetResourceResult | Should BeNullOrEmpty 146 | } 147 | 148 | It 'Should call expected Mocks' { 149 | Assert-VerifiableMock 150 | Assert-MockCalled -CommandName Invoke-SecurityCmdlet -Exactly 1 -Scope Describe 151 | } 152 | } 153 | 154 | Describe 'Function Invoke-SecurityCmdlet' { 155 | 156 | # Create function to mock since security cmdlets are not in appveyor 157 | function Restore-AuditPolicy { } 158 | function Backup-AuditPolicy { } 159 | 160 | Context 'Backup when security cmdlets are available' { 161 | 162 | Mock -CommandName Get-Module -ParameterFilter { $Name -eq "SecurityCmdlets"} ` 163 | -MockWith {"SecurityCmdlets"} -Verifiable 164 | 165 | Mock -CommandName Import-Module -ParameterFilter { $Name -eq "SecurityCmdlets"} 166 | 167 | Mock -CommandName Backup-AuditPolicy -MockWith {} -Verifiable 168 | 169 | It 'Should not throw an exception' { 170 | { 171 | $script:backupAuditPolicyResult = Invoke-SecurityCmdlet -Action Export ` 172 | -CsvPath $script:currentAuditpolicyCsv 173 | } | Should Not Throw 174 | } 175 | 176 | It 'Should not return anything' { 177 | $script:backupAuditPolicyResult | Should BeNullOrEmpty 178 | } 179 | 180 | It 'Should call expected Mocks' { 181 | Assert-VerifiableMock 182 | Assert-MockCalled -CommandName Get-Module -Exactly 1 -Scope Context 183 | Assert-MockCalled -CommandName Import-Module -Exactly 1 -Scope Context 184 | Assert-MockCalled -CommandName Backup-AuditPolicy -Exactly 1 -Scope Context 185 | } 186 | } 187 | 188 | Context 'Restore when security cmdlets are available' { 189 | 190 | Mock -CommandName Get-Module -ParameterFilter { $Name -eq "SecurityCmdlets"} ` 191 | -MockWith {"SecurityCmdlets"} -Verifiable 192 | 193 | Mock -CommandName Import-Module -ParameterFilter { $Name -eq "SecurityCmdlets"} 194 | 195 | Mock -CommandName Restore-AuditPolicy -MockWith {} -Verifiable 196 | 197 | It 'Should not throw an exception' { 198 | { $script:restoreAuditPolicyResult = Invoke-SecurityCmdlet -Action Import ` 199 | -CsvPath $script:currentAuditpolicyCsv } | 200 | Should Not Throw 201 | } 202 | 203 | It 'Should not return anything' { 204 | $script:restoreAuditPolicyResult | Should BeNullOrEmpty 205 | } 206 | 207 | It 'Should call expected Mocks' { 208 | Assert-VerifiableMock 209 | Assert-MockCalled -CommandName Get-Module -Exactly 1 -Scope Context 210 | Assert-MockCalled -CommandName Import-Module -Exactly 1 -Scope Context 211 | Assert-MockCalled -CommandName Restore-AuditPolicy -Exactly 1 -Scope Context 212 | } 213 | } 214 | 215 | Context 'Backup when security cmdlets are NOT available' { 216 | 217 | Mock -CommandName Get-Module -ParameterFilter { $Name -eq "SecurityCmdlets" } ` 218 | -MockWith {} -Verifiable 219 | 220 | Mock -CommandName Invoke-AuditPol -ParameterFilter { $Command -eq "Backup" } ` 221 | -MockWith { } -Verifiable 222 | 223 | It 'Should not throw an exception' { 224 | { $script:backupAuditPolicyResult = Invoke-SecurityCmdlet -Action Export ` 225 | -CsvPath $script:currentAuditpolicyCsv } | 226 | Should Not Throw 227 | } 228 | 229 | It 'Should not return anything' { 230 | $script:backupAuditPolicyResult | Should BeNullOrEmpty 231 | } 232 | 233 | It 'Should call expected Mocks' { 234 | Assert-VerifiableMock 235 | Assert-MockCalled -CommandName Get-Module -Exactly 1 -Scope Context 236 | Assert-MockCalled -CommandName Invoke-AuditPol -Exactly 1 -Scope Context 237 | } 238 | } 239 | 240 | Context 'Restore when security cmdlets are NOT available' { 241 | 242 | Mock -CommandName Get-Module -ParameterFilter { $Name -eq "SecurityCmdlets" } ` 243 | -MockWith {} -Verifiable 244 | 245 | Mock -CommandName Invoke-AuditPol -ParameterFilter { $Command -eq "Restore" } ` 246 | -MockWith { } -Verifiable 247 | 248 | It 'Should not throw an exception' { 249 | { $script:restoreAuditPolicyResult = Invoke-SecurityCmdlet -Action Import ` 250 | -CsvPath $script:currentAuditpolicyCsv } | 251 | Should Not Throw 252 | } 253 | 254 | It 'Should not return anything' { 255 | $script:restoreAuditPolicyResult | Should BeNullOrEmpty 256 | } 257 | 258 | It 'Should call expected Mocks' { 259 | Assert-VerifiableMock 260 | Assert-MockCalled -CommandName Get-Module -Exactly 1 -Scope Context 261 | Assert-MockCalled -CommandName Invoke-AuditPol -Exactly 1 -Scope Context 262 | } 263 | } 264 | } 265 | 266 | Describe 'Function Remove-BackupFile' { 267 | 268 | $script:csvPath = $script:currentAuditpolicyCsv 269 | 270 | Mock -CommandName Remove-Item -ParameterFilter { $Path -eq $script:currentAuditpolicyCsv} ` 271 | -MockWith { } -Verifiable 272 | 273 | It 'Should call Remove-Item to clean up temp file' { 274 | Remove-BackupFile -CsvPath $script:csvPath | Should BeNullOrEmpty 275 | Assert-MockCalled -CommandName Remove-Item -Times 1 -Scope Describe 276 | } 277 | 278 | It 'Should call expected Mocks' { 279 | Assert-VerifiableMock 280 | Assert-MockCalled -CommandName Remove-Item -Times 1 -Scope Describe 281 | } 282 | } 283 | } 284 | #endregion 285 | } 286 | finally 287 | { 288 | #region FOOTER 289 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 290 | #endregion 291 | } 292 | -------------------------------------------------------------------------------- /DSCResources/AuditPolicyResourceHelper/AuditPolicyResourceHelper.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | <# 4 | This PS module contains functions for Desired State Configuration (DSC) AuditPolicyDsc provider. 5 | It enables querying, creation, removal and update of Windows advanced audit policies through 6 | Get, Set, and Test operations on DSC managed nodes. 7 | #> 8 | 9 | <# 10 | .SYNOPSIS 11 | Retrieves the localized string data based on the machine's culture. 12 | Falls back to en-US strings if the machine's culture is not supported. 13 | 14 | .PARAMETER ResourceName 15 | The name of the resource as it appears before '.strings.psd1' of the localized string file. 16 | For example: 17 | AuditPolicySubcategory: MSFT_AuditPolicySubcategory 18 | AuditPolicyOption: MSFT_AuditPolicyOption 19 | #> 20 | function Get-LocalizedData { 21 | [CmdletBinding()] 22 | param 23 | ( 24 | [Parameter(Mandatory = $true, ParameterSetName = 'resource')] 25 | [ValidateNotNullOrEmpty()] 26 | [String] 27 | $ResourceName, 28 | 29 | [Parameter(Mandatory = $true, ParameterSetName = 'helper')] 30 | [ValidateNotNullOrEmpty()] 31 | [String] 32 | $HelperName 33 | ) 34 | 35 | # With the helper module just update the name and path variables as if it were a resource. 36 | if ($PSCmdlet.ParameterSetName -eq 'helper') { 37 | $resourceDirectory = $PSScriptRoot 38 | $ResourceName = $HelperName 39 | } 40 | else { 41 | # Step up one additional level to build the correct path to the resource culture. 42 | $resourceDirectory = Join-Path -Path ( Split-Path $PSScriptRoot -Parent ) ` 43 | -ChildPath $ResourceName 44 | } 45 | 46 | $localizedStringFileLocation = Join-Path -Path $resourceDirectory -ChildPath $PSUICulture 47 | 48 | if (-not (Test-Path -Path $localizedStringFileLocation)) { 49 | # Fallback to en-US 50 | $localizedStringFileLocation = Join-Path -Path $resourceDirectory -ChildPath 'en-US' 51 | } 52 | 53 | Import-LocalizedData ` 54 | -BindingVariable 'localizedData' ` 55 | -FileName "$ResourceName.strings.psd1" ` 56 | -BaseDirectory $localizedStringFileLocation 57 | 58 | return $localizedData 59 | } 60 | 61 | <# 62 | .SYNOPSIS 63 | Invoke-AuditPol is a private function that wraps auditpol.exe providing a 64 | centralized function to manage access to and the output of auditpol.exe. 65 | .DESCRIPTION 66 | The function will accept a string to pass to auditpol.exe for execution. Any 'get' or 67 | 'set' opertions can be passed to the central wrapper to execute. All of the 68 | nuances of auditpol.exe can be further broken out into specalized functions that 69 | call Invoke-AuditPol. 70 | 71 | Since the call operator is being used to run auditpol, the input is restricted to only execute 72 | against auditpol.exe. Any input that is an invalid flag or parameter in 73 | auditpol.exe will return an error to prevent abuse of the call. 74 | The call operator will not parse the parameters, so they are split in the function. 75 | .PARAMETER Command 76 | The action that audtipol should take on the subcommand. 77 | .PARAMETER SubCommand 78 | The subcommand to execute. 79 | .OUTPUTS 80 | The raw string output of auditpol.exe with the /r switch to return a CSV string. 81 | .EXAMPLE 82 | Invoke-AuditPol -Command 'Get' -SubCommand 'Subcategory:Logon' 83 | #> 84 | function Invoke-AuditPol { 85 | [OutputType([Object])] 86 | [CmdletBinding()] 87 | param 88 | ( 89 | [Parameter(Mandatory = $true)] 90 | [ValidateSet('Get', 'Set', 'List', 'Restore', 'Backup')] 91 | [String] 92 | $Command, 93 | 94 | [Parameter(Mandatory = $true)] 95 | [String[]] 96 | $SubCommand 97 | ) 98 | 99 | # Localized messages for Write-Verbose statements in this resource 100 | $localizedData = Get-LocalizedData -HelperName 'AuditPolicyResourceHelper' 101 | <# 102 | The raw auditpol data with the /r switch is a 3 line CSV 103 | 0 - header row 104 | 1 - blank row 105 | 2 - the data row we are interested in 106 | #> 107 | 108 | # set the base commands to execute 109 | if ( $Command -eq 'Get') { 110 | $auditpolArguments = @("/$Command", "/$SubCommand", "/r" ) 111 | } 112 | else { 113 | # The set subcommand comes in an array of the subcategory and flag 114 | $auditpolArguments = @("/$Command", "/$($SubCommand[0])", $SubCommand[1] ) 115 | } 116 | 117 | Write-Debug -Message ( $localizedData.ExecuteAuditpolCommand -f $auditpolArguments ) 118 | 119 | try { 120 | # Use System.Diagnostics.Process to process the auditpol command 121 | $process = New-Object System.Diagnostics.Process 122 | $process.StartInfo.Arguments = $auditpolArguments 123 | $process.StartInfo.CreateNoWindow = $true 124 | $process.StartInfo.FileName = 'auditpol.exe' 125 | $process.StartInfo.RedirectStandardOutput = $true 126 | $process.StartInfo.UseShellExecute = $false 127 | $null = $process.Start() 128 | 129 | $auditpolReturn = $process.StandardOutput.ReadToEnd() 130 | 131 | # auditpol does not throw exceptions, so test the results and throw if needed 132 | if ( $process.ExitCode -ne 0 ) { 133 | throw New-Object System.ArgumentException 134 | } 135 | 136 | if ( $Command -notmatch "Restore|Backup" ) { 137 | return ( ConvertFrom-Csv -InputObject $auditpolReturn ) 138 | } 139 | } 140 | catch [System.ComponentModel.Win32Exception] { 141 | # Catch error if the auditpol command is not found on the system 142 | Write-Error -Message $localizedData.AuditpolNotFound 143 | } 144 | catch [System.ArgumentException] { 145 | # Catch the error thrown if the lastexitcode is not 0 146 | [String] $errorString = $error[0].Exception 147 | $errorString = $errorString + "`$LASTEXITCODE = $LASTEXITCODE;" 148 | $errorString = $errorString + " Command = auditpol $commandString" 149 | Write-Error -Message $errorString 150 | } 151 | catch { 152 | # Catch any other errors 153 | Write-Error -Message ( $localizedData.UnknownError -f $error[0] ) 154 | } 155 | } 156 | 157 | <# 158 | .SYNOPSIS 159 | Get-FixedLanguageAuditCSV is a private function that returns the contents of a CSV with US-English names, even if input is not US English 160 | .PARAMETER Path 161 | The path to stage the auditCSV to (defaulted to the temp directory). 162 | FILE MUST EXIST AND BE A VALID AUDIT.CSV FILE, AND THE FIRST LINE MUST BE THE CSV HEADER. 163 | .OUTPUTS 164 | Content from the file converted from CSV to custom objects with US-English property names. 165 | .EXAMPLE 166 | $csv = Get-StagedAuditPolicy 167 | #> 168 | function Get-FixedLanguageAuditCSV { 169 | [OutputType([System.Object[]])] 170 | [CmdletBinding()] 171 | param 172 | ( 173 | [Parameter()] 174 | [String] 175 | $Path = $(Join-Path -Path $env:Temp -ChildPath "audit.csv") 176 | ) 177 | 178 | $headerSet = 179 | "Machine Name", 180 | "Policy Target", 181 | "Subcategory", 182 | "Subcategory GUID", 183 | "Inclusion Setting", 184 | "Exclusion Setting", 185 | "Setting Value" 186 | 187 | return (Get-Content -Path $Path | Select-Object -Skip 1 | ConvertFrom-Csv -Header $headerSet) 188 | } 189 | 190 | <# 191 | .SYNOPSIS 192 | Get-StagedAuditPol is a private function that creates staged AuditPolicy CSVs for usage over several resource blocks 193 | .DESCRIPTION 194 | The function tests if a staged AuditPolicyCSV is available and not out of date. If needed, it creates a new staged CSV 195 | .PARAMETER Path 196 | The path to stage the auditCSV to (defaulted to the temp directory) 197 | .OUTPUTS 198 | The current or newly created Staged CSV. 199 | .EXAMPLE 200 | $csv = Get-StagedAuditPolicy 201 | #> 202 | function Get-StagedAuditPolicyCSV { 203 | [OutputType([System.Object[]])] 204 | [CmdletBinding()] 205 | param 206 | ( 207 | [Parameter()] 208 | [String] 209 | $Path = $(Join-Path -Path $env:Temp -ChildPath "audit.csv") 210 | ) 211 | 212 | # Localized messages for Write-Verbose statements in this resource 213 | $localizedData = Get-LocalizedData -HelperName 'AuditPolicyResourceHelper' 214 | 215 | $auditCSV = Get-Item -Path $Path -ErrorAction SilentlyContinue 216 | if ($null -ne $auditCSV) { 217 | # Determine if the CSV was created more than 5 minutes ago, if it was, delete it and create a new one. 218 | if ((New-TimeSpan -Start $auditCSV.CreationTime -End ([datetime]::Now)).Minutes -ge 5) { 219 | Write-Debug -Message ( $localizedData.AuditCSVOutdated -f $path, $auditCSV.CreationTime) 220 | Try { 221 | Remove-Item -Path $auditCSV -Force 222 | Write-Debug -Message ( $localizedData.AuditCSVDeleted -f $Path) 223 | } 224 | Catch { 225 | Write-Debug -Message ( $localizedData.AuditCSVLocked -f $Path) 226 | Continue 227 | } 228 | } 229 | else { 230 | Write-Debug -Message ( $localizedData.AuditCSVLocked -f $Path) 231 | return Get-FixedLanguageAuditCSV -Path $auditCSV 232 | } 233 | } 234 | 235 | Write-Debug -Message ( $localizedData.AuditCSVNotFound -f $Path) 236 | Invoke-AuditPol -Command "Backup" -SubCommand "file:$Path" 237 | Write-Debug -Message ( $localizedData.AuditCSVCreated -f $auditCSV ) 238 | if (!(Test-Path -Path $Path)) { 239 | $inf = [System.Management.Automation.ItemNotFoundException]::new( ($localizedData.FileNotFound -f $Path), $fnf) 240 | Throw $inf 241 | } 242 | $auditCSV = Get-Item -Path $Path 243 | 244 | return Get-FixedLanguageAuditCSV $auditCSV 245 | } 246 | 247 | # Static Name translation to ensure GUIDS are the source of truth. 248 | ### Hash table to map audit subcategory names (US English) to GUIDs 249 | $AuditSubcategoryToGUIDHash = @{ 250 | ###### Edited from "auditpol /list /subcategory:* /v" 251 | ###### 252 | ######Category/Subcategory GUID 253 | ######System = "69979848-797A-11D9-BED3-505054503030"; 254 | "Security State Change" = "0CCE9210-69AE-11D9-BED3-505054503030"; 255 | "Security System Extension" = "0CCE9211-69AE-11D9-BED3-505054503030"; 256 | "System Integrity" = "0CCE9212-69AE-11D9-BED3-505054503030"; 257 | "IPsec Driver" = "0CCE9213-69AE-11D9-BED3-505054503030"; 258 | "Other System Events" = "0CCE9214-69AE-11D9-BED3-505054503030"; 259 | ######Logon/Logoff = "69979849-797A-11D9-BED3-505054503030"; 260 | "Logon" = "0CCE9215-69AE-11D9-BED3-505054503030"; 261 | "Logoff" = "0CCE9216-69AE-11D9-BED3-505054503030"; 262 | "Account Lockout" = "0CCE9217-69AE-11D9-BED3-505054503030"; 263 | "IPsec Main Mode" = "0CCE9218-69AE-11D9-BED3-505054503030"; 264 | "IPsec Quick Mode" = "0CCE9219-69AE-11D9-BED3-505054503030"; 265 | "IPsec Extended Mode" = "0CCE921A-69AE-11D9-BED3-505054503030"; 266 | "Special Logon" = "0CCE921B-69AE-11D9-BED3-505054503030"; 267 | "Other Logon/Logoff Events" = "0CCE921C-69AE-11D9-BED3-505054503030"; 268 | "Network Policy Server" = "0CCE9243-69AE-11D9-BED3-505054503030"; 269 | "User / Device Claims" = "0CCE9247-69AE-11D9-BED3-505054503030"; 270 | "Group Membership" = "0CCE9249-69AE-11D9-BED3-505054503030"; 271 | ######Object Access = "6997984A-797A-11D9-BED3-505054503030"; 272 | "File System" = "0CCE921D-69AE-11D9-BED3-505054503030"; 273 | "Registry" = "0CCE921E-69AE-11D9-BED3-505054503030"; 274 | "Kernel Object" = "0CCE921F-69AE-11D9-BED3-505054503030"; 275 | "SAM" = "0CCE9220-69AE-11D9-BED3-505054503030"; 276 | "Certification Services" = "0CCE9221-69AE-11D9-BED3-505054503030"; 277 | "Application Generated" = "0CCE9222-69AE-11D9-BED3-505054503030"; 278 | "Handle Manipulation" = "0CCE9223-69AE-11D9-BED3-505054503030"; 279 | "File Share" = "0CCE9224-69AE-11D9-BED3-505054503030"; 280 | "Filtering Platform Packet Drop" = "0CCE9225-69AE-11D9-BED3-505054503030"; 281 | "Filtering Platform Connection" = "0CCE9226-69AE-11D9-BED3-505054503030"; 282 | "Other Object Access Events" = "0CCE9227-69AE-11D9-BED3-505054503030"; 283 | "Detailed File Share" = "0CCE9244-69AE-11D9-BED3-505054503030"; 284 | "Removable Storage" = "0CCE9245-69AE-11D9-BED3-505054503030"; 285 | "Central Policy Staging" = "0CCE9246-69AE-11D9-BED3-505054503030"; 286 | ######Privilege Use = "6997984B-797A-11D9-BED3-505054503030"; 287 | "Sensitive Privilege Use" = "0CCE9228-69AE-11D9-BED3-505054503030"; 288 | "Non Sensitive Privilege Use" = "0CCE9229-69AE-11D9-BED3-505054503030"; 289 | "Other Privilege Use Events" = "0CCE922A-69AE-11D9-BED3-505054503030"; 290 | ######Detailed Tracking = "6997984C-797A-11D9-BED3-505054503030"; 291 | "Process Creation" = "0CCE922B-69AE-11D9-BED3-505054503030"; 292 | "Process Termination" = "0CCE922C-69AE-11D9-BED3-505054503030"; 293 | "DPAPI Activity" = "0CCE922D-69AE-11D9-BED3-505054503030"; 294 | "RPC Events" = "0CCE922E-69AE-11D9-BED3-505054503030"; 295 | "Plug and Play Events" = "0CCE9248-69AE-11D9-BED3-505054503030"; 296 | "Token Right Adjusted Events" = "0CCE924A-69AE-11D9-BED3-505054503030"; 297 | ######Policy Change = "6997984D-797A-11D9-BED3-505054503030"; 298 | "Audit Policy Change" = "0CCE922F-69AE-11D9-BED3-505054503030"; 299 | "Authentication Policy Change" = "0CCE9230-69AE-11D9-BED3-505054503030"; 300 | "Authorization Policy Change" = "0CCE9231-69AE-11D9-BED3-505054503030"; 301 | "MPSSVC Rule-Level Policy Change" = "0CCE9232-69AE-11D9-BED3-505054503030"; 302 | "Filtering Platform Policy Change" = "0CCE9233-69AE-11D9-BED3-505054503030"; 303 | "Other Policy Change Events" = "0CCE9234-69AE-11D9-BED3-505054503030"; 304 | ######Account Management = "6997984E-797A-11D9-BED3-505054503030"; 305 | "User Account Management" = "0CCE9235-69AE-11D9-BED3-505054503030"; 306 | "Computer Account Management" = "0CCE9236-69AE-11D9-BED3-505054503030"; 307 | "Security Group Management" = "0CCE9237-69AE-11D9-BED3-505054503030"; 308 | "Distribution Group Management" = "0CCE9238-69AE-11D9-BED3-505054503030"; 309 | "Application Group Management" = "0CCE9239-69AE-11D9-BED3-505054503030"; 310 | "Other Account Management Events" = "0CCE923A-69AE-11D9-BED3-505054503030"; 311 | ######DS Access = "6997984F-797A-11D9-BED3-505054503030"; 312 | "Directory Service Access" = "0CCE923B-69AE-11D9-BED3-505054503030"; 313 | "Directory Service Changes" = "0CCE923C-69AE-11D9-BED3-505054503030"; 314 | "Directory Service Replication" = "0CCE923D-69AE-11D9-BED3-505054503030"; 315 | "Detailed Directory Service Replication" = "0CCE923E-69AE-11D9-BED3-505054503030"; 316 | ######Account Logon = "69979850-797A-11D9-BED3-505054503030"; 317 | "Credential Validation" = "0CCE923F-69AE-11D9-BED3-505054503030"; 318 | "Kerberos Service Ticket Operations" = "0CCE9240-69AE-11D9-BED3-505054503030"; 319 | "Other Account Logon Events" = "0CCE9241-69AE-11D9-BED3-505054503030"; 320 | "Kerberos Authentication Service" = "0CCE9242-69AE-11D9-BED3-505054503030"; 321 | } 322 | 323 | ### Hash table to map GUIDs to audit subcategory names (US English) 324 | $AuditGUIDToSubCategoryHash = @{} 325 | $AuditSubcategoryToGUIDHash.Keys | ForEach-Object { 326 | $AuditGUIDToSubCategoryHash.Add($AuditSubcategoryToGUIDHash[$_], $_) 327 | } 328 | 329 | 330 | $AuditFlagToSettingValue = @{ 331 | 'No Auditing' = 0 332 | 'Success' = 1 333 | 'Failure' = 2 334 | 'Success and Failure' = 3 335 | } 336 | 337 | $AuditSettingValueToFlag = @( 338 | 'No Auditing', 339 | 'Success', 340 | 'Failure', 341 | 'Success and Failure' 342 | ) 343 | 344 | <# 345 | .SYNOPSIS 346 | Write-StagedAuditCSV is a private function that writes new values to the Staged Audit.CSV and imports them using auditpol 347 | .DESCRIPTION 348 | The function takes a new value to write and combines it with the staged csv. 349 | .PARAMETER Name 350 | The subcategory. 351 | .PARAMETER Flag 352 | The flag the subcategory should be set to. 353 | .PARAMETER Path 354 | The path to stage the auditCSV to (defaulted to the temp directory) 355 | .OUTPUTS 356 | The current or newly created Staged CSV. 357 | .EXAMPLE 358 | Write-StagedAuditCSV -Name 359 | #> 360 | function Write-StagedAuditCSV { 361 | [OutputType([System.Object[]])] 362 | [CmdletBinding()] 363 | param 364 | ( 365 | [Parameter(Mandatory = $true)] 366 | [GUID] 367 | $GUID, 368 | 369 | [Parameter(Mandatory = $true)] 370 | [ValidateRange(0, 4)] 371 | [Int] 372 | $SettingValue, 373 | 374 | [Parameter()] 375 | [String] 376 | $Path = $(Join-Path -Path $env:Temp -ChildPath "audit.csv"), 377 | 378 | [Parameter(Mandatory = $true)] 379 | [ValidateSet("Present", "Absent")] 380 | [String] 381 | $Ensure 382 | ) 383 | 384 | if ($AuditGUIDToSubCategoryHash.ContainsKey($GUID.Guid)) { 385 | $Name = $AuditGUIDToSubCategoryHash[$GUID.Guid] 386 | } 387 | else { 388 | Throw ($localizedData.SubCategoryTranslationFailed -f $GUID) 389 | } 390 | 391 | # translate Present/Absent to inclusion settings 392 | $auditState = [pscustomobject]@{ 393 | 'Inclusion Setting' = '' 394 | 'Exclusion Setting' = '' 395 | } 396 | 397 | $auditFlag = $AuditSettingValueToFlag[$SettingValue] 398 | 399 | # Localized messages for Write-Verbose statements in this resource 400 | $localizedData = Get-LocalizedData -HelperName 'AuditPolicyResourceHelper' 401 | 402 | $auditCSV = Get-StagedAuditPolicyCSV 403 | 404 | $currentValue = $auditCSV.Where( {$_.'SubCategory GUID' -eq "{$($GUID.guid)}"}) 405 | $currentSetting = 0 406 | if ($null -eq $currentValue) { 407 | Write-Debug -Message ($localizedData.CurrentCSVValueMissing -f $GUID) 408 | $currentSetting = 0 409 | } 410 | else { 411 | $currentSetting = $currentValue.'Setting Value' 412 | } 413 | 414 | if ($Ensure -eq "Present") { 415 | $auditState.'Inclusion Setting' = $auditFlag 416 | } 417 | else { 418 | switch ($currentSetting) { 419 | 0 { 420 | # There's no way to set the Absent of No Auditing. 421 | # Should it be Success? Failure? Both? 422 | return 423 | } 424 | 425 | 1 { 426 | if ($currentSetting -eq 1) { 427 | # If Success is absent and the current value is Success, the result is "No Auditing" 428 | $SettingValue = 0 429 | } 430 | elseif ($currentSetting -eq 3) { 431 | # If Success is absent and the current value is Succes and Failure, the result is Failure. 432 | $SettingValue = 2 433 | } 434 | else { 435 | $SettingValue = $currentSetting 436 | } 437 | } 438 | 439 | 2 { 440 | if ($currentSetting -eq 2) { 441 | # If Failure is absent and the current value is Failure, the result is "No Auditing" 442 | $SettingValue = 0 443 | } 444 | elseif ($currentSetting -eq 3) { 445 | # If Success is absent and the current value is Succes and Failure, the result is Success. 446 | $SettingValue = 1 447 | } 448 | else { 449 | $SettingValue = $currentSetting 450 | } 451 | } 452 | 453 | 3 { 454 | # if Success And Failure should be absent, the result is No Auditing 455 | $SettingValue = 0 456 | } 457 | } 458 | 459 | $auditState.'Exclusion Setting' = $auditFlag 460 | } 461 | 462 | $auditCSV = $auditCSV | Where-Object {$_.'Subcategory GUID' -ne "{$($GUID.guid)}" -and !([string]::IsNullOrEmpty($_.'Subcategory GUID'))} 463 | $tmpValue = [pscustomobject][ordered]@{ 464 | 'Machine Name' = $env:ComputerName 465 | 'Policy Target' = "System" 466 | 'Subcategory' = "Audit $Name" 467 | 'SubCategory GUID' = "{$($GUID.guid)}" 468 | 'Inclusion Setting' = $auditState.'Inclusion Setting' 469 | 'ExclusionSetting' = $auditState.'Exclusion Setting' 470 | 'Setting Value' = $SettingValue 471 | } 472 | 473 | $auditCSV += $tmpValue 474 | 475 | Write-Debug -Message ( $localizedData.WriteStagedCSV -f $Guid, $AuditFlag ) 476 | 477 | Try { 478 | $auditCSV | ConvertTo-Csv -NoTypeInformation | ForEach-Object {$_.Replace('"', '')} | Out-File -FilePath $Path -Force 479 | } 480 | Catch { 481 | Throw ($localizedata.SaveAuditCSVFailure -f $Path) 482 | } 483 | 484 | Invoke-AuditPol -Command Restore -SubCommand "file:$Path" 485 | Write-Debug -Message ( $localizedData.RestoredAuditCSV ) 486 | } 487 | 488 | <# 489 | .SYNOPSIS 490 | Returns the list of valid Subcategories. 491 | .DESCRIPTION 492 | This funciton will check if the list of valid subcategories has already been created. 493 | If the list exists it will simply return it. If it doe not exists, it will generate 494 | it and return it. 495 | #> 496 | function Get-ValidSubcategoryList { 497 | [OutputType([String[]])] 498 | [CmdletBinding()] 499 | param () 500 | 501 | if ( $null -eq $script:validSubcategoryList ) { 502 | $script:validSubcategoryList = @() 503 | 504 | # Populating $validSubcategoryList uses Invoke-AuditPol and needs to follow the definition. 505 | # Populating $validSubcategoryList uses Invoke-AuditPol and needs to follow the definition. 506 | $script:validSubcategoryList = Invoke-AuditPol -Command Get -SubCommand "category:*" | 507 | Select-Object -Property Subcategory -ExpandProperty Subcategory 508 | } 509 | 510 | return $script:validSubcategoryList 511 | } 512 | 513 | <# 514 | .SYNOPSIS 515 | Verifies that the Subcategory is valid. 516 | .PARAMETER Name 517 | The name of the Subcategory to validate. 518 | #> 519 | function Test-ValidSubcategory { 520 | [OutputType([Boolean])] 521 | [CmdletBinding()] 522 | param 523 | ( 524 | [Parameter(Mandatory = $true)] 525 | [String] 526 | $Name 527 | ) 528 | 529 | if ( ( Get-ValidSubcategoryList ) -icontains $Name ) { 530 | return $true 531 | } 532 | else { 533 | return $false 534 | } 535 | } 536 | 537 | Export-ModuleMember -Variable AuditSubCategorytoGUIDHash, AuditGUIDTOSubCategoryHash, AuditFlagToSettingValue, AuditSettingValueToFlag -Function @( 'Invoke-AuditPol', 'Get-LocalizedData', 'Write-StagedAuditCSV', 'Get-StagedAuditPolicyCSV', 'Get-FixedLanguageAuditCSV', 538 | 'Test-ValidSubcategory' ) 539 | -------------------------------------------------------------------------------- /Tests/Unit/MSFT_AuditPolicySubcategory.tests.ps1: -------------------------------------------------------------------------------- 1 | $script:DSCModuleName = 'AuditPolicyDsc' 2 | $script:DSCResourceName = 'MSFT_AuditPolicySubcategory' 3 | 4 | #region HEADER 5 | [String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $script:MyInvocation.MyCommand.Path)) 6 | if ( (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` 7 | (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) 8 | { 9 | & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\')) 10 | } 11 | else 12 | { 13 | & git @('-C',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\'),'pull') 14 | } 15 | Import-Module (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force 16 | $TestEnvironment = Initialize-TestEnvironment ` 17 | -DSCModuleName $script:DSCModuleName ` 18 | -DSCResourceName $script:DSCResourceName ` 19 | -TestType Unit 20 | #endregion 21 | 22 | # Begin Testing 23 | try 24 | { 25 | #region Pester Tests 26 | 27 | InModuleScope $script:DSCResourceName { 28 | 29 | # The script scope does not pierce the InModuleScope 30 | $script:DSCResourceName = 'MSFT_AuditPolicySubcategory' 31 | 32 | Describe "$($script:DSCResourceName)\Get-TargetResource" { 33 | 34 | $testParameters = @{ 35 | Name = 'Logon' 36 | AuditFlag = 'Success' 37 | } 38 | 39 | Context "Single word subcategory submit 'Success' and return 'Success'" { 40 | 41 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 42 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 43 | 44 | It 'Should not throw an exception' { 45 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 46 | Should Not Throw 47 | } 48 | 49 | It 'Should return the correct hashtable properties' { 50 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 51 | $script:getTargetResourceResult.AuditFlag | Should Be 'Success' 52 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 53 | } 54 | 55 | It 'Should call expected Mocks' { 56 | Assert-VerifiableMock 57 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 58 | } 59 | } 60 | 61 | Context "Single word subcategory submit 'Success' and return 'Failure'" { 62 | 63 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Failure' } ` 64 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 65 | 66 | It 'Should not throw an exception' { 67 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 68 | Should Not Throw 69 | } 70 | 71 | It 'Should return the correct hashtable properties from a Single word subcategory' { 72 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 73 | $script:getTargetResourceResult.AuditFlag | Should Be 'Failure' 74 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 75 | } 76 | 77 | It 'Should call expected Mocks' { 78 | Assert-VerifiableMock 79 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 80 | } 81 | } 82 | 83 | Context "Single word subcategory submit 'Success' and return 'NoAuditing'" { 84 | 85 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'NoAuditing' } ` 86 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 87 | 88 | It 'Should not throw an exception' { 89 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 90 | Should Not Throw 91 | } 92 | 93 | It 'Should return the correct hashtable properties' { 94 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 95 | $script:getTargetResourceResult.AuditFlag | Should Be 'NoAuditing' 96 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 97 | } 98 | 99 | It 'Should call expected Mocks' { 100 | Assert-VerifiableMock 101 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 102 | } 103 | } 104 | 105 | Context "Single word subcategory submit 'Success' and return 'SuccessandFailure'" { 106 | 107 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'SuccessandFailure' } ` 108 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 109 | 110 | It 'Should not throw an exception' { 111 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 112 | Should Not Throw 113 | } 114 | 115 | It 'Should return the correct hashtable properties' { 116 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 117 | $script:getTargetResourceResult.AuditFlag | Should Be 'Success' 118 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 119 | } 120 | 121 | It 'Should call expected Mocks' { 122 | Assert-VerifiableMock 123 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 124 | } 125 | } 126 | 127 | $testParameters.AuditFlag = 'Failure' 128 | 129 | Context "Single word subcategory submit 'Failure' and return 'Success'" { 130 | 131 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 132 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 133 | 134 | It 'Should not throw an exception' { 135 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 136 | Should Not Throw 137 | } 138 | 139 | It 'Should return the correct hashtable properties' { 140 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 141 | $script:getTargetResourceResult.AuditFlag | Should Be 'Success' 142 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 143 | } 144 | 145 | It 'Should call expected Mocks' { 146 | Assert-VerifiableMock 147 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 148 | } 149 | } 150 | 151 | Context "Single word subcategory submit 'Failure' and return 'Failure'" { 152 | 153 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Failure' } ` 154 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 155 | 156 | It 'Should not throw an exception' { 157 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 158 | Should Not Throw 159 | } 160 | 161 | It 'Should return the correct hashtable properties from a Single word subcategory' { 162 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 163 | $script:getTargetResourceResult.AuditFlag | Should Be 'Failure' 164 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 165 | } 166 | 167 | It 'Should call expected Mocks' { 168 | Assert-VerifiableMock 169 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 170 | } 171 | } 172 | 173 | Context "Single word subcategory submit 'Failure' and return 'NoAuditing'" { 174 | 175 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'NoAuditing' } ` 176 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 177 | 178 | It 'Should not throw an exception' { 179 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 180 | Should Not Throw 181 | } 182 | 183 | It 'Should return the correct hashtable properties' { 184 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 185 | $script:getTargetResourceResult.AuditFlag | Should Be 'NoAuditing' 186 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 187 | } 188 | 189 | It 'Should call expected Mocks' { 190 | Assert-VerifiableMock 191 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 192 | } 193 | } 194 | 195 | Context "Single word subcategory submit 'Failure' and return 'SuccessandFailure'" { 196 | 197 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'SuccessandFailure' } ` 198 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 199 | 200 | It 'Should not throw an exception' { 201 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 202 | Should Not Throw 203 | } 204 | 205 | It 'Should return the correct hashtable properties' { 206 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 207 | $script:getTargetResourceResult.AuditFlag | Should Be 'Failure' 208 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 209 | } 210 | 211 | It 'Should call expected Mocks' { 212 | Assert-VerifiableMock 213 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 214 | } 215 | } 216 | 217 | $testParameters.Name = 'Credential Validation' 218 | $testParameters.AuditFlag = 'Success' 219 | 220 | Context "Mulit-word subcategory submit 'Success' and return 'Success'" { 221 | 222 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 223 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 224 | 225 | It 'Should not throw an exception' { 226 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 227 | Should Not Throw 228 | } 229 | 230 | It 'Should return the correct hashtable properties' { 231 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 232 | $script:getTargetResourceResult.AuditFlag | Should Be 'Success' 233 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 234 | } 235 | 236 | It 'Should call expected Mocks' { 237 | Assert-VerifiableMock 238 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 239 | } 240 | } 241 | 242 | Context "Mulit-word subcategory submit 'Success' and return 'Failure'" { 243 | 244 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Failure' } ` 245 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 246 | 247 | It 'Should not throw an exception' { 248 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 249 | Should Not Throw 250 | } 251 | 252 | It 'Should return the correct hashtable properties' { 253 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 254 | $script:getTargetResourceResult.AuditFlag | Should Be 'Failure' 255 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 256 | } 257 | 258 | It 'Should call expected Mocks' { 259 | Assert-VerifiableMock 260 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 261 | } 262 | } 263 | 264 | Context "Mulit-word subcategory submit 'Success' and return 'NoAuditing'" { 265 | 266 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'NoAuditing' } ` 267 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 268 | 269 | It 'Should not throw an exception' { 270 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 271 | Should Not Throw 272 | } 273 | 274 | It 'Should return the correct hashtable properties' { 275 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 276 | $script:getTargetResourceResult.AuditFlag | Should Be 'NoAuditing' 277 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 278 | } 279 | 280 | It 'Should call expected Mocks' { 281 | Assert-VerifiableMock 282 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 283 | } 284 | } 285 | 286 | Context "Mulit-word subcategory submit 'Success' and return 'SuccessandFailure'" { 287 | 288 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'SuccessandFailure' } ` 289 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 290 | 291 | It 'Should not throw an exception' { 292 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 293 | Should Not Throw 294 | } 295 | 296 | It 'Should return the correct hashtable properties' { 297 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 298 | $script:getTargetResourceResult.AuditFlag | Should Be 'Success' 299 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 300 | } 301 | 302 | It 'Should call expected Mocks' { 303 | Assert-VerifiableMock 304 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 305 | } 306 | } 307 | 308 | $testParameters.AuditFlag = 'Failure' 309 | 310 | Context "Mulit-word subcategory submit 'Failure' and return 'Success'" { 311 | 312 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 313 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 314 | 315 | It 'Should not throw an exception' { 316 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 317 | Should Not Throw 318 | } 319 | 320 | It 'Should return the correct hashtable properties' { 321 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 322 | $script:getTargetResourceResult.AuditFlag | Should Be 'Success' 323 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 324 | } 325 | 326 | It 'Should call expected Mocks' { 327 | Assert-VerifiableMock 328 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 329 | } 330 | } 331 | 332 | Context "Mulit-word subcategory submit 'Failure' and return 'Failure'" { 333 | 334 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Failure' } ` 335 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 336 | 337 | It 'Should not throw an exception' { 338 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 339 | Should Not Throw 340 | } 341 | 342 | It 'Should return the correct hashtable properties from a Single word subcategory' { 343 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 344 | $script:getTargetResourceResult.AuditFlag | Should Be 'Failure' 345 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 346 | } 347 | 348 | It 'Should call expected Mocks' { 349 | Assert-VerifiableMock 350 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 351 | } 352 | } 353 | 354 | Context "Mulit-word subcategory submit 'Failure' and return 'NoAuditing'" { 355 | 356 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'NoAuditing' } ` 357 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 358 | 359 | It 'Should not throw an exception' { 360 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 361 | Should Not Throw 362 | } 363 | 364 | It 'Should return the correct hashtable properties' { 365 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 366 | $script:getTargetResourceResult.AuditFlag | Should Be 'NoAuditing' 367 | $script:getTargetResourceResult.Ensure | Should Be 'Absent' 368 | } 369 | 370 | It 'Should call expected Mocks' { 371 | Assert-VerifiableMock 372 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 373 | } 374 | } 375 | 376 | Context "Mulit-word subcategory submit 'Failure' and return 'SuccessandFailure'" { 377 | 378 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'SuccessandFailure' } ` 379 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 380 | 381 | It 'Should not throw an exception' { 382 | { $script:getTargetResourceResult = Get-TargetResource @testParameters } | 383 | Should Not Throw 384 | } 385 | 386 | It 'Should return the correct hashtable properties' { 387 | $script:getTargetResourceResult.Name | Should Be $testParameters.Name 388 | $script:getTargetResourceResult.AuditFlag | Should Be 'Failure' 389 | $script:getTargetResourceResult.Ensure | Should Be 'Present' 390 | } 391 | 392 | It 'Should call expected Mocks' { 393 | Assert-VerifiableMock 394 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 395 | } 396 | } 397 | } 398 | 399 | Describe "$($script:DSCResourceName)\Test-TargetResource" { 400 | 401 | Mock -CommandName Test-ValidSubcategory -MockWith { return $true } ` 402 | -ModuleName MSFT_AuditPolicySubcategory 403 | 404 | $testParameters = @{ 405 | Name = 'Invalid' 406 | AuditFlag = 'Success' 407 | Ensure = 'Present' 408 | } 409 | 410 | Context 'Invalid subcategory' { 411 | 412 | Mock -CommandName Get-AuditSubcategory -MockWith { } ` 413 | -ModuleName MSFT_AuditPolicySubcategory 414 | 415 | It 'Should throw an exception' { 416 | { $getTargetResourceResult = Get-TargetResource @testParameters } | 417 | Should Throw 418 | } 419 | 420 | It 'Should NOT call expected Mocks' { 421 | Assert-MockCalled -CommandName Get-AuditSubcategory -Times 0 422 | } 423 | } 424 | 425 | # Update the Subcategory to a valid name 426 | $testParameters.Name = 'Logon' 427 | 428 | Context 'Single word subcategory Success flag present and should be' { 429 | 430 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 431 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 432 | 433 | It 'Should not throw an exception' { 434 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 435 | Should Not Throw 436 | } 437 | 438 | It 'Should return true' { 439 | $script:testTargetResourceResult | Should Be $true 440 | } 441 | 442 | It 'Should call expected Mocks' { 443 | Assert-VerifiableMock 444 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 445 | } 446 | } 447 | 448 | Context 'Single word subcategory Success flag present and should not be' { 449 | 450 | $testParameters.Ensure = 'Absent' 451 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 452 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 453 | 454 | It 'Should not throw an exception' { 455 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | Should Not Throw 456 | } 457 | 458 | It 'Should return false' { 459 | $script:testTargetResourceResult | Should Be $false 460 | } 461 | 462 | It 'Should call expected Mocks' { 463 | Assert-VerifiableMock 464 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 465 | } 466 | } 467 | 468 | $testParameters.AuditFlag = 'Failure' 469 | 470 | Context 'Single word subcategory failure flag present and should be' { 471 | 472 | $testParameters.Ensure = 'Present' 473 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'failure' } ` 474 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 475 | 476 | It 'Should not throw an exception' { 477 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 478 | Should Not Throw 479 | } 480 | 481 | It 'Should return true' { 482 | $script:testTargetResourceResult | Should Be $true 483 | } 484 | 485 | It 'Should call expected Mocks' { 486 | Assert-VerifiableMock 487 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 488 | } 489 | } 490 | 491 | Context 'Single word subcategory failure flag present and should not be' { 492 | 493 | $testParameters.Ensure = 'Absent' 494 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'failure' } ` 495 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 496 | 497 | It 'Should not throw an exception' { 498 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | Should Not Throw 499 | } 500 | 501 | It 'Should return false' { 502 | $script:testTargetResourceResult | Should Be $false 503 | } 504 | 505 | It 'Should call expected Mocks' { 506 | Assert-VerifiableMock 507 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 508 | } 509 | } 510 | 511 | $testParameters.AuditFlag = 'Success' 512 | $testParameters.Name = 'Credential Validation' 513 | 514 | Context 'Multi-word subcategory Success flag present and should be' { 515 | 516 | $testParameters.Ensure = 'Present' 517 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 518 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 519 | 520 | It 'Should not throw an exception' { 521 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 522 | Should Not Throw 523 | } 524 | 525 | It 'Should return true' { 526 | $script:testTargetResourceResult | Should Be $true 527 | } 528 | 529 | It 'Should call expected Mocks' { 530 | Assert-VerifiableMock 531 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 532 | } 533 | } 534 | 535 | Context 'Multi-word subcategory Success flag present and should not be' { 536 | 537 | $testParameters.Ensure = 'Absent' 538 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'Success' } ` 539 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 540 | 541 | It 'Should not throw an exception' { 542 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | Should Not Throw 543 | } 544 | 545 | It 'Should return false' { 546 | $script:testTargetResourceResult | Should Be $false 547 | } 548 | 549 | It 'Should call expected Mocks' { 550 | Assert-VerifiableMock 551 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 552 | } 553 | } 554 | 555 | $testParameters.AuditFlag = 'Failure' 556 | 557 | Context 'Multi-word subcategory failure flag present and should be' { 558 | 559 | $testParameters.Ensure = 'Present' 560 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'failure' } ` 561 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 562 | 563 | It 'Should not throw an exception' { 564 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | 565 | Should Not Throw 566 | } 567 | 568 | It 'Should return true' { 569 | $script:testTargetResourceResult | Should Be $true 570 | } 571 | 572 | It 'Should call expected Mocks' { 573 | Assert-VerifiableMock 574 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 575 | } 576 | } 577 | 578 | Context 'Multi-word subcategory failure flag present and should not be' { 579 | 580 | $testParameters.Ensure = 'Absent' 581 | Mock -CommandName Get-AuditSubcategory -MockWith { return 'failure' } ` 582 | -ModuleName MSFT_AuditPolicySubcategory -Verifiable 583 | 584 | It 'Should not throw an exception' { 585 | { $script:testTargetResourceResult = Test-TargetResource @testParameters } | Should Not Throw 586 | } 587 | 588 | It 'Should return false' { 589 | $script:testTargetResourceResult | Should Be $false 590 | } 591 | 592 | It 'Should call expected Mocks' { 593 | Assert-VerifiableMock 594 | Assert-MockCalled -CommandName Get-AuditSubcategory -Exactly 1 595 | } 596 | } 597 | } 598 | 599 | Describe "$($script:DSCResourceName)\Set-TargetResource" { 600 | 601 | Mock -CommandName Test-ValidSubcategory -MockWith { return $true } ` 602 | -ModuleName MSFT_AuditPolicySubcategory 603 | 604 | $testParameters = @{ 605 | Name = 'Logon' 606 | AuditFlag = 'Success' 607 | Ensure = 'Present' 608 | } 609 | 610 | Context 'Set single word subcategory success flag to present' { 611 | 612 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 613 | 614 | It 'Should not throw an exception' { 615 | { Set-TargetResource @testParameters } | Should Not Throw 616 | } 617 | 618 | It 'Should call expected Mocks' { 619 | Assert-VerifiableMock 620 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 621 | } 622 | } 623 | 624 | Context 'Set single word subcategory failure flag to present' { 625 | 626 | $testParameters.AuditFlag = 'Failure' 627 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 628 | 629 | It 'Should not throw an exception' { 630 | { Set-TargetResource @testParameters } | Should Not Throw 631 | } 632 | 633 | It 'Should call expected Mocks' { 634 | Assert-VerifiableMock 635 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 636 | } 637 | } 638 | 639 | Context 'Set single word subcategory success flag to absent' { 640 | 641 | $testParameters.Ensure = 'Absent' 642 | $testParameters.AuditFlag = 'Success' 643 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 644 | 645 | It 'Should not throw an exception' { 646 | { Set-TargetResource @testParameters } | Should Not Throw 647 | } 648 | 649 | It 'Should call expected Mocks' { 650 | Assert-VerifiableMock 651 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 652 | } 653 | } 654 | 655 | Context 'Set single word subcategory failure flag to absent' { 656 | 657 | $testParameters.AuditFlag = 'Failure' 658 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 659 | 660 | It 'Should not throw an exception' { 661 | { Set-TargetResource @testParameters } | Should Not Throw 662 | } 663 | 664 | It 'Should call expected Mocks' { 665 | Assert-VerifiableMock 666 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 667 | } 668 | } 669 | 670 | Context 'Set multi-word subcategory success flag to present' { 671 | 672 | $testParameters.Name = 'Credential Validation' 673 | $testParameters.AuditFlag = 'Success' 674 | $testParameters.Ensure = 'Present' 675 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 676 | 677 | It 'Should not throw an exception' { 678 | { Set-TargetResource @testParameters } | Should Not Throw 679 | } 680 | 681 | It 'Should call expected Mocks' { 682 | Assert-VerifiableMock 683 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 684 | } 685 | } 686 | 687 | Context 'Set multi-word subcategory failure flag to present' { 688 | 689 | $testParameters.AuditFlag = 'Failure' 690 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 691 | 692 | It 'Should not throw an exception' { 693 | { Set-TargetResource @testParameters } | Should Not Throw 694 | } 695 | 696 | It 'Should call expected Mocks' { 697 | Assert-VerifiableMock 698 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 699 | } 700 | } 701 | 702 | Context 'Set single word subcategory success flag to absent' { 703 | 704 | $testParameters.AuditFlag = 'Success' 705 | $testParameters.Ensure = 'Absent' 706 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 707 | 708 | It 'Should not throw an exception' { 709 | { Set-TargetResource @testParameters } | Should Not Throw 710 | } 711 | 712 | It 'Should call expected Mocks' { 713 | Assert-VerifiableMock 714 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 715 | } 716 | } 717 | 718 | Context 'Set single word subcategory failure flag to absent' { 719 | 720 | $testParameters.AuditFlag = 'Failure' 721 | Mock -CommandName Set-AuditSubcategory -MockWith { } -Verifiable 722 | 723 | It 'Should not throw an exception' { 724 | { Set-TargetResource @testParameters } | Should Not Throw 725 | } 726 | 727 | It 'Should call expected Mocks' { 728 | Assert-VerifiableMock 729 | Assert-MockCalled -CommandName Set-AuditSubcategory -Exactly 1 730 | } 731 | } 732 | } 733 | 734 | Describe 'Function Get-AuditSubcategory' { 735 | 736 | [String] $subCategory = 'Logon' 737 | [String] $subCategoryGuid = '{0CCE9215-69AE-11D9-BED3-505054503030}' 738 | Context 'Get single word audit category success flag' { 739 | 740 | [String] $auditFlag = 'Success' 741 | <# 742 | The return is 3 lines Header, blank line, data 743 | ComputerName,System,Subcategory,GUID,AuditFlags 744 | #> 745 | Mock -CommandName Invoke-Auditpol -MockWith { 746 | @{ 747 | 'Machine Name'= $env:COMPUTERNAME 748 | 'Policy Target' = 'System' 749 | 'Subcategory' = $subCategory 750 | 'Subcategory GUID' = $subCategoryGuid 751 | 'Inclusion Setting' = $auditFlag 752 | 'Exclusion Setting' = '' 753 | } 754 | } -ParameterFilter { $Command -eq 'Get' } -Verifiable 755 | 756 | It 'Should not throw an exception' { 757 | { $script:getAuditCategoryResult = Get-AuditSubcategory -Name $subCategory } | 758 | Should Not Throw 759 | } 760 | 761 | It 'Should return the correct value' { 762 | $script:getAuditCategoryResult | Should Be $auditFlag 763 | } 764 | 765 | It 'Should call expected Mocks' { 766 | Assert-VerifiableMock 767 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 768 | } 769 | } 770 | 771 | Context 'Get single word audit category failure flag' { 772 | 773 | [String] $auditFlag = 'failure' 774 | <# 775 | The return is 3 lines Header, blank line, data 776 | ComputerName,System,Subcategory,GUID,AuditFlags 777 | #> 778 | Mock -CommandName Invoke-Auditpol -MockWith { 779 | @{ 780 | 'Machine Name'= $env:COMPUTERNAME 781 | 'Policy Target' = 'System' 782 | 'Subcategory' = $subCategory 783 | 'Subcategory GUID' = $subCategoryGuid 784 | 'Inclusion Setting' = $auditFlag 785 | 'Exclusion Setting' = '' 786 | } 787 | } -ParameterFilter { $Command -eq 'Get' } -Verifiable 788 | 789 | It 'Should not throw an exception' { 790 | { $script:getAuditCategoryResult = Get-AuditSubcategory -Name $subCategory } | 791 | Should Not Throw 792 | } 793 | 794 | It 'Should return the correct value' { 795 | $script:getAuditCategoryResult | Should Be $auditFlag 796 | } 797 | 798 | It 'Should call expected Mocks' { 799 | Assert-VerifiableMock 800 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 801 | } 802 | } 803 | 804 | [String] $subCategory = 'Credential Validation' 805 | [String] $subCategoryGuid = '{0CCE923F-69AE-11D9-BED3-505054503030}' 806 | Context 'Get single word audit category success flag' { 807 | 808 | [String] $auditFlag = 'Success' 809 | # the return is 3 lines Header, blank line, data 810 | # ComputerName,System,Subcategory,GUID,AuditFlags 811 | Mock -CommandName Invoke-Auditpol -MockWith { 812 | @{ 813 | 'Machine Name'= $env:COMPUTERNAME 814 | 'Policy Target' = 'System' 815 | 'Subcategory' = $subCategory 816 | 'Subcategory GUID' = $subCategoryGuid 817 | 'Inclusion Setting' = $auditFlag 818 | 'Exclusion Setting' = '' 819 | } 820 | } -ParameterFilter { $Command -eq 'Get' } -Verifiable 821 | 822 | It 'Should not throw an exception' { 823 | { $script:getAuditCategoryResult = Get-AuditSubcategory -Name $subCategory } | 824 | Should Not Throw 825 | } 826 | 827 | It 'Should return the correct value' { 828 | $script:getAuditCategoryResult | Should Be $auditFlag 829 | } 830 | 831 | It 'Should call expected Mocks' { 832 | Assert-VerifiableMock 833 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 834 | } 835 | } 836 | 837 | Context 'Get single word audit category failure flag' { 838 | 839 | [String] $auditFlag = 'failure' 840 | # the return is 3 lines Header, blank line, data 841 | # ComputerName,System,Subcategory,GUID,AuditFlags 842 | Mock -CommandName Invoke-Auditpol -MockWith { 843 | @{ 844 | 'Machine Name'= $env:COMPUTERNAME 845 | 'Policy Target' = 'System' 846 | 'Subcategory' = $subCategory 847 | 'Subcategory GUID' = $subCategoryGuid 848 | 'Inclusion Setting' = $auditFlag 849 | 'Exclusion Setting' = '' 850 | } 851 | } -ParameterFilter { $Command -eq 'Get' } -Verifiable 852 | 853 | It 'Should not throw an exception' { 854 | { $script:getAuditCategoryResult = Get-AuditSubcategory -Name $subCategory } | 855 | Should Not Throw 856 | } 857 | 858 | It 'Should return the correct value' { 859 | $script:getAuditCategoryResult | Should Be $auditFlag 860 | } 861 | 862 | It 'Should call expected Mocks' { 863 | Assert-VerifiableMock 864 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 865 | } 866 | } 867 | } 868 | 869 | Describe 'Function Set-AuditSubcategory' { 870 | 871 | Context 'Set single word audit category Success flag to Present' { 872 | 873 | Mock -CommandName Invoke-Auditpol -MockWith { } -ParameterFilter { 874 | $Command -eq 'Set' } -Verifiable 875 | 876 | $comamnd = @{ 877 | Name = "Logon" 878 | AuditFlag = "Success" 879 | Ensure = "Present" 880 | } 881 | 882 | It 'Should not throw an error' { 883 | { Set-AuditSubcategory @comamnd } | Should Not Throw 884 | } 885 | 886 | It 'Should call expected Mocks' { 887 | Assert-VerifiableMock 888 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 889 | } 890 | } 891 | 892 | Context 'Set single word audit category Success flag to Absent' { 893 | 894 | Mock -CommandName Invoke-Auditpol -MockWith { } -ParameterFilter { 895 | $Command -eq 'Set' } -Verifiable 896 | 897 | $comamnd = @{ 898 | Name = "Logon" 899 | AuditFlag = "Success" 900 | Ensure = "Absent" 901 | } 902 | 903 | It 'Should not throw an exception' { 904 | { Set-AuditSubcategory @comamnd } | Should Not Throw 905 | } 906 | 907 | It 'Should call expected Mocks' { 908 | Assert-VerifiableMock 909 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 910 | } 911 | } 912 | 913 | Context 'Set multi-word audit category Success flag to Present' { 914 | 915 | Mock -CommandName Invoke-Auditpol -MockWith { } -ParameterFilter { 916 | $Command -eq 'Set' } -Verifiable 917 | 918 | $comamnd = @{ 919 | Name = "Object Access" 920 | AuditFlag = "Success" 921 | Ensure = "Present" 922 | } 923 | 924 | It 'Should not throw an exception' { 925 | { Set-AuditSubcategory @comamnd } | Should Not Throw 926 | } 927 | 928 | It 'Should call expected Mocks' { 929 | Assert-VerifiableMock 930 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 931 | } 932 | } 933 | 934 | Context 'Set multi-word audit category Success flag to Absent' { 935 | 936 | Mock -CommandName Invoke-Auditpol -MockWith { } -ParameterFilter { 937 | $Command -eq 'Set' } -Verifiable 938 | 939 | $comamnd = @{ 940 | Name = "Object Access" 941 | AuditFlag = "Success" 942 | Ensure = "Absent" 943 | } 944 | 945 | It 'Should not throw an exception' { 946 | { Set-AuditSubcategory @comamnd } | Should Not Throw 947 | } 948 | 949 | It 'Should call expected Mocks' { 950 | Assert-VerifiableMock 951 | Assert-MockCalled -CommandName Invoke-Auditpol -Exactly 1 952 | } 953 | } 954 | } 955 | } 956 | #endregion 957 | } 958 | finally 959 | { 960 | #region FOOTER 961 | Restore-TestEnvironment -TestEnvironment $TestEnvironment 962 | #endregion 963 | } 964 | --------------------------------------------------------------------------------