1r""" 2A salt util for modifying the audit policies on the machine. This util is used 3by the ``win_auditpol`` and ``win_lgpo`` modules. 4 5Though this utility does not set group policy for auditing, it displays how all 6auditing configuration is applied on the machine, either set directly or via 7local or domain group policy. 8 9.. versionadded:: 2018.3.4 10.. versionadded:: 2019.2.1 11 12This util allows you to view and modify the audit settings as they are applied 13on the machine. The audit settings are broken down into nine categories: 14 15- Account Logon 16- Account Management 17- Detailed Tracking 18- DS Access 19- Logon/Logoff 20- Object Access 21- Policy Change 22- Privilege Use 23- System 24 25The ``get_settings`` function will return the subcategories for all nine of 26the above categories in one dictionary along with their auditing status. 27 28To modify a setting you only need to specify the subcategory name and the value 29you wish to set. Valid settings are: 30 31- No Auditing 32- Success 33- Failure 34- Success and Failure 35 36Usage: 37 38.. code-block:: python 39 40 import salt.utils.win_lgpo_auditpol 41 42 # Get current state of all audit settings 43 salt.utils.win_lgpo_auditpol.get_settings() 44 45 # Get the current state of all audit settings in the "Account Logon" 46 # category 47 salt.utils.win_lgpo_auditpol.get_settings(category="Account Logon") 48 49 # Get current state of the "Credential Validation" setting 50 salt.utils.win_lgpo_auditpol.get_setting(name='Credential Validation') 51 52 # Set the state of the "Credential Validation" setting to Success and 53 # Failure 54 salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', 55 value='Success and Failure') 56 57 # Set the state of the "Credential Validation" setting to No Auditing 58 salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', 59 value='No Auditing') 60""" 61 62import logging 63import re 64import tempfile 65 66import salt.modules.cmdmod 67import salt.utils.files 68import salt.utils.platform 69from salt.exceptions import CommandExecutionError 70 71log = logging.getLogger(__name__) 72__virtualname__ = "auditpol" 73 74categories = [ 75 "Account Logon", 76 "Account Management", 77 "Detailed Tracking", 78 "DS Access", 79 "Logon/Logoff", 80 "Object Access", 81 "Policy Change", 82 "Privilege Use", 83 "System", 84] 85 86settings = { 87 "No Auditing": "/success:disable /failure:disable", 88 "Success": "/success:enable /failure:disable", 89 "Failure": "/success:disable /failure:enable", 90 "Success and Failure": "/success:enable /failure:enable", 91} 92 93 94# Although utils are often directly imported, it is also possible to use the 95# loader. 96def __virtual__(): 97 """ 98 Only load if on a Windows system 99 """ 100 if not salt.utils.platform.is_windows(): 101 return False, "This utility only available on Windows" 102 103 return __virtualname__ 104 105 106def _auditpol_cmd(cmd): 107 """ 108 Helper function for running the auditpol command 109 110 Args: 111 cmd (str): the auditpol command to run 112 113 Returns: 114 list: A list containing each line of the return (splitlines) 115 116 Raises: 117 CommandExecutionError: If the command encounters an error 118 """ 119 ret = salt.modules.cmdmod.run_all(cmd="auditpol {}".format(cmd), python_shell=True) 120 if ret["retcode"] == 0: 121 return ret["stdout"].splitlines() 122 123 msg = "Error executing auditpol command: {}\n".format(cmd) 124 msg += "\n".join(ret["stdout"]) 125 raise CommandExecutionError(msg) 126 127 128def get_settings(category="All"): 129 """ 130 Get the current configuration for all audit settings specified in the 131 category 132 133 Args: 134 category (str): 135 One of the nine categories to return. Can also be ``All`` to return 136 the settings for all categories. Valid options are: 137 138 - Account Logon 139 - Account Management 140 - Detailed Tracking 141 - DS Access 142 - Logon/Logoff 143 - Object Access 144 - Policy Change 145 - Privilege Use 146 - System 147 - All 148 149 Default value is ``All`` 150 151 Returns: 152 dict: A dictionary containing all subcategories for the specified 153 category along with their current configuration 154 155 Raises: 156 KeyError: On invalid category 157 CommandExecutionError: If an error is encountered retrieving the settings 158 159 Usage: 160 161 .. code-block:: python 162 163 import salt.utils.win_lgpo_auditpol 164 165 # Get current state of all audit settings 166 salt.utils.win_lgpo_auditpol.get_settings() 167 168 # Get the current state of all audit settings in the "Account Logon" 169 # category 170 salt.utils.win_lgpo_auditpol.get_settings(category="Account Logon") 171 """ 172 # Parameter validation 173 if category.lower() in ["all", "*"]: 174 category = "*" 175 elif category.lower() not in [x.lower() for x in categories]: 176 raise KeyError('Invalid category: "{}"'.format(category)) 177 178 cmd = '/get /category:"{}"'.format(category) 179 results = _auditpol_cmd(cmd) 180 181 ret = {} 182 # Skip the first 2 lines 183 for line in results[3:]: 184 if " " in line.strip(): 185 ret.update(dict(list(zip(*[iter(re.split(r"\s{2,}", line.strip()))] * 2)))) 186 return ret 187 188 189def get_setting(name): 190 """ 191 Get the current configuration for the named audit setting 192 193 Args: 194 name (str): The name of the setting to retrieve 195 196 Returns: 197 str: The current configuration for the named setting 198 199 Raises: 200 KeyError: On invalid setting name 201 CommandExecutionError: If an error is encountered retrieving the settings 202 203 Usage: 204 205 .. code-block:: python 206 207 import salt.utils.win_lgpo_auditpol 208 209 # Get current state of the "Credential Validation" setting 210 salt.utils.win_lgpo_auditpol.get_setting(name='Credential Validation') 211 """ 212 current_settings = get_settings(category="All") 213 for setting in current_settings: 214 if name.lower() == setting.lower(): 215 return current_settings[setting] 216 raise KeyError("Invalid name: {}".format(name)) 217 218 219def _get_valid_names(): 220 if "auditpol.valid_names" not in __context__: 221 settings = get_settings(category="All") 222 __context__["auditpol.valid_names"] = [k.lower() for k in settings] 223 return __context__["auditpol.valid_names"] 224 225 226def set_setting(name, value): 227 """ 228 Set the configuration for the named audit setting 229 230 Args: 231 232 name (str): 233 The name of the setting to configure 234 235 value (str): 236 The configuration for the named value. Valid options are: 237 238 - No Auditing 239 - Success 240 - Failure 241 - Success and Failure 242 243 Returns: 244 bool: True if successful 245 246 Raises: 247 KeyError: On invalid ``name`` or ``value`` 248 CommandExecutionError: If an error is encountered modifying the setting 249 250 Usage: 251 252 .. code-block:: python 253 254 import salt.utils.win_lgpo_auditpol 255 256 # Set the state of the "Credential Validation" setting to Success and 257 # Failure 258 salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', 259 value='Success and Failure') 260 261 # Set the state of the "Credential Validation" setting to No Auditing 262 salt.utils.win_lgpo_auditpol.set_setting(name='Credential Validation', 263 value='No Auditing') 264 """ 265 # Input validation 266 if name.lower() not in _get_valid_names(): 267 raise KeyError("Invalid name: {}".format(name)) 268 for setting in settings: 269 if value.lower() == setting.lower(): 270 cmd = '/set /subcategory:"{}" {}'.format(name, settings[setting]) 271 break 272 else: 273 raise KeyError("Invalid setting value: {}".format(value)) 274 275 _auditpol_cmd(cmd) 276 277 return True 278 279 280def get_auditpol_dump(): 281 """ 282 Gets the contents of an auditpol /backup. Used by the LGPO module to get 283 fieldnames and GUIDs for Advanced Audit policies. 284 285 Returns: 286 list: A list of lines form the backup file 287 288 Usage: 289 290 .. code-block:: python 291 292 import salt.utils.win_lgpo_auditpol 293 294 dump = salt.utils.win_lgpo_auditpol.get_auditpol_dump() 295 """ 296 # Just get a temporary file name 297 # NamedTemporaryFile will delete the file it creates by default on Windows 298 with tempfile.NamedTemporaryFile(suffix=".csv") as tmp_file: 299 csv_file = tmp_file.name 300 301 cmd = "/backup /file:{}".format(csv_file) 302 _auditpol_cmd(cmd) 303 304 with salt.utils.files.fopen(csv_file) as fp: 305 return fp.readlines() 306