192 lines
5.8 KiB
Python
192 lines
5.8 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# (c) 2019, Adam Miller (admiller@redhat.com)
|
|
# 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 = """
|
|
---
|
|
module: offense_action
|
|
short_description: Take action on a QRadar Offense
|
|
description:
|
|
- This module allows to assign, protect, follow up, set status, and assign closing reason to QRadar Offenses
|
|
version_added: "1.0.0"
|
|
options:
|
|
id:
|
|
description:
|
|
- ID of Offense
|
|
required: true
|
|
type: int
|
|
status:
|
|
description:
|
|
- One of "open", "hidden" or "closed". (Either all lower case or all caps)
|
|
required: false
|
|
choices: [ "open", "OPEN", "hidden", "HIDDEN", "closed", "CLOSED" ]
|
|
type: str
|
|
assigned_to:
|
|
description:
|
|
- Assign to an user, the QRadar username should be provided
|
|
required: false
|
|
type: str
|
|
closing_reason:
|
|
description:
|
|
- Assign a predefined closing reason here, by name.
|
|
required: false
|
|
type: str
|
|
closing_reason_id:
|
|
description:
|
|
- Assign a predefined closing reason here, by id.
|
|
required: false
|
|
type: int
|
|
follow_up:
|
|
description:
|
|
- Set or unset the flag to follow up on a QRadar Offense
|
|
required: false
|
|
type: bool
|
|
protected:
|
|
description:
|
|
- Set or unset the flag to protect a QRadar Offense
|
|
required: false
|
|
type: bool
|
|
|
|
notes:
|
|
- Requires one of C(name) or C(id) be provided
|
|
- Only one of C(closing_reason) or C(closing_reason_id) can be provided
|
|
|
|
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
|
|
"""
|
|
|
|
"""
|
|
# FIXME - WOULD LIKE TO QUERY BY NAME BUT HOW TO ACCOMPLISH THAT IS NON-OBVIOUS
|
|
# name:
|
|
# description:
|
|
# - Name of Offense
|
|
# required: true
|
|
# type: str
|
|
"""
|
|
|
|
EXAMPLES = """
|
|
"""
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
from ansible.module_utils._text import to_text
|
|
|
|
from ansible.module_utils.urls import Request
|
|
from ansible.module_utils.six.moves.urllib.parse import quote
|
|
from ansible.module_utils.six.moves.urllib.error import HTTPError
|
|
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
|
|
QRadarRequest,
|
|
find_dict_in_list,
|
|
set_offense_values,
|
|
)
|
|
|
|
import copy
|
|
import json
|
|
|
|
|
|
def main():
|
|
|
|
argspec = dict(
|
|
# name=dict(required=False, type='str'),
|
|
# id=dict(required=False, type='str'),
|
|
id=dict(required=True, type="int"),
|
|
assigned_to=dict(required=False, type="str"),
|
|
closing_reason=dict(required=False, type="str"),
|
|
closing_reason_id=dict(required=False, type="int"),
|
|
follow_up=dict(required=False, type="bool"),
|
|
protected=dict(required=False, type="bool"),
|
|
status=dict(
|
|
required=False,
|
|
choices=["open", "OPEN", "hidden", "HIDDEN", "closed", "CLOSED"],
|
|
type="str",
|
|
),
|
|
)
|
|
|
|
module = AnsibleModule(
|
|
argument_spec=argspec,
|
|
# required_one_of=[
|
|
# ('name', 'id',),
|
|
# ],
|
|
mutually_exclusive=[("closing_reason", "closing_reason_id")],
|
|
supports_check_mode=True,
|
|
)
|
|
|
|
qradar_request = QRadarRequest(
|
|
module, not_rest_data_keys=["name", "id", "assigned_to", "closing_reason"],
|
|
)
|
|
|
|
# if module.params['name']:
|
|
# # FIXME - QUERY HERE BY NAME
|
|
# found_offense = qradar_request.get('/api/siem/offenses?filter={0}'.format(module.params['name']))
|
|
|
|
found_offense = qradar_request.get(
|
|
"/api/siem/offenses/{0}".format(module.params["id"])
|
|
)
|
|
|
|
if found_offense:
|
|
set_offense_values(module, qradar_request)
|
|
|
|
post_strs = []
|
|
|
|
if module.params["status"] and (
|
|
to_text(found_offense["status"]) != to_text(module.params["status"])
|
|
):
|
|
post_strs.append("status={0}".format(to_text(module.params["status"])))
|
|
|
|
if module.params["assigned_to"] and (
|
|
to_text(found_offense["assigned_to"])
|
|
!= to_text(module.params["assigned_to"])
|
|
):
|
|
post_strs.append("assigned_to={0}".format(module.params["assigned_to"]))
|
|
|
|
if module.params["closing_reason_id"] and (
|
|
found_offense["closing_reason_id"] != module.params["closing_reason_id"]
|
|
):
|
|
post_strs.append(
|
|
"closing_reason_id={0}".format(module.params["closing_reason_id"])
|
|
)
|
|
|
|
if module.params["follow_up"] and (
|
|
found_offense["follow_up"] != module.params["follow_up"]
|
|
):
|
|
post_strs.append("follow_up={0}".format(module.params["follow_up"]))
|
|
|
|
if module.params["protected"] and (
|
|
found_offense["protected"] != module.params["protected"]
|
|
):
|
|
post_strs.append("protected={0}".format(module.params["protected"]))
|
|
|
|
if post_strs:
|
|
if module.check_mode:
|
|
module.exit_json(
|
|
msg="A change would have been made but was not because of Check Mode.",
|
|
changed=True,
|
|
)
|
|
|
|
qradar_return_data = qradar_request.post_by_path(
|
|
"api/siem/offenses/{0}?{1}".format(
|
|
module.params["id"], "&".join(post_strs)
|
|
)
|
|
)
|
|
# FIXME - handle the scenario in which we can search by name and this isn't a required param anymore
|
|
module.exit_json(
|
|
msg="Successfully updated Offense ID: {0}".format(module.params["id"]),
|
|
qradar_return_data=qradar_return_data,
|
|
changed=True,
|
|
)
|
|
else:
|
|
module.exit_json(msg="No changes necessary. Nothing to do.", changed=False)
|
|
else:
|
|
# FIXME - handle the scenario in which we can search by name and this isn't a required param anymore
|
|
module.fail_json(
|
|
msg="Unable to find Offense ID: {0}".format(module.params["id"])
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|