From cf6f6d09db1a1eb4511486ca7f55163e18c30197 Mon Sep 17 00:00:00 2001 From: nwsparks Date: Mon, 4 Dec 2017 17:42:36 -0500 Subject: [PATCH] new windows module win_audit_policy_system (#31046) * new windows module win_audit_policy_system * removed the backup/restore functionality adjusted to use run-command rather than running the command directly adjusted testing appropriately for the above changes * fixed issue with variable naming in testing removed .psm1 from requires fixed copyright * Updated audit_type to list and added appropriate error handling Updated testing accordingly Fixed up documentation --- .../windows/win_audit_policy_system.ps1 | 142 ++++++++++++++++++ .../windows/win_audit_policy_system.py | 68 +++++++++ .../targets/win_audit_policy_system/aliases | 1 + .../win_audit_policy_system/defaults/main.yml | 3 + .../win_audit_policy_system/tasks/add.yml | 108 +++++++++++++ .../win_audit_policy_system/tasks/main.yml | 25 +++ .../win_audit_policy_system/tasks/remove.yml | 96 ++++++++++++ 7 files changed, 443 insertions(+) create mode 100644 lib/ansible/modules/windows/win_audit_policy_system.ps1 create mode 100644 lib/ansible/modules/windows/win_audit_policy_system.py create mode 100644 test/integration/targets/win_audit_policy_system/aliases create mode 100644 test/integration/targets/win_audit_policy_system/defaults/main.yml create mode 100644 test/integration/targets/win_audit_policy_system/tasks/add.yml create mode 100644 test/integration/targets/win_audit_policy_system/tasks/main.yml create mode 100644 test/integration/targets/win_audit_policy_system/tasks/remove.yml diff --git a/lib/ansible/modules/windows/win_audit_policy_system.ps1 b/lib/ansible/modules/windows/win_audit_policy_system.ps1 new file mode 100644 index 00000000000..e50a6243d64 --- /dev/null +++ b/lib/ansible/modules/windows/win_audit_policy_system.ps1 @@ -0,0 +1,142 @@ +#!powershell +# Copyright: (c) 2017, Noah Sparks +# Copyright: (c) 2017, Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#Requires -Module Ansible.ModuleUtils.Legacy +#Requires -Module Ansible.ModuleUtils.CommandUtil + +$ErrorActionPreference = 'Stop' + +$params = Parse-Args -arguments $args -supports_check_mode $true +$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false + +$results = @{ + changed = $false +} + +###################################### +### populate sets for -validateset ### +###################################### +$categories_rc = run-command -command 'auditpol /list /category /r' +$subcategories_rc = run-command -command 'auditpol /list /subcategory:* /r' + +If ($categories_rc.item('rc') -eq 0) +{ + $categories = ConvertFrom-Csv $categories_rc.item('stdout') | Select-Object -expand Category* +} +Else +{ + Fail-Json -obj $results -message "Failed to retrive audit policy categories. Please make sure the auditpol command is functional on + the system and that the account ansible is running under is able to retrieve them. $($_.Exception.Message)" +} + +If ($subcategories_rc.item('rc') -eq 0) +{ + $subcategories = ConvertFrom-Csv $subcategories_rc.item('stdout') | Select-Object -expand Category* | + Where-Object {$_ -notin $categories} +} +Else +{ + Fail-Json -obj $results -message "Failed to retrive audit policy subcategories. Please make sure the auditpol command is functional on + the system and that the account ansible is running under is able to retrieve them. $($_.Exception.Message)" +} + +###################### +### ansible params ### +###################### +$category = Get-AnsibleParam -obj $params -name "category" -type "str" -ValidateSet $categories +$subcategory = Get-AnsibleParam -obj $params -name "subcategory" -type "str" -ValidateSet $subcategories +$audit_type = Get-AnsibleParam -obj $params -name "audit_type" -type "list" -failifempty - + +######################## +### Start Processing ### +######################## +Function Get-AuditPolicy ($GetString) { + $auditpolcsv = Run-Command -command $GetString + If ($auditpolcsv.item('rc') -eq 0) + { + $Obj = ConvertFrom-CSV $auditpolcsv.item('stdout') | Select-Object @{n='subcategory';e={$_.Subcategory.ToLower()}}, + @{n='audit_type';e={$_."Inclusion Setting".ToLower()}} + } + Else { + return $auditpolcsv.item('stderr') + } + + $HT = @{} + Foreach ( $Item in $Obj ) + { + $HT.Add($Item.subcategory,$Item.audit_type) + } + $HT +} + +################ +### Validate ### +################ + +#make sure category and subcategory are valid +If (-Not $category -and -Not $subcategory) {Fail-Json -obj $results -message "You must provide either a Category or Subcategory parameter"} +If ($category -and $subcategory) {Fail-Json -obj $results -message "Must pick either a specific subcategory or category. You cannot define both"} + + +$possible_audit_types = 'success','failure','none' +$audit_type | ForEach-Object { + If ($_ -notin $possible_audit_types) + { + Fail-Json -obj $result -message "$_ is not a valid audit_type. Please choose from $($possible_audit_types -join ',')" + } +} + +############################################################# +### build lists for setting, getting, and comparing rules ### +############################################################# +$audit_type_string = $audit_type -join ' and ' + +$SetString = 'auditpol /set' +$GetString = 'auditpol /get /r' + +If ($category) {$SetString = "$SetString /category:`"$category`""; $GetString = "$GetString /category:`"$category`""} +If ($subcategory) {$SetString= "$SetString /subcategory:`"$subcategory`""; $GetString = "$GetString /subcategory:`"$subcategory`""} + + +Switch ($audit_type_string) +{ + 'success and failure' {$SetString = "$SetString /success:enable /failure:enable"; $audit_type_check = $audit_type_string} + 'failure' {$SetString = "$SetString /success:disable /failure:enable"; $audit_type_check = $audit_type_string} + 'success' {$SetString = "$SetString /success:enable /failure:disable"; $audit_type_check = $audit_type_string} + 'none' {$SetString = "$SetString /success:disable /failure:disable"; $audit_type_check = 'No Auditing'} + default {Fail-Json -obj $result -message "It seems you have specified an invalid combination of items for audit_type. Please review documentation"} +} + +######################### +### check Idempotence ### +######################### + +$CurrentRule = Get-AuditPolicy $GetString + +#exit if the audit_type is already set properly for the categroy +If (-not ($CurrentRule.Values | Where-Object {$_ -ne $audit_type_check}) ) +{ + $results.current_audit_policy = Get-AuditPolicy $GetString + Exit-Json -obj $results +} + +#################### +### Apply Change ### +#################### + +If (-not $check_mode) +{ + $ApplyPolicy = Run-Command -command $SetString + + If ($ApplyPolicy.Item('rc') -ne 0) + { + $results.current_audit_policy = Get-AuditPolicy $GetString + Fail-Json $results "Failed to set audit policy - $($_.Exception.Message)" + } +} + +$results.changed = $true +$results.current_audit_policy = Get-AuditPolicy $GetString +Exit-Json $results diff --git a/lib/ansible/modules/windows/win_audit_policy_system.py b/lib/ansible/modules/windows/win_audit_policy_system.py new file mode 100644 index 00000000000..6f30137372b --- /dev/null +++ b/lib/ansible/modules/windows/win_audit_policy_system.py @@ -0,0 +1,68 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2017 Noah Sparks +# Copyright (c) 2017 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: win_audit_policy_system +short_description: Used to make changes to the system wide Audit Policy. +description: + - Used to make changes to the system wide Audit Policy. + - It is recommended to take a backup of the policies before adjusting them for the first time. + - See this page for in depth information U(https://technet.microsoft.com/en-us/library/cc766468.aspx). +version_added: "2.5" +author: + - Noah Sparks (@nwsparks) +options: + category: + description: + - Single string value for the category you would like to adjust the policy on. + - Cannot be used with I(subcategory). You must define one or the other. + - Changing this setting causes all subcategories to be adjusted to the defined I(audit_type). + subcategory: + description: + - Single string value for the subcategory you would like to adjust the policy on. + - Cannot be used with I(category). You must define one or the other. + audit_type: + description: + - The type of event you would like to audit for. + - Accepts a list. See examples. + choices: [ 'success', 'failure', 'none' ] + required: true +''' + +EXAMPLES = r''' +- name: enable failure auditing for the subcategory "File System" + win_audit_policy_system: + subcategory: File System + audit_type: failure + +- name: enable all auditing types for the category "Account logon events" + win_audit_policy_system: + category: Account logon events + audit_type: success, failure + +- name: disable auditing for the subcategory "File System" + win_audit_policy_system: + subcategory: File System + audit_type: none +''' + +RETURN = ''' +current_audit_policy: + description: details on the policy being targetted + returned: always + type: dictionary + sample: |- + { + "File Share":"failure" + } +''' diff --git a/test/integration/targets/win_audit_policy_system/aliases b/test/integration/targets/win_audit_policy_system/aliases new file mode 100644 index 00000000000..ee0ed5974e9 --- /dev/null +++ b/test/integration/targets/win_audit_policy_system/aliases @@ -0,0 +1 @@ +windows/ci/group2 diff --git a/test/integration/targets/win_audit_policy_system/defaults/main.yml b/test/integration/targets/win_audit_policy_system/defaults/main.yml new file mode 100644 index 00000000000..9e0d35c7774 --- /dev/null +++ b/test/integration/targets/win_audit_policy_system/defaults/main.yml @@ -0,0 +1,3 @@ +#important that the subcategory is from a different category +category_name: detailed tracking +subcategory_name: file system diff --git a/test/integration/targets/win_audit_policy_system/tasks/add.yml b/test/integration/targets/win_audit_policy_system/tasks/add.yml new file mode 100644 index 00000000000..e65e6a330c2 --- /dev/null +++ b/test/integration/targets/win_audit_policy_system/tasks/add.yml @@ -0,0 +1,108 @@ +######################## +### check mode apply ### +######################## +- name: check mode enable category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: success + check_mode: yes + register: category + +- name: check mode enable subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: success, failure + check_mode: yes + register: subcategory + +- name: check mode assert that changed is true + assert: + that: + - category | changed + - subcategory | changed + +- name: check mode assert that audit_type is "no auditing" + assert: + that: + - item == "no auditing" + with_items: + - "{{ subcategory.current_audit_policy.values() | list }}" + - "{{ category.current_audit_policy.values() | list | unique }}" + +#alternative check for category...pretty noise and requires more lines +# - name: assert that audit_type is no auditing +# assert: +# that: item.value == "no auditing" +# with_dict: "{{ category.current_audit_policy }}" + +#################### +### apply change ### +#################### + +- name: enable category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: success + register: category + +- name: enable subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: success, failure + register: subcategory + +- name: enable assert that changed is true + assert: + that: + - category | changed + - subcategory | changed + +- name: enable assert that audit_type is "success" for category + assert: + that: + - item == "success" + with_items: + - "{{ category.current_audit_policy.values() | list | unique }}" + +- name: enable assert that audit_type is "success and failure" for subcategory + assert: + that: + - item == "success and failure" + with_items: + - "{{ subcategory.current_audit_policy.values() | list }}" + +############################### +### idempotent apply change ### +############################### + +- name: idem enable category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: success + register: category + +- name: idem enable subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: success, failure + register: subcategory + +- name: idem assert that changed is false + assert: + that: + - not category | changed + - not subcategory | changed + +- name: idem assert that audit_type is "success" for category + assert: + that: + - item == "success" + with_items: + - "{{ category.current_audit_policy.values() | list | unique }}" + +- name: idem assert that audit_type is "success and failure" for subcategory + assert: + that: + - item == "success and failure" + with_items: + - "{{ subcategory.current_audit_policy.values() | list }}" diff --git a/test/integration/targets/win_audit_policy_system/tasks/main.yml b/test/integration/targets/win_audit_policy_system/tasks/main.yml new file mode 100644 index 00000000000..c2e55accf5e --- /dev/null +++ b/test/integration/targets/win_audit_policy_system/tasks/main.yml @@ -0,0 +1,25 @@ +#turn off so then we can test changes occur on enable. Turning off for object access also +#covers our subcategory test for file system +- name: turn off auditing for category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: none + +- name: turn off auditing for subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: none + +- block: + - include_tasks: add.yml + - include_tasks: remove.yml + always: + - name: CLEANUP turn "{{ category_name }}" back to no auditing + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: none + + - name: CLEANUP turn "{{ subcategory_name }}" back to no auditing + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: none diff --git a/test/integration/targets/win_audit_policy_system/tasks/remove.yml b/test/integration/targets/win_audit_policy_system/tasks/remove.yml new file mode 100644 index 00000000000..09d449befd7 --- /dev/null +++ b/test/integration/targets/win_audit_policy_system/tasks/remove.yml @@ -0,0 +1,96 @@ +######################### +### check mode remove ### +######################### +- name: check mode disable category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: none + check_mode: yes + register: category + +- name: check mode disable subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: none + check_mode: yes + register: subcategory + +- name: check mode assert that changed is true + assert: + that: + - category | changed + - subcategory | changed + +- name: check mode assert that audit_type is still "success" (old value) for category + assert: + that: + - item == "success" + with_items: + - "{{ category.current_audit_policy.values() | list | unique }}" + +- name: check mode assert that audit_type is still "success and failure" (old value) for subcategory + assert: + that: + - item == "success and failure" + with_items: + - "{{ subcategory.current_audit_policy.values() | list }}" + +###################### +### disable policy ### +###################### + +- name: disable category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: none + register: category + +- name: disable subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: none + register: subcategory + +- name: assert that changed is true + assert: + that: + - category | changed + - subcategory | changed + +- name: assert that audit_type is "no auditing" + assert: + that: + - item == "no auditing" + with_items: + - "{{ subcategory.current_audit_policy.values() | list }}" + - "{{ category.current_audit_policy.values() | list | unique }}" + +########################## +### idempotent disable ### +########################## + +- name: idem disable category + win_audit_policy_system: + category: "{{ category_name }}" + audit_type: none + register: category + +- name: idem disable subcategory + win_audit_policy_system: + subcategory: "{{ subcategory_name }}" + audit_type: none + register: subcategory + +- name: idem assert that changed is false + assert: + that: + - not category | changed + - not subcategory | changed + +- name: assert that audit_type is "no auditing" + assert: + that: + - item == "no auditing" + with_items: + - "{{ subcategory.current_audit_policy.values() | list }}" + - "{{ category.current_audit_policy.values() | list | unique }}"