PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/win_snmp.py |
""" Module for managing SNMP service settings on Windows servers. The Windows feature 'SNMP-Service' must be installed. """ import logging import salt.utils.platform from salt.exceptions import CommandExecutionError, SaltInvocationError _HKEY = "HKLM" _SNMP_KEY = r"SYSTEM\CurrentControlSet\Services\SNMP\Parameters" _AGENT_KEY = rf"{_SNMP_KEY}\RFC1156Agent" _COMMUNITIES_KEY = rf"{_SNMP_KEY}\ValidCommunities" _SNMP_GPO_KEY = r"SOFTWARE\Policies\SNMP\Parameters" _COMMUNITIES_GPO_KEY = rf"{_SNMP_GPO_KEY}\ValidCommunities" _PERMISSION_TYPES = { "None": 1, "Notify": 2, "Read Only": 4, "Read Write": 8, "Read Create": 16, } _SERVICE_TYPES = { "None": 0, "Physical": 1, "Datalink and subnetwork": 2, "Internet": 4, "End-to-end": 8, "Applications": 64, } _LOG = logging.getLogger(__name__) # Define the module's virtual name __virtualname__ = "win_snmp" def __virtual__(): """ Only works on Windows systems. """ if not salt.utils.platform.is_windows(): return False, "Module win_snmp: Requires Windows" if not __utils__["reg.key_exists"](_HKEY, _SNMP_KEY): return False, "Module win_snmp: SNMP not installed" return __virtualname__ def get_agent_service_types(): """ Get the sysServices types that can be configured. Returns: list: A list of service types. CLI Example: .. code-block:: bash salt '*' win_snmp.get_agent_service_types """ return list(_SERVICE_TYPES) def get_permission_types(): """ Get the permission types that can be configured for communities. Returns: list: A list of permission types. CLI Example: .. code-block:: bash salt '*' win_snmp.get_permission_types """ return list(_PERMISSION_TYPES) def get_agent_settings(): """ Determine the value of the SNMP sysContact, sysLocation, and sysServices settings. Returns: dict: A dictionary of the agent settings. CLI Example: .. code-block:: bash salt '*' win_snmp.get_agent_settings """ ret = dict() sorted_types = sorted(_SERVICE_TYPES.items(), key=lambda x: (-x[1], x[0])) ret["services"] = list() ret["contact"] = (__utils__["reg.read_value"](_HKEY, _AGENT_KEY, "sysContact"))[ "vdata" ] ret["location"] = (__utils__["reg.read_value"](_HKEY, _AGENT_KEY, "sysLocation"))[ "vdata" ] current_bitmask = (__utils__["reg.read_value"](_HKEY, _AGENT_KEY, "sysServices"))[ "vdata" ] if current_bitmask == 0: ret["services"].append(sorted_types[-1][0]) else: # sorted_types is sorted from greatest to least bitmask. for service, bitmask in sorted_types: if current_bitmask is not None and current_bitmask > 0: remaining_bitmask = current_bitmask - bitmask if remaining_bitmask >= 0: current_bitmask = remaining_bitmask ret["services"].append(service) else: break ret["services"] = sorted(ret["services"]) return ret def set_agent_settings(contact=None, location=None, services=None): """ Manage the SNMP sysContact, sysLocation, and sysServices settings. Args: contact (str, optional): The SNMP contact. location (str, optional): The SNMP location. services (list, optional): A list of selected services. The possible service names can be found via ``win_snmp.get_agent_service_types``. To disable all services pass a list of None, ie: ['None'] Returns: bool: True if successful, otherwise False CLI Example: .. code-block:: bash salt '*' win_snmp.set_agent_settings contact='Contact Name' location='Place' services="['Physical']" """ if services is not None: # Filter services for unique items, and sort them for comparison # purposes. services = sorted(set(services)) # Validate the services. for service in services: if service not in _SERVICE_TYPES: message = "Invalid service '{}' specified. Valid services: {}".format( service, get_agent_service_types() ) raise SaltInvocationError(message) settings = {"contact": contact, "location": location, "services": services} current_settings = get_agent_settings() if settings == current_settings: _LOG.debug("Agent settings already contain the provided values.") return True if contact is not None: if contact != current_settings["contact"]: __utils__["reg.set_value"]( _HKEY, _AGENT_KEY, "sysContact", contact, "REG_SZ" ) if location is not None: if location != current_settings["location"]: __utils__["reg.set_value"]( _HKEY, _AGENT_KEY, "sysLocation", location, "REG_SZ" ) if services is not None: if set(services) != set(current_settings["services"]): # Calculate the total value. Produces 0 if an empty list was provided, # corresponding to the None _SERVICE_TYPES value. vdata = sum(_SERVICE_TYPES[service] for service in services) _LOG.debug("Setting sysServices vdata to: %s", vdata) __utils__["reg.set_value"]( _HKEY, _AGENT_KEY, "sysServices", vdata, "REG_DWORD" ) # Get the fields post-change so that we can verify tht all values # were modified successfully. Track the ones that weren't. new_settings = get_agent_settings() failed_settings = dict() for setting in settings: if settings[setting] is not None and settings[setting] != new_settings[setting]: failed_settings[setting] = settings[setting] if failed_settings: _LOG.error("Unable to configure agent settings: %s", failed_settings) return False _LOG.debug("Agent settings configured successfully: %s", settings.keys()) return True def get_auth_traps_enabled(): """ Determine whether the host is configured to send authentication traps. Returns: bool: True if traps are enabled, otherwise False CLI Example: .. code-block:: bash salt '*' win_snmp.get_auth_traps_enabled """ reg_ret = __utils__["reg.read_value"](_HKEY, _SNMP_KEY, "EnableAuthenticationTraps") if reg_ret["vdata"] == "(value not set)": return False return bool(reg_ret["vdata"] or 0) def set_auth_traps_enabled(status=True): """ Manage the sending of authentication traps. Args: status (bool): True to enable traps. False to disable. Returns: bool: True if successful, otherwise False CLI Example: .. code-block:: bash salt '*' win_snmp.set_auth_traps_enabled status='True' """ vname = "EnableAuthenticationTraps" current_status = get_auth_traps_enabled() if bool(status) == current_status: _LOG.debug("%s already contains the provided value.", vname) return True vdata = int(status) __utils__["reg.set_value"](_HKEY, _SNMP_KEY, vname, vdata, "REG_DWORD") new_status = get_auth_traps_enabled() if status == new_status: _LOG.debug("Setting %s configured successfully: %s", vname, vdata) return True _LOG.error("Unable to configure %s with value: %s", vname, vdata) return False def get_community_names(): """ Get the current accepted SNMP community names and their permissions. If community names are being managed by Group Policy, those values will be returned instead like this: .. code-block:: bash TestCommunity: Managed by GPO Community names managed normally will denote the permission instead: .. code-block:: bash TestCommunity: Read Only Returns: dict: A dictionary of community names and permissions. CLI Example: .. code-block:: bash salt '*' win_snmp.get_community_names """ ret = dict() # Look in GPO settings first if __utils__["reg.key_exists"](_HKEY, _COMMUNITIES_GPO_KEY): _LOG.debug("Loading communities from Group Policy settings") current_values = __utils__["reg.list_values"](_HKEY, _COMMUNITIES_GPO_KEY) # GPO settings are different in that they do not designate permissions # They are a numbered list of communities like so: # # {1: "community 1", # 2: "community 2"} # # Denote that it is being managed by Group Policy. # # community 1: # Managed by GPO # community 2: # Managed by GPO if isinstance(current_values, list): for current_value in current_values: # Ignore error values if not isinstance(current_value, dict): continue ret[current_value["vdata"]] = "Managed by GPO" if not ret: _LOG.debug("Loading communities from SNMP settings") current_values = __utils__["reg.list_values"](_HKEY, _COMMUNITIES_KEY) # The communities are stored as the community name with a numeric # permission value. Like this (4 = Read Only): # # {"community 1": 4, # "community 2": 4} # # Convert the numeric value to the text equivalent, as present in the # Windows SNMP service GUI. # # community 1: # Read Only # community 2: # Read Only if isinstance(current_values, list): for current_value in current_values: # Ignore error values if not isinstance(current_value, dict): continue permissions = "" for permission_name in _PERMISSION_TYPES: if current_value["vdata"] == _PERMISSION_TYPES[permission_name]: permissions = permission_name break ret[current_value["vname"]] = permissions if not ret: _LOG.debug("Unable to find existing communities.") return ret def set_community_names(communities): """ Manage the SNMP accepted community names and their permissions. .. note:: Settings managed by Group Policy will always take precedence over those set using the SNMP interface. Therefore if this function finds Group Policy settings it will raise a CommandExecutionError Args: communities (dict): A dictionary of SNMP community names and permissions. The possible permissions can be found via ``win_snmp.get_permission_types``. Returns: bool: True if successful, otherwise False Raises: CommandExecutionError: If SNMP settings are being managed by Group Policy CLI Example: .. code-block:: bash salt '*' win_snmp.set_community_names communities="{'TestCommunity': 'Read Only'}' """ values = dict() if __utils__["reg.key_exists"](_HKEY, _COMMUNITIES_GPO_KEY): _LOG.debug("Communities on this system are managed by Group Policy") raise CommandExecutionError( "Communities on this system are managed by Group Policy" ) current_communities = get_community_names() if communities == current_communities: _LOG.debug("Communities already contain the provided values.") return True for vname in communities: if not communities[vname]: communities[vname] = "None" try: vdata = _PERMISSION_TYPES[communities[vname]] except KeyError: raise SaltInvocationError( "Invalid permission '{}' specified. Valid permissions: {}".format( communities[vname], _PERMISSION_TYPES.keys() ) ) values[vname] = vdata # Check current communities. for current_vname in current_communities: if current_vname in values: # Modify existing communities that have a different permission value. if current_communities[current_vname] != values[current_vname]: __utils__["reg.set_value"]( _HKEY, _COMMUNITIES_KEY, current_vname, values[current_vname], "REG_DWORD", ) else: # Remove current communities that weren't provided. __utils__["reg.delete_value"](_HKEY, _COMMUNITIES_KEY, current_vname) # Create any new communities. for vname in values: if vname not in current_communities: __utils__["reg.set_value"]( _HKEY, _COMMUNITIES_KEY, vname, values[vname], "REG_DWORD" ) # Get the fields post-change so that we can verify tht all values # were modified successfully. Track the ones that weren't. new_communities = get_community_names() failed_communities = dict() for new_vname in new_communities: if new_vname not in communities: failed_communities[new_vname] = None for vname in communities: if communities[vname] != new_communities[vname]: failed_communities[vname] = communities[vname] if failed_communities: _LOG.error("Unable to configure communities: %s", failed_communities) return False _LOG.debug("Communities configured successfully: %s", communities.keys()) return True