Skip to content

Commit

Permalink
Merge pull request #6 from sophos/snmp
Browse files Browse the repository at this point in the history
Feat: SNMP Agent and SNMPv3 users
  • Loading branch information
mamullen13316 authored Oct 15, 2024
2 parents 8ca5856 + 6e5f3e7 commit 8ff3b8a
Show file tree
Hide file tree
Showing 7 changed files with 1,190 additions and 9 deletions.
23 changes: 20 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,37 @@

**Topics**

- <a href="#v1-0-0">v1\.0\.0</a>
- <a href="#v1-1-0">v1\.1\.0</a>
- <a href="#release-summary">Release Summary</a>
- <a href="#new-modules">New Modules</a>
- <a href="#v1-0-0">v1\.0\.0</a>
- <a href="#release-summary-1">Release Summary</a>
- <a href="#new-modules-1">New Modules</a>

<a id="v1-1-0"></a>
## v1\.1\.0

<a id="release-summary"></a>
### Release Summary

This release contains new modules for working with the SNMP agent and SNMPv3 users on Sophos Firewall

<a id="new-modules"></a>
### New Modules

* sophos\.sophos\_firewall\.sfos\_snmp\_agent \- Manage SNMP Agent \(System \> Administration \> SNMP\)\.
* sophos\.sophos\_firewall\.sfos\_snmp\_user \- Manage SNMPv3 User \(System \> Administration \> SNMP\)\.

<a id="v1-0-0"></a>
## v1\.0\.0

<a id="release-summary"></a>
<a id="release-summary-1"></a>
### Release Summary

This is the first proper release of the <code>sophos\.sophos\_firewall</code> collection\.
The changelog describes all changes made to the modules and plugins included in this collection\.

<a id="new-modules"></a>
<a id="new-modules-1"></a>
### New Modules

* sophos\.sophos\_firewall\.sfos\_admin\_settings \- Manage Admin and user settings \(System \> Administration\)\.
Expand Down
14 changes: 14 additions & 0 deletions changelogs/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,17 @@ releases:
name: sfos_zone
namespace: ''
release_date: '2024-10-08'
1.1.0:
changes:
release_summary: This release contains new modules for working with the SNMP
agent and SNMPv3 users on Sophos Firewall
fragments:
- 1.1.0.yml
modules:
- description: Manage SNMP Agent (System > Administration > SNMP).
name: sfos_snmp_agent
namespace: ''
- description: Manage SNMPv3 User (System > Administration > SNMP).
name: sfos_snmp_user
namespace: ''
release_date: '2024-10-15'
282 changes: 282 additions & 0 deletions plugins/modules/sfos_snmp_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
#!/usr/bin/python

# Copyright 2024 Sophos Ltd. All rights reserved.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function

__metaclass__ = type

DOCUMENTATION = r"""
---
module: sfos_snmp_agent
short_description: Manage SNMP Agent (System > Administration > SNMP)
version_added: "1.1.0"
description: Manage SNMP Agent (System > Administration > SNMP) on Sophos Firewall
extends_documentation_fragment:
- sophos.sophos_firewall.fragments.base
options:
enabled:
description: Enable (true) or disable (false) threat feeds
type: bool
required: false
name:
description: Identifying name of firewall
type: str
required: false
description:
description: Description assigned to SNMP agent
type: str
required: false
location:
description: SNMP location
type: str
required: false
contact_person:
description: SNMP contact
type: str
required: false
state:
description:
- Use C(query) to retrieve or C(updated) to modify
choices: [updated, query]
type: str
required: true
author:
- Matt Mullen (@mamullen13316)
"""

EXAMPLES = r"""
- name: Update SNMP agent configuration
sophos.sophos_firewall.sfos_snmp_agent:
username: "{{ username }}"
password: "{{ password }}"
hostname: "{{ inventory_hostname }}"
port: 4444
verify: false
enabled: true
name: testfirewall
description: Firewall used for automation testing
location: AWS
contact_person: Network Operations
state: updated
delegate_to: localhost
- name: Query advanced threat protection settings
sophos.sophos_firewall.sfos_snmp_agent:
username: "{{ username }}"
password: "{{ password }}"
hostname: "{{ inventory_hostname }}"
port: 4444
verify: false
state: query
delegate_to: localhost
"""

RETURN = r"""
api_response:
description: Serialized object containing the API response.
type: dict
returned: always
"""
import io
import contextlib

output_buffer = io.StringIO()

try:
from sophosfirewall_python.firewallapi import (
SophosFirewall,
SophosFirewallZeroRecords,
SophosFirewallAuthFailure,
SophosFirewallAPIError,
)
from requests.exceptions import RequestException

PREREQ_MET = {"result": True}
except ImportError as errMsg:
PREREQ_MET = {"result": False, "missing_module": errMsg.name}


from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import missing_required_lib


def get_snmp_agent(fw_obj, module, result):
"""Get current SNMP agent settings from Sophos Firewall
Args:
fw_obj (SophosFirewall): SophosFirewall object
module (AnsibleModule): AnsibleModule object
result (dict): Result output to be sent to the console
Returns:
dict: Results of lookup
"""
try:
resp = fw_obj.get_tag("SNMPAgentConfiguration")
except SophosFirewallZeroRecords as error:
return {"exists": False, "api_response": str(error)}
except SophosFirewallAuthFailure as error:
module.fail_json(msg="Authentication error: {0}".format(error), **result)
except SophosFirewallAPIError as error:
module.fail_json(msg="API Error: {0}".format(error), **result)
except RequestException as error:
module.fail_json(msg="Error communicating to API: {0}".format(error), **result)

return {"exists": True, "api_response": resp}


def update_snmp_agent(fw_obj, module, result):
"""Update SNMP agent configuration on Sophos Firewall
Args:
fw_obj (SophosFirewall): SophosFirewall object
module (AnsibleModule): AnsibleModule object
result (dict): Result output to be sent to the console
Returns:
dict: API response
"""
update_params = {}
if module.params.get("enabled") is True:
update_params["Configuration"] = "Enable"
elif module.params.get("enabled") is False:
update_params["Configuration"] = "Disable"

if module.params.get("description"):
update_params["Description"] = module.params.get("description")

if module.params.get("name"):
update_params["Name"] = module.params.get("name")

if module.params.get("location"):
update_params["Location"] = module.params.get("location")

if module.params.get("contact_person"):
update_params["ContactPerson"] = module.params.get("contact_person")

try:
with contextlib.redirect_stdout(output_buffer):
resp = fw_obj.update(xml_tag="SNMPAgentConfiguration", update_params=update_params, debug=True)
except SophosFirewallAuthFailure as error:
module.fail_json(msg="Authentication error: {0}".format(error), **result)
except SophosFirewallAPIError as error:
module.fail_json(
msg="API Error: {0},{1}".format(error, output_buffer.getvalue()), **result
)
except RequestException as error:
module.fail_json(msg="Error communicating to API: {0}".format(error), **result)
return resp


def eval_changed(module, exist_settings):
"""Evaluate the provided arguments against existing settings.
Args:
module (AnsibleModule): AnsibleModule object
exist_settings (dict): Response from the call to get_admin_settings()
Returns:
bool: Return true if any settings are different, otherwise return false
"""
exist_settings = exist_settings["api_response"]["Response"]["SNMPAgentConfiguration"]

if module.params.get("enabled"):
status = "Enable"
else:
status = "Disable"

if not status == exist_settings["Configuration"] or (
module.params.get("location") and not module.params.get("location") == exist_settings["Location"] or
module.params.get("name") and not module.params.get("name") == exist_settings["Name"] or
module.params.get("description") and not module.params.get("description") == exist_settings["Description"] or
module.params.get("contact_person") and not module.params.get("contact_person") == exist_settings["ContactPerson"]
):
return True

return False


def main():
"""Code executed at run time."""
argument_spec = {
"username": {"required": True},
"password": {"required": True, "no_log": True},
"hostname": {"required": True},
"port": {"type": "int", "default": 4444},
"verify": {"type": "bool", "default": True},
"enabled": {"type": "bool", "required": False},
"name": {"type": "str", "required": False},
"description": {"type": "str", "required": False},
"location": {"type": "str", "required": False},
"contact_person": {"type": "str", "required": False},
"state": {"type": "str", "required": True, "choices": ["updated", "query"]},
}

required_if = [
(
"enabled",
True,
[
"name",
"location",
"contact_person"
],
False,
),
]

module = AnsibleModule(
argument_spec=argument_spec, required_if=required_if, supports_check_mode=True
)

if not PREREQ_MET["result"]:
module.fail_json(msg=missing_required_lib(PREREQ_MET["missing_module"]))

fw = SophosFirewall(
username=module.params.get("username"),
password=module.params.get("password"),
hostname=module.params.get("hostname"),
port=module.params.get("port"),
verify=module.params.get("verify"),
)

result = {"changed": False, "check_mode": False}

state = module.params.get("state")

exist_settings = get_snmp_agent(fw, module, result)
result["api_response"] = exist_settings["api_response"]

if state == "query":
module.exit_json(**result)

if module.check_mode:
result["check_mode"] = True
module.exit_json(**result)

elif state == "updated":
if eval_changed(module, exist_settings):
api_response = update_snmp_agent(fw, module, result)

if api_response:
result["api_response"] = api_response
if (
api_response["Response"]["SNMPAgentConfiguration"]["Status"]["#text"]
== "Configuration applied successfully."
):
result["changed"] = True

module.exit_json(**result)


if __name__ == "__main__":
main()
Loading

0 comments on commit 8ff3b8a

Please sign in to comment.