File manager - Edit - /opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/win_lgpo_auditpol.py
Back
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 Audit policy is read and written using the Windows ``advapi32`` APIs (``AuditQuerySystemPolicy`` / ``AuditSetSystemPolicy``) with a static subcategory GUID to English name map, so behavior is consistent regardless of the host OS display language. 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. Subcategory names are **canonical English** strings (they match the names Salt and LGPO use, not the host OS localized ``auditpol`` display names). 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 The module constant ``settings`` maps those English labels to the integer **auditing bitmask** passed to ``AuditSetSystemPolicy`` (``0``–``3``, aligned with LGPO ``audit.csv`` ``Setting Value``). Execution modules should keep using the string labels; callers should not rely on ``settings`` values being ``auditpol.exe`` switch strings. LGPO loads defaults via :func:`get_advaudit_policy_rows`; :func:`get_auditpol_dump` serializes the same data as UTF-8 CSV lines for backward compatibility. 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') """ from __future__ import annotations import contextlib import csv import ctypes import io import logging import struct import uuid from ctypes import wintypes as w from types import SimpleNamespace import salt.utils.platform from salt.exceptions import CommandExecutionError log = logging.getLogger(__name__) __virtualname__ = "auditpol" __context__ = {} categories = [ "Account Logon", "Account Management", "Detailed Tracking", "DS Access", "Logon/Logoff", "Object Access", "Policy Change", "Privilege Use", "System", ] # English value label -> bitmask for AuditSetSystemPolicy (matches LGPO 0–3) settings = { "No Auditing": 0, "Success": 1, "Failure": 2, "Success and Failure": 3, } _AUDIT_NONE = 0 _AUDIT_SUCCESS = 1 _AUDIT_FAILURE = 2 _TOKEN_QUERY = 0x0008 _TOKEN_ADJUST_PRIVILEGES = 0x0020 _SE_PRIVILEGE_ENABLED = 0x00000002 _FIELDNAMES = [ "Machine Name", "Policy Target", "Subcategory", "Subcategory GUID", "Inclusion Setting", "Exclusion Setting", "Setting Value", ] class _GUID(ctypes.Structure): """Win32 ``GUID`` layout (``Data1``..``Data4``) for ``Audit*`` APIs.""" _fields_ = [ ("Data1", w.DWORD), ("Data2", w.WORD), ("Data3", w.WORD), ("Data4", w.BYTE * 8), ] class _AUDIT_POLICY_INFORMATION(ctypes.Structure): """``AUDIT_POLICY_INFORMATION`` from ntsecapi / advapi32 (per subcategory).""" _fields_ = [ ("AuditSubcategoryGuid", _GUID), ("AuditingInformation", w.ULONG), ("AuditCategoryGuid", _GUID), ] class _LUID(ctypes.Structure): """Locally unique identifier (used with ``LookupPrivilegeValueW``).""" _fields_ = [("LowPart", w.DWORD), ("HighPart", w.LONG)] class _LUID_AND_ATTRIBUTES(ctypes.Structure): """One privilege entry for ``TOKEN_PRIVILEGES``.""" _fields_ = [("Luid", _LUID), ("Attributes", w.DWORD)] class _TOKEN_PRIVILEGES(ctypes.Structure): """``TOKEN_PRIVILEGES`` with a single ``LUID_AND_ATTRIBUTES`` (fixed size).""" _fields_ = [("PrivilegeCount", w.DWORD), ("Privileges", _LUID_AND_ATTRIBUTES * 1)] def _load_advapi32(): """ Bind advapi32/kernel32 entry points used for audit policy and token privileges. ``use_last_error=True`` so ``ctypes.get_last_error()`` matches Win32 failures after each call. """ advapi32_dll = ctypes.WinDLL("advapi32", use_last_error=True) kernel32_dll = ctypes.WinDLL("kernel32", use_last_error=True) # AuditQuerySystemPolicy — ntsecapi.h; ppAuditPolicy is heap-allocated; free # with AuditFree. Local names match Win32 exports for easier MSDN lookup. AuditQuerySystemPolicy = advapi32_dll.AuditQuerySystemPolicy AuditQuerySystemPolicy.argtypes = [ ctypes.POINTER(_GUID), w.ULONG, ctypes.POINTER(ctypes.POINTER(_AUDIT_POLICY_INFORMATION)), ] AuditQuerySystemPolicy.restype = w.BOOL # AuditSetSystemPolicy — category GUID member ignored per MSDN. AuditSetSystemPolicy = advapi32_dll.AuditSetSystemPolicy AuditSetSystemPolicy.argtypes = [ ctypes.POINTER(_AUDIT_POLICY_INFORMATION), w.ULONG, ] AuditSetSystemPolicy.restype = w.BOOL AuditFree = advapi32_dll.AuditFree AuditFree.argtypes = [w.LPVOID] AuditFree.restype = None OpenProcessToken = advapi32_dll.OpenProcessToken OpenProcessToken.argtypes = [w.HANDLE, w.DWORD, ctypes.POINTER(w.HANDLE)] OpenProcessToken.restype = w.BOOL LookupPrivilegeValueW = advapi32_dll.LookupPrivilegeValueW LookupPrivilegeValueW.argtypes = [ w.LPCWSTR, w.LPCWSTR, ctypes.POINTER(_LUID), ] LookupPrivilegeValueW.restype = w.BOOL AdjustTokenPrivileges = advapi32_dll.AdjustTokenPrivileges AdjustTokenPrivileges.argtypes = [ w.HANDLE, w.BOOL, ctypes.POINTER(_TOKEN_PRIVILEGES), w.DWORD, ctypes.c_void_p, ctypes.c_void_p, ] AdjustTokenPrivileges.restype = w.BOOL GetCurrentProcess = kernel32_dll.GetCurrentProcess GetCurrentProcess.argtypes = [] GetCurrentProcess.restype = w.HANDLE CloseHandle = kernel32_dll.CloseHandle CloseHandle.argtypes = [w.HANDLE] CloseHandle.restype = w.BOOL return SimpleNamespace( AuditQuerySystemPolicy=AuditQuerySystemPolicy, AuditSetSystemPolicy=AuditSetSystemPolicy, AuditFree=AuditFree, OpenProcessToken=OpenProcessToken, LookupPrivilegeValueW=LookupPrivilegeValueW, AdjustTokenPrivileges=AdjustTokenPrivileges, GetCurrentProcess=GetCurrentProcess, CloseHandle=CloseHandle, ) _API = None def _api(): """ Lazy singleton of :func:`_load_advapi32` bindings (``_API`` cache). Attributes use **PascalCase** names matching the Win32 exports (e.g. ``AuditQuerySystemPolicy``) for parity with MSDN and headers. """ global _API if _API is None: _API = _load_advapi32() return _API def _uuid_to_guid(subcategory_uuid: uuid.UUID) -> _GUID: """ Pack a Python :class:`uuid.UUID` into the Win32 ``GUID`` memory layout. ``UUID.bytes_le`` matches how ``GUID`` fields are ordered in RAM for the ``Data1``/``Data2``/``Data3``/``Data4`` split used by ``AuditQuerySystemPolicy``. """ uuid_bytes_le = subcategory_uuid.bytes_le guid_struct = _GUID() guid_struct.Data1, guid_struct.Data2, guid_struct.Data3 = struct.unpack( "<IHH", uuid_bytes_le[:8] ) ctypes.memmove(guid_struct.Data4, uuid_bytes_le[8:16], 8) return guid_struct def _mask_to_labels(audit_mask: int) -> tuple[str, str]: """Map ``AuditingInformation`` bitmask to (Inclusion Setting, Setting Value str).""" success_on = bool(audit_mask & _AUDIT_SUCCESS) failure_on = bool(audit_mask & _AUDIT_FAILURE) if success_on and failure_on: return "Success and Failure", "3" if success_on: return "Success", "1" if failure_on: return "Failure", "2" return "No Auditing", "0" @contextlib.contextmanager def _enable_se_security_privilege(): """ Enable ``SeSecurityPrivilege`` on this process for the duration of the ``with`` block (required for ``AuditSetSystemPolicy``). """ win32 = _api() process_token_handle = w.HANDLE() if not win32.OpenProcessToken( win32.GetCurrentProcess(), _TOKEN_ADJUST_PRIVILEGES | _TOKEN_QUERY, ctypes.byref(process_token_handle), ): raise CommandExecutionError( "OpenProcessToken failed", info={"errno": ctypes.get_last_error()} ) try: security_privilege_luid = _LUID() if not win32.LookupPrivilegeValueW( None, "SeSecurityPrivilege", ctypes.byref(security_privilege_luid) ): raise CommandExecutionError( "LookupPrivilegeValueW(SeSecurityPrivilege) failed", info={"errno": ctypes.get_last_error()}, ) token_privileges = _TOKEN_PRIVILEGES() token_privileges.PrivilegeCount = 1 token_privileges.Privileges[0].Luid = security_privilege_luid token_privileges.Privileges[0].Attributes = _SE_PRIVILEGE_ENABLED if not win32.AdjustTokenPrivileges( process_token_handle, False, ctypes.byref(token_privileges), ctypes.sizeof(token_privileges), None, None, ): raise CommandExecutionError( "AdjustTokenPrivileges failed", info={"errno": ctypes.get_last_error()}, ) yield finally: win32.CloseHandle(process_token_handle) def _query_system_policies(): """ Call ``AuditQuerySystemPolicy`` for every subcategory in :data:`_AUDIT_SUBCATEGORY_METADATA`. Returns: list: One tuple per row: ``(category_name, subcategory_name, subcategory_uuid, audit_mask)`` — ``audit_mask`` is the raw ``AuditingInformation`` ULONG (success/failure bits per MSDN). """ metadata_rows = _AUDIT_SUBCATEGORY_METADATA subcategory_count = len(metadata_rows) # Contiguous array of GUIDs — required; passing a single GUID pointer is a # common marshaling mistake and yields ERROR_INVALID_PARAMETER. guid_array_type = _GUID * subcategory_count subcategory_guid_array = guid_array_type() subcategory_uuids_ordered = [] for index, (_category, _subcategory, guid_string) in enumerate(metadata_rows): parsed_uuid = uuid.UUID(guid_string) subcategory_uuids_ordered.append(parsed_uuid) subcategory_guid_array[index] = _uuid_to_guid(parsed_uuid) # Output: pointer to heap array of AUDIT_POLICY_INFORMATION (same length). allocated_policy_array_ptr = ctypes.POINTER(_AUDIT_POLICY_INFORMATION)() win32 = _api() if not win32.AuditQuerySystemPolicy( subcategory_guid_array, subcategory_count, ctypes.byref(allocated_policy_array_ptr), ): err = ctypes.get_last_error() raise CommandExecutionError( "AuditQuerySystemPolicy failed", info={"errno": err}, ) if not allocated_policy_array_ptr: return [ ( metadata_rows[i][0], metadata_rows[i][1], subcategory_uuids_ordered[i], 0, ) for i in range(subcategory_count) ] try: results = [] for index in range(subcategory_count): policy_info_struct = allocated_policy_array_ptr[index] results.append( ( metadata_rows[index][0], metadata_rows[index][1], subcategory_uuids_ordered[index], int(policy_info_struct.AuditingInformation), ) ) return results finally: win32.AuditFree(allocated_policy_array_ptr) # (category, subcategory English name as in auditpol backup / set, GUID string) # GUIDs align with Microsoft advanced audit subcategories (see e.g. PowerShell # AuditPolicyDsc AuditPolicyResourceHelper). _AUDIT_SUBCATEGORY_METADATA = [ ("System", "Security State Change", "{0CCE9210-69AE-11D9-BED3-505054503030}"), ("System", "Security System Extension", "{0CCE9211-69AE-11D9-BED3-505054503030}"), ("System", "System Integrity", "{0CCE9212-69AE-11D9-BED3-505054503030}"), ("System", "IPsec Driver", "{0CCE9213-69AE-11D9-BED3-505054503030}"), ("System", "Other System Events", "{0CCE9214-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "Logon", "{0CCE9215-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "Logoff", "{0CCE9216-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "Account Lockout", "{0CCE9217-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "IPsec Main Mode", "{0CCE9218-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "IPsec Quick Mode", "{0CCE9219-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "IPsec Extended Mode", "{0CCE921A-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "Special Logon", "{0CCE921B-69AE-11D9-BED3-505054503030}"), ( "Logon/Logoff", "Other Logon/Logoff Events", "{0CCE921C-69AE-11D9-BED3-505054503030}", ), ("Logon/Logoff", "Network Policy Server", "{0CCE9243-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "User / Device Claims", "{0CCE9247-69AE-11D9-BED3-505054503030}"), ("Logon/Logoff", "Group Membership", "{0CCE9249-69AE-11D9-BED3-505054503030}"), ("Object Access", "File System", "{0CCE921D-69AE-11D9-BED3-505054503030}"), ("Object Access", "Registry", "{0CCE921E-69AE-11D9-BED3-505054503030}"), ("Object Access", "Kernel Object", "{0CCE921F-69AE-11D9-BED3-505054503030}"), ("Object Access", "SAM", "{0CCE9220-69AE-11D9-BED3-505054503030}"), ( "Object Access", "Certification Services", "{0CCE9221-69AE-11D9-BED3-505054503030}", ), ( "Object Access", "Application Generated", "{0CCE9222-69AE-11D9-BED3-505054503030}", ), ("Object Access", "Handle Manipulation", "{0CCE9223-69AE-11D9-BED3-505054503030}"), ("Object Access", "File Share", "{0CCE9224-69AE-11D9-BED3-505054503030}"), ( "Object Access", "Filtering Platform Packet Drop", "{0CCE9225-69AE-11D9-BED3-505054503030}", ), ( "Object Access", "Filtering Platform Connection", "{0CCE9226-69AE-11D9-BED3-505054503030}", ), ( "Object Access", "Other Object Access Events", "{0CCE9227-69AE-11D9-BED3-505054503030}", ), ("Object Access", "Detailed File Share", "{0CCE9244-69AE-11D9-BED3-505054503030}"), ("Object Access", "Removable Storage", "{0CCE9245-69AE-11D9-BED3-505054503030}"), ( "Object Access", "Central Policy Staging", "{0CCE9246-69AE-11D9-BED3-505054503030}", ), ( "Privilege Use", "Sensitive Privilege Use", "{0CCE9228-69AE-11D9-BED3-505054503030}", ), ( "Privilege Use", "Non Sensitive Privilege Use", "{0CCE9229-69AE-11D9-BED3-505054503030}", ), ( "Privilege Use", "Other Privilege Use Events", "{0CCE922A-69AE-11D9-BED3-505054503030}", ), ("Detailed Tracking", "Process Creation", "{0CCE922B-69AE-11D9-BED3-505054503030}"), ( "Detailed Tracking", "Process Termination", "{0CCE922C-69AE-11D9-BED3-505054503030}", ), ("Detailed Tracking", "DPAPI Activity", "{0CCE922D-69AE-11D9-BED3-505054503030}"), ("Detailed Tracking", "RPC Events", "{0CCE922E-69AE-11D9-BED3-505054503030}"), ( "Detailed Tracking", "Plug and Play Events", "{0CCE9248-69AE-11D9-BED3-505054503030}", ), ( "Detailed Tracking", "Token Right Adjusted Events", "{0CCE924A-69AE-11D9-BED3-505054503030}", ), ("Policy Change", "Audit Policy Change", "{0CCE922F-69AE-11D9-BED3-505054503030}"), ( "Policy Change", "Authentication Policy Change", "{0CCE9230-69AE-11D9-BED3-505054503030}", ), ( "Policy Change", "Authorization Policy Change", "{0CCE9231-69AE-11D9-BED3-505054503030}", ), ( "Policy Change", "MPSSVC Rule-Level Policy Change", "{0CCE9232-69AE-11D9-BED3-505054503030}", ), ( "Policy Change", "Filtering Platform Policy Change", "{0CCE9233-69AE-11D9-BED3-505054503030}", ), ( "Policy Change", "Other Policy Change Events", "{0CCE9234-69AE-11D9-BED3-505054503030}", ), ( "Account Management", "User Account Management", "{0CCE9235-69AE-11D9-BED3-505054503030}", ), ( "Account Management", "Computer Account Management", "{0CCE9236-69AE-11D9-BED3-505054503030}", ), ( "Account Management", "Security Group Management", "{0CCE9237-69AE-11D9-BED3-505054503030}", ), ( "Account Management", "Distribution Group Management", "{0CCE9238-69AE-11D9-BED3-505054503030}", ), ( "Account Management", "Application Group Management", "{0CCE9239-69AE-11D9-BED3-505054503030}", ), ( "Account Management", "Other Account Management Events", "{0CCE923A-69AE-11D9-BED3-505054503030}", ), ("DS Access", "Directory Service Access", "{0CCE923B-69AE-11D9-BED3-505054503030}"), ( "DS Access", "Directory Service Changes", "{0CCE923C-69AE-11D9-BED3-505054503030}", ), ( "DS Access", "Directory Service Replication", "{0CCE923D-69AE-11D9-BED3-505054503030}", ), ( "DS Access", "Detailed Directory Service Replication", "{0CCE923E-69AE-11D9-BED3-505054503030}", ), ( "Account Logon", "Credential Validation", "{0CCE923F-69AE-11D9-BED3-505054503030}", ), ( "Account Logon", "Kerberos Service Ticket Operations", "{0CCE9240-69AE-11D9-BED3-505054503030}", ), ( "Account Logon", "Other Account Logon Events", "{0CCE9241-69AE-11D9-BED3-505054503030}", ), ( "Account Logon", "Kerberos Authentication Service", "{0CCE9242-69AE-11D9-BED3-505054503030}", ), ] 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 get_advaudit_policy_rows(): """ Return one row per advanced audit subcategory for LGPO and related code. Rows are built from ``AuditQuerySystemPolicy`` and the in-module GUID/name table, so they do not depend on ``auditpol.exe`` or the host display language. Returns: list: A list of dictionaries, each with keys ``Machine Name``, ``Policy Target``, ``Subcategory``, ``Subcategory GUID``, ``Inclusion Setting``, ``Exclusion Setting``, and ``Setting Value``. ``Machine Name`` is always ``""``; ``Policy Target`` is ``System``; ``Subcategory`` is the English name used with :func:`set_setting`; ``Subcategory GUID`` is braced uppercase; ``Setting Value`` is ``"0"``–``"3"`` matching LGPO's ``audit.csv`` convention. Raises: CommandExecutionError: If the Windows API call fails. """ rows_out = [] for (_metadata_category, subcategory, guid_string), query_row in zip( _AUDIT_SUBCATEGORY_METADATA, _query_system_policies() ): _, _, _, audit_mask = query_row inclusion, setting_val = _mask_to_labels(audit_mask) guid_braced = guid_string.upper() rows_out.append( { "Machine Name": "", "Policy Target": "System", "Subcategory": subcategory, "Subcategory GUID": guid_braced, "Inclusion Setting": inclusion, "Exclusion Setting": "", "Setting Value": setting_val, } ) return rows_out def get_settings(category="All"): """ Get the current configuration for all audit settings in the given category. Reads effective policy via ``AuditQuerySystemPolicy`` (not ``auditpol /get``), so results use English subcategory keys and English value labels regardless of OS language. Args: category (str): One of the nine categories, or ``All`` / ``*`` for every subcategory. Names are matched case-insensitively against :data:`categories`. Returns: dict: Maps each **English** subcategory name to one of ``No Auditing``, ``Success``, ``Failure``, or ``Success and Failure``. Raises: KeyError: If ``category`` is not recognized. CommandExecutionError: If the Windows API call fails. """ if category.lower() in ["all", "*"]: want = None else: want = None for c in categories: if c.lower() == category.lower(): want = c break if want is None: raise KeyError(f'Invalid category: "{category}"') ret = {} for (category_name, subcategory_name, _subcategory_uuid), query_row in zip( _AUDIT_SUBCATEGORY_METADATA, _query_system_policies() ): _, _, _, audit_mask = query_row if want is not None and category_name != want: continue label, _setting_value_str = _mask_to_labels(audit_mask) ret[subcategory_name] = label return ret def get_setting(name): """ Get the current configuration for a single subcategory. Args: name (str): English subcategory name (matched case-insensitively). Returns: str: One of ``No Auditing``, ``Success``, ``Failure``, or ``Success and Failure``. Raises: KeyError: If ``name`` is not a known subcategory. CommandExecutionError: If querying the current policy fails. """ current_settings = get_settings(category="All") for setting in current_settings: if name.lower() == setting.lower(): return current_settings[setting] raise KeyError(f"Invalid name: {name}") def _get_valid_names(): """ Return lowercase English subcategory names valid for :func:`set_setting`. Cached on ``__context__['auditpol.valid_names']`` until cleared after a successful :func:`set_setting`. """ if "auditpol.valid_names" not in __context__: settings_map = get_settings(category="All") __context__["auditpol.valid_names"] = [k.lower() for k in settings_map] return __context__["auditpol.valid_names"] def set_setting(name, value): """ Set the auditing bitmask for one subcategory. Enables ``SeSecurityPrivilege`` on the current process token for the duration of the ``AuditSetSystemPolicy`` call. Args: name (str): English subcategory name (same strings as returned by :func:`get_settings`). value (str): One of ``No Auditing``, ``Success``, ``Failure``, or ``Success and Failure`` (matched case-insensitively). Returns: bool: ``True`` on success. Raises: KeyError: On invalid ``name`` or ``value``. CommandExecutionError: If privilege adjustment or ``AuditSetSystemPolicy`` fails. """ if name.lower() not in _get_valid_names(): raise KeyError(f"Invalid name: {name}") audit_bitmask = None for setting in settings: if value.lower() == setting.lower(): audit_bitmask = int(settings[setting]) break if audit_bitmask is None: raise KeyError(f"Invalid setting value: {value}") resolved_subcategory_name = None resolved_subcategory_uuid = None for _meta_cat, meta_subcategory, guid_string in _AUDIT_SUBCATEGORY_METADATA: if name.lower() == meta_subcategory.lower(): resolved_subcategory_name = meta_subcategory resolved_subcategory_uuid = uuid.UUID(guid_string) break if resolved_subcategory_uuid is None: raise KeyError(f"Invalid name: {name}") audit_policy_info = _AUDIT_POLICY_INFORMATION() audit_policy_info.AuditSubcategoryGuid = _uuid_to_guid(resolved_subcategory_uuid) audit_policy_info.AuditingInformation = audit_bitmask audit_policy_info.AuditCategoryGuid = _GUID() win32 = _api() with _enable_se_security_privilege(): policy_count = 1 if not win32.AuditSetSystemPolicy( ctypes.byref(audit_policy_info), policy_count ): err = ctypes.get_last_error() raise CommandExecutionError( "AuditSetSystemPolicy failed", info={ "errno": err, "name": resolved_subcategory_name, "value": value, }, ) __context__.pop("auditpol.valid_names", None) return True def get_auditpol_dump(): """ Return advanced audit policy rows as CSV **text lines** (UTF-8). This does not run ``auditpol /backup`` or read a temp file. It formats the same data as :func:`get_advaudit_policy_rows` using :mod:`csv`, so each line is a normal Unicode string (newlines ``\\n``). Returns: list: Lines including a header row, suitable for passing to :class:`csv.DictReader` if needed. Raises: CommandExecutionError: If building rows fails (e.g. API error from :func:`get_advaudit_policy_rows`). """ buf = io.StringIO(newline="") writer = csv.DictWriter(buf, fieldnames=_FIELDNAMES, lineterminator="\n") writer.writeheader() for row in get_advaudit_policy_rows(): writer.writerow(row) buf.seek(0) return buf.readlines()
| ver. 1.4 |
Github
|
.
| PHP 8.2.30 | Generation time: 0 |
proxy
|
phpinfo
|
Settings