diff --git a/salt/auth/__init__.py b/salt/auth/__init__.py index c4e44097f3..ca7168d00e 100644 --- a/salt/auth/__init__.py +++ b/salt/auth/__init__.py @@ -46,6 +46,7 @@ AUTH_INTERNAL_KEYWORDS = frozenset([ 'gather_job_timeout', 'kwarg', 'match', + 'metadata', 'print_event', 'raw', 'yield_pub_data' diff --git a/salt/modules/win_auditpol.py b/salt/modules/win_auditpol.py new file mode 100644 index 0000000000..755b58aed4 --- /dev/null +++ b/salt/modules/win_auditpol.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +''' +A salt module for modifying the audit policies on the machine + +Though this module does not set group policy for auditing, it displays how all +auditing configuration is applied on the machine, either set directly or via +local or domain group policy. + +.. versionadded:: 2018.3.4 +.. versionadded:: 2019.2.1 + +This module allows you to view and modify the audit settings as they are applied +on the machine. The audit settings are broken down into nine categories: + +- Account Logon +- Account Management +- Detailed Tracking +- DS Access +- Logon/Logoff +- Object Access +- Policy Change +- Privilege Use +- System + +The ``get_settings`` function will return the subcategories for all nine of +the above categories in one dictionary along with their auditing status. + +To modify a setting you only need to specify the subcategory name and the value +you wish to set. Valid settings are: + +- No Auditing +- Success +- Failure +- Success and Failure + +CLI Example: + +.. code-block:: bash + + # Get current state of all audit settings + salt * auditpol.get_settings + + # Get the current state of all audit settings in the "Account Logon" + # category + salt * auditpol.get_settings category="Account Logon" + + # Get current state of the "Credential Validation" setting + salt * auditpol.get_setting name="Credential Validation" + + # Set the state of the "Credential Validation" setting to Success and + # Failure + salt * auditpol.set_setting name="Credential Validation" value="Success and Failure" + + # Set the state of the "Credential Validation" setting to No Auditing + salt * auditpol.set_setting name="Credential Validation" value="No Auditing" +''' +from __future__ import absolute_import, unicode_literals, print_function + +# Import Salt libs +import salt.utils.platform + +# Define the module's virtual name +__virtualname__ = 'auditpol' + + +def __virtual__(): + ''' + Only works on Windows systems + ''' + if not salt.utils.platform.is_windows(): + return False, "Module win_auditpol: module only available on Windows" + + return __virtualname__ + + +def get_settings(category='All'): + ''' + Get the current configuration for all audit settings specified in the + category + + Args: + category (str): + One of the nine categories to return. Can also be ``All`` to return + the settings for all categories. Valid options are: + + - Account Logon + - Account Management + - Detailed Tracking + - DS Access + - Logon/Logoff + - Object Access + - Policy Change + - Privilege Use + - System + - All + + Default value is ``All`` + + Returns: + dict: A dictionary containing all subcategories for the specified + category along with their current configuration + + Raises: + KeyError: On invalid category + CommandExecutionError: If an error is encountered retrieving the settings + + CLI Example: + + .. code-block:: bash + + # Get current state of all audit settings + salt * auditipol.get_settings + + # Get the current state of all audit settings in the "Account Logon" + # category + salt * auditpol.get_settings "Account Logon" + ''' + return __utils__['auditpol.get_settings'](category=category) + + +def get_setting(name): + ''' + Get the current configuration for the named audit setting + + Args: + name (str): The name of the setting to retrieve + + Returns: + str: The current configuration for the named setting + + Raises: + KeyError: On invalid setting name + CommandExecutionError: If an error is encountered retrieving the settings + + CLI Example: + + .. code-block:: bash + + # Get current state of the "Credential Validation" setting + salt * auditpol.get_setting "Credential Validation" + ''' + return __utils__['auditpol.get_setting'](name=name) + + +def set_setting(name, value): + ''' + Set the configuration for the named audit setting + + Args: + + name (str): + The name of the setting to configure + + value (str): + The configuration for the named value. Valid options are: + + - No Auditing + - Success + - Failure + - Success and Failure + + Returns: + bool: True if successful + + Raises: + KeyError: On invalid ``name`` or ``value`` + CommandExecutionError: If an error is encountered modifying the setting + + CLI Example: + + .. code-block:: bash + # Set the state of the "Credential Validation" setting to Success and + # Failure + salt * auditpol.set_setting "Credential Validation" "Success and Failure" + + # Set the state of the "Credential Validation" setting to No Auditing + salt * auditpol.set_setting "Credential Validation" "No Auditing" + ''' + return __utils__['auditpol.set_setting'](name=name, value=value) diff --git a/salt/modules/win_lgpo.py b/salt/modules/win_lgpo.py index 3cd389c98c..d8d5ed44de 100644 --- a/salt/modules/win_lgpo.py +++ b/salt/modules/win_lgpo.py @@ -39,12 +39,14 @@ Current known limitations ''' # Import Python libs from __future__ import absolute_import, unicode_literals, print_function +import csv import io import os import logging import re import locale import ctypes +import tempfile import time # Import Salt libs @@ -280,6 +282,19 @@ class _policy_info(object): netsh advfirewall>set help netsh advfirewall>set domain help + AdvAudit Mechanism + ------------------ + + The Advanced Audit Policies are configured using a combination of the + auditpol command-line utility and modifying the audit.csv file in two + locations. The value of this key is a dict with the following make-up: + + ====== =================================== + Key Value + ====== =================================== + Option The Advanced Audit Policy to modify + ====== =================================== + Transforms ---------- @@ -310,6 +325,13 @@ class _policy_info(object): 'Not Defined': 'Not Defined', None: 'Not Defined', } + self.advanced_audit_lookup = { + 0: 'No Auditing', + 1: 'Success', + 2: 'Failure', + 3: 'Success and Failure', + None: 'Not Configured', + } self.sc_removal_lookup = { 0: 'No Action', 1: 'Lock Workstation', @@ -372,6 +394,18 @@ class _policy_info(object): 'value_lookup': True, }, } + self.advanced_audit_transform = { + 'Get': '_dict_lookup', + 'Put': '_dict_lookup', + 'GetArgs': { + 'lookup': self.advanced_audit_lookup, + 'value_lookup': False, + }, + 'PutArgs': { + 'lookup': self.advanced_audit_lookup, + 'value_lookup': True, + }, + } self.enabled_one_disabled_zero_strings = { '0': 'Disabled', '1': 'Enabled', @@ -418,6 +452,13 @@ class _policy_info(object): 'Local Policies', 'Audit Policy' ] + self.advanced_audit_policy_gpedit_path = [ + 'Computer Configuration', + 'Windows Settings', + 'Security Settings', + 'Advanced Audit Policy Configuration', + 'System Audit Policies - Local Group Policy Object' + ] self.account_lockout_policy_gpedit_path = [ 'Computer Configuration', 'Windows Settings', @@ -2603,6 +2644,11 @@ class _policy_info(object): 'Put': '_minutes_to_seconds' }, }, + ########## LEGACY AUDIT POLICIES ########## + # To use these set the following policy to DISABLED + # "Audit: Force audit policy subcategory settings (Windows Vista or later) to override audit policy category settings" + # or it's alias... + # SceNoApplyLegacyAuditPolicy 'AuditAccountLogon': { 'Policy': 'Audit account logon events', 'lgpo_section': self.audit_policy_gpedit_path, @@ -2693,6 +2739,557 @@ class _policy_info(object): }, 'Transform': self.audit_transform, }, + ########## END OF LEGACY AUDIT POLICIES ########## + ########## ADVANCED AUDIT POLICIES ########## + # Advanced Audit Policies + # To use these set the following policy to ENABLED + # "Audit: Force audit policy subcategory settings (Windows + # Vista or later) to override audit policy category + # settings" + # or it's alias... + # SceNoApplyLegacyAuditPolicy + + # Account Logon Section + 'AuditCredentialValidation': { + 'Policy': 'Audit Credential Validation', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Credential Validation', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditKerberosAuthenticationService': { + 'Policy': 'Audit Kerberos Authentication Service', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Kerberos Authentication Service', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditKerberosServiceTicketOperations': { + 'Policy': 'Audit Kerberos Service Ticket Operations', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Kerberos Service Ticket Operations', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherAccountLogonEvents': { + 'Policy': 'Audit Other Account Logon Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other Account Logon Events', + }, + 'Transform': self.advanced_audit_transform, + }, + # Account Management Section + 'AuditApplicationGroupManagement': { + 'Policy': 'Audit Application Group Management', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Application Group Management', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditComputerAccountManagement': { + 'Policy': 'Audit Computer Account Management', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Computer Account Management', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditDistributionGroupManagement': { + 'Policy': 'Audit Distribution Group Management', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Distribution Group Management', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherAccountManagementEvents': { + 'Policy': 'Audit Other Account Management Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other Account Management Events', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSecurityGroupManagement': { + 'Policy': 'Audit Security Group Management', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Security Group Management', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditUserAccountManagement': { + 'Policy': 'Audit User Account Management', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit User Account Management', + }, + 'Transform': self.advanced_audit_transform, + }, + # Detailed Tracking Settings + 'AuditDPAPIActivity': { + 'Policy': 'Audit DPAPI Activity', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit DPAPI Activity', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditPNPActivity': { + 'Policy': 'Audit PNP Activity', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit PNP Activity', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditProcessCreation': { + 'Policy': 'Audit Process Creation', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Process Creation', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditProcessTermination': { + 'Policy': 'Audit Process Termination', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Process Termination', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditRPCEvents': { + 'Policy': 'Audit RPC Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit RPC Events', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditTokenRightAdjusted': { + 'Policy': 'Audit Token Right Adjusted', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Token Right Adjusted', + }, + 'Transform': self.advanced_audit_transform, + }, + # DS Access Section + 'AuditDetailedDirectoryServiceReplication': { + 'Policy': 'Audit Detailed Directory Service Replication', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Detailed Directory Service Replication', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditDirectoryServiceAccess': { + 'Policy': 'Audit Directory Service Access', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Directory Service Access', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditDirectoryServiceChanges': { + 'Policy': 'Audit Directory Service Changes', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Directory Service Changes', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditDirectoryServiceReplication': { + 'Policy': 'Audit Directory Service Replication', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Directory Service Replication', + }, + 'Transform': self.advanced_audit_transform, + }, + # Logon/Logoff Section + 'AuditAccountLockout': { + 'Policy': 'Audit Account Lockout', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Account Lockout', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditUserDeviceClaims': { + 'Policy': 'Audit User / Device Claims', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit User / Device Claims', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditGroupMembership': { + 'Policy': 'Audit Group Membership', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Group Membership', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditIPsecExtendedMode': { + 'Policy': 'Audit IPsec Extended Mode', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit IPsec Extended Mode', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditIPsecMainMode': { + 'Policy': 'Audit IPsec Main Mode', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit IPsec Main Mode', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditIPsecQuickMode': { + 'Policy': 'Audit IPsec Quick Mode', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit IPsec Quick Mode', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditLogoff': { + 'Policy': 'Audit Logoff', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Logoff', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditLogon': { + 'Policy': 'Audit Logon', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Logon', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditNetworkPolicyServer': { + 'Policy': 'Audit Network Policy Server', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Network Policy Server', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherLogonLogoffEvents': { + 'Policy': 'Audit Other Logon/Logoff Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other Logon/Logoff Events', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSpecialLogon': { + 'Policy': 'Audit Special Logon', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Special Logon', + }, + 'Transform': self.advanced_audit_transform, + }, + # Object Access Section + 'AuditApplicationGenerated': { + 'Policy': 'Audit Application Generated', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Application Generated', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditCertificationServices': { + 'Policy': 'Audit Certification Services', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Certification Services', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditDetailedFileShare': { + 'Policy': 'Audit Detailed File Share', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Detailed File Share', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditFileShare': { + 'Policy': 'Audit File Share', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit File Share', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditFileSystem': { + 'Policy': 'Audit File System', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit File System', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditFilteringPlatformConnection': { + 'Policy': 'Audit Filtering Platform Connection', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Filtering Platform Connection', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditFilteringPlatformPacketDrop': { + 'Policy': 'Audit Filtering Platform Packet Drop', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Filtering Platform Packet Drop', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditHandleManipulation': { + 'Policy': 'Audit Handle Manipulation', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Handle Manipulation', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditKernelObject': { + 'Policy': 'Audit Kernel Object', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Kernel Object', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherObjectAccessEvents': { + 'Policy': 'Audit Other Object Access Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other Object Access Events', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditRegistry': { + 'Policy': 'Audit Registry', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Registry', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditRemovableStorage': { + 'Policy': 'Audit Removable Storage', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Removable Storage', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSAM': { + 'Policy': 'Audit SAM', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit SAM', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditCentralAccessPolicyStaging': { + 'Policy': 'Audit Central Access Policy Staging', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Central Access Policy Staging', + }, + 'Transform': self.advanced_audit_transform, + }, + # Policy Change Section + 'AuditAuditPolicyChange': { + 'Policy': 'Audit Audit Policy Change', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Audit Policy Change', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditAuthenticationPolicyChange': { + 'Policy': 'Audit Authentication Policy Change', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Authentication Policy Change', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditAuthorizationPolicyChange': { + 'Policy': 'Audit Authorization Policy Change', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Authorization Policy Change', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditFilteringPlatformPolicyChange': { + 'Policy': 'Audit Filtering Platform Policy Change', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Filtering Platform Policy Change', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditMPSSVCRuleLevelPolicyChange': { + 'Policy': 'Audit MPSSVC Rule-Level Policy Change', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit MPSSVC Rule-Level Policy Change', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherPolicyChangeEvents': { + 'Policy': 'Audit Other Policy Change Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other Policy Change Events', + }, + 'Transform': self.advanced_audit_transform, + }, + # Privilege Use Section + 'AuditNonSensitivePrivilegeUse': { + 'Policy': 'Audit Non Sensitive Privilege Use', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Non Sensitive Privilege Use', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherPrivilegeUseEvents': { + 'Policy': 'Audit Other Privilege Use Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other Privilege Use Events', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSensitivePrivilegeUse': { + 'Policy': 'Audit Sensitive Privilege Use', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Sensitive Privilege Use', + }, + 'Transform': self.advanced_audit_transform, + }, + # System Section + 'AuditIPsecDriver': { + 'Policy': 'Audit IPsec Driver', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit IPsec Driver', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditOtherSystemEvents': { + 'Policy': 'Audit Other System Events', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Other System Events', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSecurityStateChange': { + 'Policy': 'Audit Security State Change', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Security State Change', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSecuritySystemExtension': { + 'Policy': 'Audit Security System Extension', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit Security System Extension', + }, + 'Transform': self.advanced_audit_transform, + }, + 'AuditSystemIntegrity': { + 'Policy': 'Audit System Integrity', + 'lgpo_section': self.advanced_audit_policy_gpedit_path, + 'Settings': self.advanced_audit_lookup.keys(), + 'AdvAudit': { + 'Option': 'Audit System Integrity', + }, + 'Transform': self.advanced_audit_transform, + }, + ########## END OF ADVANCED AUDIT POLICIES ########## 'SeTrustedCredManAccessPrivilege': { 'Policy': 'Access Credential Manager as a trusted ' 'caller', @@ -4349,6 +4946,296 @@ def _buildElementNsmap(using_elements): return thisMap +def _get_audit_defaults(option=None): + ''' + Loads audit.csv defaults into a dict in __context__ called + 'lgpo.audit_defaults'. The dictionary includes fieldnames and all + configurable policies as keys. The values are used to create/modify the + ``audit.csv`` file. The first entry is `fieldnames` used to create the + header for the csv file. The rest of the entries are the audit policy names. + Sample data follows: + + { + 'fieldnames': ['Machine Name', + 'Policy Target', + 'Subcategory', + 'Subcategory GUID', + 'Inclusion Setting', + 'Exclusion Setting', + 'Setting Value'], + 'Audit Sensitive Privilege Use': {'Auditpol Name': 'Sensitive Privilege Use', + 'Exclusion Setting': '', + 'Inclusion Setting': 'No Auditing', + 'Machine Name': 'WIN-8FGT3E045SE', + 'Policy Target': 'System', + 'Setting Value': '0', + 'Subcategory': u'Audit Sensitive Privilege Use', + 'Subcategory GUID': '{0CCE9228-69AE-11D9-BED3-505054503030}'}, + 'Audit Special Logon': {'Auditpol Name': 'Special Logon', + 'Exclusion Setting': '', + 'Inclusion Setting': 'No Auditing', + 'Machine Name': 'WIN-8FGT3E045SE', + 'Policy Target': 'System', + 'Setting Value': '0', + 'Subcategory': u'Audit Special Logon', + 'Subcategory GUID': '{0CCE921B-69AE-11D9-BED3-505054503030}'}, + 'Audit System Integrity': {'Auditpol Name': 'System Integrity', + 'Exclusion Setting': '', + 'Inclusion Setting': 'No Auditing', + 'Machine Name': 'WIN-8FGT3E045SE', + 'Policy Target': 'System', + 'Setting Value': '0', + 'Subcategory': u'Audit System Integrity', + 'Subcategory GUID': '{0CCE9212-69AE-11D9-BED3-505054503030}'}, + ... + } + + .. note:: + `Auditpol Name` designates the value to use when setting the value with + the auditpol command + + Args: + option (str): The item from the dictionary to return. If ``None`` the + entire dictionary is returned. Default is ``None`` + + Returns: + dict: If ``None`` or one of the audit settings is passed + list: If ``fieldnames`` is passed + ''' + if 'lgpo.audit_defaults' not in __context__: + # Get available setting names and GUIDs + # This is used to get the fieldnames and GUIDs for individual policies + log.debug('Loading auditpol defaults into __context__') + dump = __utils__['auditpol.get_auditpol_dump']() + reader = csv.DictReader(dump) + audit_defaults = {'fieldnames': reader.fieldnames} + for row in reader: + row['Machine Name'] = '' + row['Auditpol Name'] = row['Subcategory'] + # Special handling for snowflake scenarios where the audit.csv names + # don't match the auditpol names + if row['Subcategory'] == 'Central Policy Staging': + row['Subcategory'] = 'Audit Central Access Policy Staging' + elif row['Subcategory'] == 'Plug and Play Events': + row['Subcategory'] = 'Audit PNP Activity' + elif row['Subcategory'] == 'Token Right Adjusted Events': + row['Subcategory'] = 'Audit Token Right Adjusted' + else: + row['Subcategory'] = 'Audit {0}'.format(row['Subcategory']) + audit_defaults[row['Subcategory']] = row + + __context__['lgpo.audit_defaults'] = audit_defaults + + if option: + return __context__['lgpo.audit_defaults'][option] + else: + return __context__['lgpo.audit_defaults'] + + +def _findOptionValueAdvAudit(option): + ''' + Get the Advanced Auditing policy as configured in + ``C:\\Windows\\Security\\Audit\\audit.csv`` + + Args: + option (str): The name of the setting as it appears in audit.csv + + Returns: + bool: ``True`` if successful, otherwise ``False`` + ''' + if 'lgpo.adv_audit_data' not in __context__: + system_root = os.environ.get('SystemRoot', 'C:\\Windows') + f_audit = os.path.join(system_root, 'security', 'audit', 'audit.csv') + f_audit_gpo = os.path.join(system_root, 'System32', 'GroupPolicy', + 'Machine', 'Microsoft', 'Windows NT', + 'Audit', 'audit.csv') + + # Make sure there is an existing audit.csv file on the machine + if not __salt__['file.file_exists'](f_audit): + if __salt__['file.file_exists'](f_audit_gpo): + # If the GPO audit.csv exists, we'll use that one + __salt__['file.copy'](f_audit_gpo, f_audit) + else: + field_names = _get_audit_defaults('fieldnames') + # If the file doesn't exist anywhere, create it with default + # fieldnames + __salt__['file.touch'](f_audit) + __salt__['file.append'](f_audit, ','.join(field_names)) + + audit_settings = {} + with salt.utils.files.fopen(f_audit, mode='r') as csv_file: + reader = csv.DictReader(csv_file) + + for row in reader: + audit_settings.update( + {row['Subcategory']: row['Setting Value']}) + + __context__['lgpo.adv_audit_data'] = audit_settings + + return __context__['lgpo.adv_audit_data'].get(option, None) + + +def _set_audit_file_data(option, value): + ''' + Helper function that sets the Advanced Audit settings in the two .csv files + on Windows. Those files are located at: + C:\\Windows\\Security\\Audit\\audit.csv + C:\\Windows\\System32\\GroupPolicy\\Machine\\Microsoft\\Windows NT\\Audit\\audit.csv + + Args: + option (str): The name of the option to set + value (str): The value to set. ['None', '0', '1', '2', '3'] + + Returns: + bool: ``True`` if successful, otherwise ``False`` + ''' + # Set up some paths here + system_root = os.environ.get('SystemRoot', 'C:\\Windows') + f_audit = os.path.join(system_root, 'security', 'audit', 'audit.csv') + f_audit_gpo = os.path.join(system_root, 'System32', 'GroupPolicy', + 'Machine', 'Microsoft', 'Windows NT', + 'Audit', 'audit.csv') + f_temp = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.csv', + prefix='audit') + + # Lookup dict for "Inclusion Setting" field + auditpol_values = {'None': 'No Auditing', + '0': 'No Auditing', + '1': 'Success', + '2': 'Failure', + '3': 'Success and Failure'} + + try: + # Open the existing audit.csv and load the csv `reader` + with salt.utils.files.fopen(f_audit, mode='r') as csv_file: + reader = csv.DictReader(csv_file) + + # Open the temporary .csv and load the csv `writer` + with salt.utils.files.fopen(f_temp.name, mode='w') as tmp_file: + writer = csv.DictWriter(tmp_file, fieldnames=reader.fieldnames) + + # Write the header values (labels) + writer.writeheader() + + value_written = False + # Loop through the current audit.csv and write the changes to + # the temp csv file for existing settings + for row in reader: + # If the row matches the value we're setting, update it with + # the new value + if row['Subcategory'] == option: + if not value == 'None': + # The value is not None, make the change + row['Inclusion Setting'] = auditpol_values[value] + row['Setting Value'] = value + log.debug('LGPO: Setting {0} to {1}' + ''.format(option, value)) + writer.writerow(row) + else: + # value is None, remove it by not writing it to the + # temp file + log.debug('LGPO: Removing {0}'.format(option)) + value_written = True + # If it's not the value we're setting, just write it + else: + writer.writerow(row) + + # If a value was not written, it is a new setting not found in + # the existing audit.cvs file. Add the new setting with values + # from the defaults + if not value_written: + if not value == 'None': + # value is not None, write the new value + log.debug('LGPO: Setting {0} to {1}' + ''.format(option, value)) + defaults = _get_audit_defaults(option) + writer.writerow({ + 'Machine Name': defaults['Machine Name'], + 'Policy Target': defaults['Policy Target'], + 'Subcategory': defaults['Subcategory'], + 'Subcategory GUID': defaults['Subcategory GUID'], + 'Inclusion Setting': auditpol_values[value], + 'Exclusion Setting': defaults['Exclusion Setting'], + 'Setting Value': value}) + value_written = True + + if value_written: + # Copy the temporary csv file over the existing audit.csv in both + # locations if a value was written + __salt__['file.copy'](f_temp.name, f_audit, remove_existing=True) + __salt__['file.copy'](f_temp.name, f_audit_gpo, remove_existing=True) + finally: + f_temp.close() + __salt__['file.remove'](f_temp.name) + + return value_written + + +def _set_auditpol_data(option, value): + ''' + Helper function that updates the current applied settings to match what has + just been set in the audit.csv files. We're doing it this way instead of + running `gpupdate` + + Args: + option (str): The name of the option to set + value (str): The value to set. ['None', '0', '1', '2', '3'] + + Returns: + bool: ``True`` if successful, otherwise ``False`` + ''' + auditpol_values = {'None': 'No Auditing', + '0': 'No Auditing', + '1': 'Success', + '2': 'Failure', + '3': 'Success and Failure'} + defaults = _get_audit_defaults(option) + return __utils__['auditpol.set_setting']( + name=defaults['Auditpol Name'], + value=auditpol_values[value]) + + +def _setOptionValueAdvAudit(option, value): + ''' + Helper function to update the Advanced Audit policy on the machine. This + function modifies the two ``audit.csv`` files in the following locations: + + C:\\Windows\\Security\\Audit\\audit.csv + C:\\Windows\\System32\\GroupPolicy\\Machine\\Microsoft\\Windows NT\\Audit\\audit.csv + + Then it applies those settings using ``auditpol`` + + After that, it updates ``__context__`` with the new setting + + Args: + option (str): The name of the option to set + value (str): The value to set. ['None', '0', '1', '2', '3'] + + Returns: + bool: ``True`` if successful, otherwise ``False`` + ''' + # Set the values in both audit.csv files + if not _set_audit_file_data(option=option, value=value): + raise CommandExecutionError('Failed to set audit.csv option: {0}' + ''.format(option)) + # Apply the settings locally + if not _set_auditpol_data(option=option, value=value): + # Only log this error, it will be in effect the next time the machine + # updates its policy + log.debug('Failed to apply audit setting: {0}'.format(option)) + + # Update __context__ + if value is None: + log.debug('LGPO: Removing Advanced Audit data: {0}'.format(option)) + __context__['lgpo.adv_audit_data'].pop(option) + else: + log.debug('LGPO: Updating Advanced Audit data: {0}: {1}' + ''.format(option, value)) + __context__['lgpo.adv_audit_data'][option] = value + + return True + + def _findOptionValueNetSH(profile, option): if 'lgpo.netsh_data' not in __context__: __context__['lgpo.netsh_data'] = {} @@ -6770,7 +7657,10 @@ def get(policy_class=None, return_full_policy_names=True, class_vals[policy_name] = _findOptionValueNetSH( profile=_pol['NetSH']['Profile'], option=_pol['NetSH']['Option']) - + elif 'AdvAudit' in _pol: + # get value from auditpol + class_vals[policy_name] = _findOptionValueAdvAudit( + option=_pol['AdvAudit']['Option']) elif 'NetUserModal' in _pol: # get value from UserNetMod if _pol['NetUserModal']['Modal'] not in modal_returns: @@ -6993,6 +7883,7 @@ def set_(computer_policy=None, user_policy=None, for p_class in policies: _secedits = {} _netshs = {} + _advaudits = {} _modal_sets = {} _admTemplateData = {} _regedits = {} @@ -7041,6 +7932,12 @@ def set_(computer_policy=None, user_policy=None, 'option': _pol['NetSH']['Option'], 'value': six.text_type(_value) }) + elif 'AdvAudit' in _pol: + # set value with advaudit + _advaudits.setdefault(policy_name, { + 'option': _pol['AdvAudit']['Option'], + 'value': six.text_type(_value) + }) elif 'NetUserModal' in _pol: # set value via NetUserModal log.debug('%s is a NetUserModal policy', policy_name) @@ -7237,6 +8134,13 @@ def set_(computer_policy=None, user_policy=None, log.debug(_netshs[setting]) _setOptionValueNetSH(**_netshs[setting]) + if _advaudits: + # We've got AdvAudit settings to make + for setting in _advaudits: + log.debug('Setting Advanced Audit policy: {0}'.format(setting)) + log.debug(_advaudits[setting]) + _setOptionValueAdvAudit(**_advaudits[setting]) + if _modal_sets: # we've got modalsets to make log.debug(_modal_sets) diff --git a/salt/utils/win_lgpo_auditpol.py b/salt/utils/win_lgpo_auditpol.py new file mode 100644 index 0000000000..b729728b8d --- /dev/null +++ b/salt/utils/win_lgpo_auditpol.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +r''' +A salt util for modifying the audit policies on the machine. This util is used +by the ``win_auditpol`` and ``win_lgpo`` modules. + +Though this utility does not set group policy for auditing, it displays how all +auditing configuration is applied on the machine, either set directly or via +local or domain group policy. + +.. versionadded:: 2018.3.4 +.. versionadded:: 2019.2.1 + +This util allows you to view and modify the audit settings as they are applied +on the machine. The audit settings are broken down into nine categories: + +- Account Logon +- Account Management +- Detailed Tracking +- DS Access +- Logon/Logoff +- Object Access +- Policy Change +- Privilege Use +- System + +The ``get_settings`` function will return the subcategories for all nine of +the above categories in one dictionary along with their auditing status. + +To modify a setting you only need to specify the subcategory name and the value +you wish to set. Valid settings are: + +- No Auditing +- Success +- Failure +- Success and Failure + +Usage: + +.. code-block:: python + + import salt.utils.win_lgpo_auditpol + + # Get current state of all audit settings + salt.utils.win_lgpo_auditpol.get_settings() + + # Get the current state of all audit settings in the "Account Logon" + # category + salt.utils.win_lgpo_auditpol.get_settings(category="Account Logon") + + # Get current state of the "Credential Validation" setting + salt.utils.win_lgpo_auditpol.get_setting(name='Credential Validation') + + # Set the state of the "Credential Validation" setting to Success and + # Failure + salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', + value='Success and Failure') + + # Set the state of the "Credential Validation" setting to No Auditing + salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', + value='No Auditing') +''' +# Import Python libs +from __future__ import absolute_import, unicode_literals, print_function +import logging +import re +import tempfile + +# Import Salt libs +import salt.modules.cmdmod +import salt.utils.files +import salt.utils.platform +from salt.exceptions import CommandExecutionError + +# Import 3rd Party libs +from salt.ext.six.moves import zip + +log = logging.getLogger(__name__) +__virtualname__ = 'auditpol' + +categories = ['Account Logon', + 'Account Management', + 'Detailed Tracking', + 'DS Access', + 'Logon/Logoff', + 'Object Access', + 'Policy Change', + 'Privilege Use', + 'System'] + +settings = {'No Auditing': '/success:disable /failure:disable', + 'Success': '/success:enable /failure:disable', + 'Failure': '/success:disable /failure:enable', + 'Success and Failure': '/success:enable /failure:enable'} + + +# Although utils are often directly imported, it is also possible to use the +# loader. +def __virtual__(): + ''' + Only load if on a Windows system + ''' + if not salt.utils.platform.is_windows(): + return False, 'This utility only available on Windows' + + return __virtualname__ + + +def _auditpol_cmd(cmd): + ''' + Helper function for running the auditpol command + + Args: + cmd (str): the auditpol command to run + + Returns: + list: A list containing each line of the return (splitlines) + + Raises: + CommandExecutionError: If the command encounters an error + ''' + ret = salt.modules.cmdmod.run_all(cmd='auditpol {0}'.format(cmd), + python_shell=True) + if ret['retcode'] == 0: + return ret['stdout'].splitlines() + + msg = 'Error executing auditpol command: {0}\n'.format(cmd) + msg += '\n'.join(ret['stdout']) + raise CommandExecutionError(msg) + + +def get_settings(category='All'): + ''' + Get the current configuration for all audit settings specified in the + category + + Args: + category (str): + One of the nine categories to return. Can also be ``All`` to return + the settings for all categories. Valid options are: + + - Account Logon + - Account Management + - Detailed Tracking + - DS Access + - Logon/Logoff + - Object Access + - Policy Change + - Privilege Use + - System + - All + + Default value is ``All`` + + Returns: + dict: A dictionary containing all subcategories for the specified + category along with their current configuration + + Raises: + KeyError: On invalid category + CommandExecutionError: If an error is encountered retrieving the settings + + Usage: + + .. code-block:: python + + import salt.utils.win_lgpo_auditpol + + # Get current state of all audit settings + salt.utils.win_lgpo_auditpol.get_settings() + + # Get the current state of all audit settings in the "Account Logon" + # category + salt.utils.win_lgpo_auditpol.get_settings(category="Account Logon") + ''' + # Parameter validation + if category.lower() in ['all', '*']: + category = '*' + elif category.lower() not in [x.lower() for x in categories]: + raise KeyError('Invalid category: "{0}"'.format(category)) + + cmd = '/get /category:"{0}"'.format(category) + results = _auditpol_cmd(cmd) + + ret = {} + # Skip the first 2 lines + for line in results[3:]: + if ' ' in line.strip(): + ret.update(dict(list(zip(*[iter(re.split(r"\s{2,}", line.strip()))]*2)))) + return ret + + +def get_setting(name): + ''' + Get the current configuration for the named audit setting + + Args: + name (str): The name of the setting to retrieve + + Returns: + str: The current configuration for the named setting + + Raises: + KeyError: On invalid setting name + CommandExecutionError: If an error is encountered retrieving the settings + + Usage: + + .. code-block:: python + + import salt.utils.win_lgpo_auditpol + + # Get current state of the "Credential Validation" setting + salt.utils.win_lgpo_auditpol.get_setting(name='Credential Validation') + ''' + current_settings = get_settings(category='All') + for setting in current_settings: + if name.lower() == setting.lower(): + return current_settings[setting] + raise KeyError('Invalid name: {0}'.format(name)) + + +def _get_valid_names(): + if 'auditpol.valid_names' not in __context__: + settings = get_settings(category='All') + __context__['auditpol.valid_names'] = [k.lower() for k in settings] + return __context__['auditpol.valid_names'] + + +def set_setting(name, value): + ''' + Set the configuration for the named audit setting + + Args: + + name (str): + The name of the setting to configure + + value (str): + The configuration for the named value. Valid options are: + + - No Auditing + - Success + - Failure + - Success and Failure + + Returns: + bool: True if successful + + Raises: + KeyError: On invalid ``name`` or ``value`` + CommandExecutionError: If an error is encountered modifying the setting + + Usage: + + .. code-block:: python + + import salt.utils.win_lgpo_auditpol + + # Set the state of the "Credential Validation" setting to Success and + # Failure + salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', + value='Success and Failure') + + # Set the state of the "Credential Validation" setting to No Auditing + salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', + value='No Auditing') + ''' + # Input validation + if name.lower() not in _get_valid_names(): + raise KeyError('Invalid name: {0}'.format(name)) + for setting in settings: + if value.lower() == setting.lower(): + cmd = '/set /subcategory:"{0}" {1}'.format(name, settings[setting]) + break + else: + raise KeyError('Invalid setting value: {0}'.format(value)) + + _auditpol_cmd(cmd) + + return True + + +def get_auditpol_dump(): + ''' + Gets the contents of an auditpol /backup. Used by the LGPO module to get + fieldnames and GUIDs for Advanced Audit policies. + + Returns: + list: A list of lines form the backup file + + Usage: + + .. code-block:: python + + import salt.utils.win_lgpo_auditpol + + dump = salt.utils.win_lgpo_auditpol.get_auditpol_dump() + ''' + # Just get a temporary file name + # NamedTemporaryFile will delete the file it creates by default on Windows + with tempfile.NamedTemporaryFile(suffix='.csv') as tmp_file: + csv_file = tmp_file.name + + cmd = '/backup /file:{0}'.format(csv_file) + _auditpol_cmd(cmd) + + with salt.utils.files.fopen(csv_file) as fp: + return fp.readlines() diff --git a/salt/utils/win_lgpo_netsh.py b/salt/utils/win_lgpo_netsh.py index f284651ff4..30cfb1afda 100644 --- a/salt/utils/win_lgpo_netsh.py +++ b/salt/utils/win_lgpo_netsh.py @@ -81,6 +81,19 @@ from salt.ext.six.moves import zip log = logging.getLogger(__name__) __hostname__ = socket.gethostname() +__virtualname__ = 'netsh' + + +# Although utils are often directly imported, it is also possible to use the +# loader. +def __virtual__(): + ''' + Only load if on a Windows system + ''' + if not salt.utils.platform.is_windows(): + return False, 'This utility only available on Windows' + + return __virtualname__ def _netsh_file(content): diff --git a/tests/unit/utils/test_win_lgpo_auditpol.py b/tests/unit/utils/test_win_lgpo_auditpol.py new file mode 100644 index 0000000000..b7b288a64c --- /dev/null +++ b/tests/unit/utils/test_win_lgpo_auditpol.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- + +# Import Python Libs +from __future__ import absolute_import, unicode_literals, print_function +import random + +# Import Salt Testing Libs +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import NO_MOCK, NO_MOCK_REASON, patch, MagicMock +from tests.support.unit import TestCase, skipIf + +# Import Salt Libs +import salt.modules.cmdmod +import salt.utils.platform +import salt.utils.win_lgpo_auditpol as win_lgpo_auditpol + +settings = ['No Auditing', 'Success', 'Failure', 'Success and Failure'] + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +@skipIf(not salt.utils.platform.is_windows(), 'System is not Windows') +class WinLgpoAuditpolTestCase(TestCase, LoaderModuleMockMixin): + def setup_loader_modules(self): + return { + win_lgpo_auditpol: { + '__context__': {}, + '__salt__': { + 'cmd.run_all': salt.modules.cmdmod.run_all + }}} + + def test_get_settings(self): + names = win_lgpo_auditpol._get_valid_names() + ret = win_lgpo_auditpol.get_settings(category='All') + for name in names: + self.assertIn(name, [k.lower() for k in ret]) + + def test_get_settings_invalid_category(self): + self.assertRaises( + KeyError, + win_lgpo_auditpol.get_settings, + category='Fake Category') + + def test_get_setting(self): + names = win_lgpo_auditpol._get_valid_names() + for name in names: + ret = win_lgpo_auditpol.get_setting(name) + self.assertIn(ret, settings) + + def test_get_setting_invalid_name(self): + self.assertRaises( + KeyError, + win_lgpo_auditpol.get_setting, + name='Fake Name') + + def test_set_setting(self): + names = ['Credential Validation', 'IPsec Driver', 'File System', 'SAM'] + mock_set = MagicMock(return_value={'retcode': 0, 'stdout': 'Success'}) + with patch.object(salt.modules.cmdmod, 'run_all', mock_set): + with patch.object(win_lgpo_auditpol, '_get_valid_names', + return_value=[k.lower() for k in names]): + for name in names: + value = random.choice(settings) + win_lgpo_auditpol.set_setting(name=name, value=value) + switches = win_lgpo_auditpol.settings[value] + cmd = 'auditpol /set /subcategory:"{0}" {1}' \ + ''.format(name, switches) + mock_set.assert_called_once_with(cmd=cmd, python_shell=True) + mock_set.reset_mock() + + def test_set_setting_invalid_setting(self): + names = ['Credential Validation', 'IPsec Driver', 'File System'] + with patch.object(win_lgpo_auditpol, '_get_valid_names', + return_value=[k.lower() for k in names]): + self.assertRaises( + KeyError, + win_lgpo_auditpol.set_setting, + name='Fake Name', + value='No Auditing') + + def test_set_setting_invalid_value(self): + names = ['Credential Validation', 'IPsec Driver', 'File System'] + with patch.object(win_lgpo_auditpol, '_get_valid_names', + return_value=[k.lower() for k in names]): + self.assertRaises( + KeyError, + win_lgpo_auditpol.set_setting, + name='Credential Validation', + value='Fake Value') + + def test_get_auditpol_dump(self): + names = win_lgpo_auditpol._get_valid_names() + dump = win_lgpo_auditpol.get_auditpol_dump() + for name in names: + found = False + for line in dump: + if name.lower() in line.lower(): + found = True + break + self.assertTrue(found)