Init: mediaserver

This commit is contained in:
2023-02-08 12:13:28 +01:00
parent 848bc9739c
commit f7c23d4ba9
31914 changed files with 6175775 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
#!/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: deploy
short_description: Trigger a qradar configuration deployment
description:
- This module allows for INCREMENTAL or FULL deployments
version_added: "1.0.0"
options:
type:
description:
- Type of deployment
required: false
type: str
choices:
- "INCREMENTAL"
- "FULL"
default: "INCREMENTAL"
notes:
- This module does not support check mode because the QRadar REST API does not offer stateful inspection of configuration deployments
author: "Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>"
"""
EXAMPLES = """
- name: run an incremental deploy
ibm.qradar.deploy:
type: INCREMENTAL
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
def main():
argspec = dict(
type=dict(
choices=["INCREMENTAL", "FULL"],
required=False,
default="INCREMENTAL",
)
)
module = AnsibleModule(argument_spec=argspec, supports_check_mode=False)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["state", "type_name", "identifier"],
)
qradar_return_data = qradar_request.post_by_path(
"api/staged_config/deploy_status"
)
if "message" in qradar_return_data and (
to_text("No changes to deploy")
in to_text(qradar_return_data["message"])
):
module.exit_json(
msg="No changes to deploy",
qradar_return_data=qradar_return_data,
changed=False,
)
else:
module.exit_json(
msg="Successfully initiated {0} deployment.".format(
module.params["type"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,263 @@
#!/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: log_source_management
short_description: Manage Log Sources in QRadar
description:
- This module allows for addition, deletion, or modification of Log Sources in QRadar
version_added: "1.0.0"
deprecated:
alternative: qradar_log_sources_management
why: Newer and updated modules released with more functionality.
removed_at_date: '2024-09-01'
options:
name:
description:
- Name of Log Source
required: true
type: str
state:
description:
- Add or remove a log source.
required: true
choices: [ "present", "absent" ]
type: str
type_name:
description:
- Type of resource by name
required: false
type: str
type_id:
description:
- Type of resource by id, as defined in QRadar Log Source Types Documentation
required: false
type: int
protocol_type_id:
description:
- Type of protocol by id, as defined in QRadar Log Source Types Documentation
required: false
type: int
identifier:
description:
- Log Source Identifier (Typically IP Address or Hostname of log source)
required: true
type: str
description:
description:
- Description of log source
required: true
type: str
notes:
- Either C(type) or C(type_id) is required
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
"""
EXAMPLES = """
- name: Add a snort log source to IBM QRadar
ibm.qradar.log_source_management:
name: "Snort logs"
type_name: "Snort Open Source IDS"
state: present
description: "Snort IDS remote logs from rsyslog"
identifier: "192.168.1.101"
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
find_dict_in_list,
)
import json
def set_log_source_values(module, qradar_request):
if module.params["type_name"]:
code, query_response = qradar_request.get(
"/api/config/event_sources/log_source_management/log_source_types?filter={0}".format(
quote('name="{0}"'.format(module.params["type_name"]))
)
)
log_source_type_found = query_response[0]
if module.params["type_id"]:
code, query_response = qradar_request.get(
"/api/config/event_sources/log_source_management/log_source_types?filter={0}".format(
quote('name="{0}"'.format(module.params["type_name"]))
)
)
code, log_source_type_found = query_response[0]
if log_source_type_found:
if not module.params["type_id"]:
module.params["type_id"] = log_source_type_found["id"]
else:
module.fail_json(
msg="Incompatible type provided, please consult QRadar Documentation for Log Source Types"
)
if module.params["protocol_type_id"]:
found_dict_in_list, _fdil_index = find_dict_in_list(
log_source_type_found["protocol_types"],
"protocol_id",
module.params["protocol_type_id"],
)
if not found_dict_in_list:
module.fail_json(
msg="Incompatible protocol_type_id provided, please consult QRadar Documentation for Log Source Types"
)
else:
# Set it to the default as provided by the QRadar Instance
module.params["protocol_type_id"] = log_source_type_found[
"protocol_types"
][0]["protocol_id"]
module.params["protocol_parameters"] = [
{
"id": module.params["protocol_type_id"],
"name": "identifier",
"value": module.params["identifier"],
}
]
def main():
argspec = dict(
name=dict(required=True, type="str"),
state=dict(choices=["present", "absent"], required=True),
type_name=dict(required=False, type="str"),
type_id=dict(required=False, type="int"),
identifier=dict(required=True, type="str"),
protocol_type_id=dict(required=False, type="int"),
description=dict(required=True, type="str"),
)
module = AnsibleModule(
argument_spec=argspec,
required_one_of=[("type_name", "type_id")],
mutually_exclusive=[("type_name", "type_id")],
supports_check_mode=True,
)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["state", "type_name", "identifier"],
)
code, log_source_exists = qradar_request.get(
"/api/config/event_sources/log_source_management/log_sources?filter={0}".format(
quote('name="{0}"'.format(module.params["name"]))
)
)
if log_source_exists:
if module.params["state"] == "present":
(
existing_log_source_protocol_identifier,
_elspi_index,
) = find_dict_in_list(
log_source_exists[0]["protocol_parameters"],
"name",
"identifier",
)
set_log_source_values(module, qradar_request)
comparison_map = [
existing_log_source_protocol_identifier["value"]
== module.params["identifier"],
log_source_exists[0]["name"] == module.params["name"],
log_source_exists[0]["type_id"] == module.params["type_id"],
to_text(log_source_exists[0]["description"])
== to_text(module.params["description"]),
]
if all(comparison_map):
module.exit_json(changed=False, msg="Nothing to do.")
else:
log_source_exists[0]["protocol_parameters"][
_elspi_index
] = module.params["protocol_parameters"][0]
log_source_exists[0]["name"] = module.params["name"]
log_source_exists[0]["type_id"] = module.params["type_id"]
log_source_exists[0]["description"] = module.params[
"description"
]
if module.check_mode:
qradar_return_data = {
"EMPTY": "IN CHECK MODE, NO TRANSACTION TOOK PLACE"
}
else:
code, qradar_return_data = qradar_request.create_update(
"api/config/event_sources/log_source_management/log_sources",
data=json.dumps(log_source_exists),
)
module.exit_json(
msg="Successfully updated log source: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["state"] == "absent":
if module.check_mode:
qradar_return_data = {
"EMPTY": "IN CHECK MODE, NO TRANSACTION TOOK PLACE"
}
else:
code, qradar_return_data = qradar_request.delete(
"/api/config/event_sources/log_source_management/log_sources/{0}".format(
log_source_exists[0]["id"]
)
)
module.exit_json(
msg="Successfully deleted log source: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
if module.params["state"] == "present":
set_log_source_values(module, qradar_request)
if module.check_mode:
qradar_return_data = {
"EMPTY": "IN CHECK MODE, NO TRANSACTION TOOK PLACE"
}
else:
code, qradar_return_data = qradar_request.create_update(
"api/config/event_sources/log_source_management/log_sources",
data=json.dumps([qradar_request.get_data()]),
)
module.exit_json(
msg="Successfully created log source: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["state"] == "absent":
module.exit_json(changed=False, msg="Nothing to do.")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
#!/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_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
set_offense_values,
)
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']))
code, 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()

View File

@@ -0,0 +1,216 @@
#!/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_info
short_description: Obtain information about one or many QRadar Offenses, with filter options
description:
- This module allows to obtain information about one or many QRadar Offenses, with filter options
version_added: "1.0.0"
options:
id:
description:
- Obtain only information of the Offense with provided ID
required: false
type: int
name:
description:
- Obtain only information of the Offense that matches the provided name
required: false
type: str
status:
description:
- Obtain only information of Offenses of a certain status
required: false
choices: [ "open", "OPEN", "hidden", "HIDDEN", "closed", "CLOSED" ]
default: "open"
type: str
assigned_to:
description:
- Obtain only information of Offenses assigned to a certain user
required: false
type: str
closing_reason:
description:
- Obtain only information of Offenses that were closed by a specific closing reason
required: false
type: str
closing_reason_id:
description:
- Obtain only information of Offenses that were closed by a specific closing reason ID
required: false
type: int
follow_up:
description:
- Obtain only information of Offenses that are marked with the follow up flag
required: false
type: bool
protected:
description:
- Obtain only information of Offenses that are protected
required: false
type: bool
notes:
- You may provide many filters and they will all be applied, except for C(id)
as that will return only
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
"""
# FIXME - provide correct example here
RETURN = """
offenses:
description: Information
returned: always
type: list
elements: dict
contains:
qradar_offenses:
description: IBM QRadar Offenses found based on provided filters
returned: always
type: complex
contains:
source:
description: Init system of the service. One of C(systemd), C(sysv), C(upstart).
returned: always
type: str
sample: sysv
state:
description: State of the service. Either C(running), C(stopped), or C(unknown).
returned: always
type: str
sample: running
status:
description: State of the service. Either C(enabled), C(disabled), or C(unknown).
returned: systemd systems or RedHat/SUSE flavored sysvinit/upstart
type: str
sample: enabled
name:
description: Name of the service.
returned: always
type: str
sample: arp-ethers.service
"""
EXAMPLES = """
- name: Get list of all currently OPEN IBM QRadar Offenses
ibm.qradar.offense_info:
status: OPEN
register: offense_list
- name: display offense information for debug purposes
debug:
var: offense_list
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
find_dict_in_list,
set_offense_values,
)
def main():
argspec = dict(
id=dict(required=False, type="int"),
name=dict(required=False, type="str"),
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", default=None),
protected=dict(required=False, type="bool", default=None),
status=dict(
required=False,
choices=["open", "OPEN", "hidden", "HIDDEN", "closed", "CLOSED"],
default="open",
type="str",
),
)
module = AnsibleModule(
argument_spec=argspec,
mutually_exclusive=[("closing_reason", "closing_reason_id")],
supports_check_mode=True,
)
qradar_request = QRadarRequest(module)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME NATIVELY VIA REST API (DOESN'T EXIST YET)
# found_offense = qradar_request.get('/api/siem/offenses?filter={0}'.format(module.params['name']))
set_offense_values(module, qradar_request)
if module.params["id"]:
code, offenses = qradar_request.get(
"/api/siem/offenses/{0}".format(module.params["id"])
)
else:
query_strs = []
if module.params["status"]:
query_strs.append(
quote("status={0}".format(to_text(module.params["status"])))
)
if module.params["assigned_to"]:
query_strs.append(
quote("assigned_to={0}".format(module.params["assigned_to"]))
)
if module.params["closing_reason_id"]:
query_strs.append(
quote(
"closing_reason_id={0}".format(
module.params["closing_reason_id"]
)
)
)
if module.params["follow_up"] is not None:
query_strs.append(
quote("follow_up={0}".format(module.params["follow_up"]))
)
if module.params["protected"] is not None:
query_strs.append(
quote("protected={0}".format(module.params["protected"]))
)
if query_strs:
code, offenses = qradar_request.get(
"/api/siem/offenses?filter={0}".format("&".join(query_strs))
)
else:
code, offenses = qradar_request.get("/api/siem/offenses")
if module.params["name"]:
named_offense = find_dict_in_list(
offenses, "description", module.params["name"]
)
if named_offense:
offenses = named_offense
else:
offenses = []
module.exit_json(offenses=offenses, changed=False)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,189 @@
#!/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_note
short_description: Create or update a QRadar Offense Note
description:
- This module allows to create a QRadar Offense note
version_added: "1.0.0"
options:
id:
description:
- Offense ID to operate on
required: true
type: int
note_text:
description: The note's text contents
required: true
type: str
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
# offense_name:
# description:
# - Name of Offense
# required: true
# type: str
# FIXME - WOULD LIKE TO MANAGE STATE
# state:
# description: Define state of the note: present or absent
# required: false
# choices: ["present", "absent"]
# default: "present"
"""
EXAMPLES = """
- name: Add a note to QRadar Offense ID 1
ibm.qradar.offense_note:
id: 1
note_text: This an example note entry that should be made on offense id 1
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
def set_offense_values(module, qradar_request):
if module.params["closing_reason"]:
code, found_closing_reason = qradar_request.get(
"/api/siem/offense_closing_reasons?filter={0}".format(
quote('text="{0}"'.format(module.params["closing_reason"]))
)
)
if found_closing_reason:
module.params["closing_reason_id"] = found_closing_reason[0]["id"]
else:
module.fail_json(
"Unable to find closing_reason text: {0}".format(
module.params["closing_reason"]
)
)
if module.params["status"]:
module.params["status"] = module.params["status"].upper()
def main():
argspec = dict(
# state=dict(required=False, choices=["present", "absent"], type='str', default="present"),
id=dict(required=True, type="int"),
note_text=dict(required=True, type="str"),
)
module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["state", "id"],
)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME
# found_offense = qradar_request.get('/api/siem/offenses?filter={0}'.format(module.params['name']))
# FIXME - once this is sorted, add it to module_utils
code, found_notes = qradar_request.get(
"/api/siem/offenses/{0}/notes?filter={1}".format(
module.params["id"],
quote('note_text="{0}"'.format(module.params["note_text"])),
)
)
# if module.params['state'] == 'present':
if found_notes:
# The note we want exists either by ID or by text name, verify
note = found_notes[0]
if note["note_text"] == module.params["note_text"]:
module.exit_json(
msg="No changes necessary. Nothing to do.", changed=False
)
else:
if module.check_mode:
module.exit_json(
msg="A change would have occured but did not because Check Mode",
changed=True,
)
qradar_return_data = qradar_request.post_by_path(
"api/siem/offenses/{0}/notes?note_text={1}".format(
module.params["id"],
quote("{0}".format(module.params["note_text"])),
),
data=False,
)
module.exit_json(
msg="Successfully created Offense Note ID: {0}".format(
qradar_return_data["id"]
),
qradar_return_data=qradar_return_data,
changed=False,
)
else:
if module.check_mode:
module.exit_json(
msg="A change would have occured but did not because Check Mode",
changed=True,
)
qradar_return_data = qradar_request.post_by_path(
"api/siem/offenses/{0}/notes?note_text={1}".format(
module.params["id"],
quote("{0}".format(module.params["note_text"])),
),
data=False,
)
module.exit_json(
msg="Successfully created Offense Note ID: {0}".format(
qradar_return_data["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
module.exit_json(msg="No changes necessary. Nothing to do.", changed=False)
# FIXME FIXME FIXME - can we actually delete these via the REST API?
# if module.params['state'] == 'absent':
# if not found_notes:
# module.exit_json(msg="No changes necessary. Nothing to do.", changed=False)
# else:
# if module.check_mode:
# module.exit_json(msg="A change would have occured but did not because Check Mode", changed=True)
# # FIXME: fix the POST here to actually delete
# qradar_return_data = qradar_request.post_by_path(
# 'api/siem/offenses/{0}/notes?note_text={1}'.format(
# module.params['id'],
# quote("{0}".format(module.params['note_text'])),
# ),
# data=False
# )
# module.exit_json(
# msg="Successfully created Offense Note ID: {0}".format(qradar_return_data['id']),
# qradar_return_data=qradar_return_data,
# changed=True
# )
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,279 @@
#!/usr/bin/python
# Copyright: Ansible Project
# 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: qradar_analytics_rules
short_description: Qradar Analytics Rules Management resource module
description:
- This module allows for modification, deletion, and checking of Analytics Rules in QRadar
version_added: "2.1.0"
options:
config:
description: A dictionary of Qradar Analytics Rules options
type: dict
suboptions:
id:
description: The sequence ID of the rule.
type: int
name:
description: The name of the rule.
type: str
enabled:
description: Check if the rule is enabled
type: bool
owner:
description: Manage ownership of a QRadar Rule
type: str
fields:
description:
- List of params filtered from the Rule config
- NOTE, this param is valid only via state GATHERED.
type: list
elements: str
choices:
- average_capacity
- base_capacity
- base_host_id
- capacity_timestamp
- creation_date
- enabled
- id
- identifier
- linked_rule_identifier
- modification_date
- name
- origin
- owner
- type
range:
description:
- Parameter to restrict the number of elements that
are returned in the list to a specified range.
- NOTE, this param is valid only via state GATHERED.
type: str
state:
description:
- The state the configuration should be left in
- The state I(gathered) will get the module API configuration from the device
and transform it into structured data in the format as per the module argspec
and the value is returned in the I(gathered) key within the result.
type: str
choices:
- merged
- gathered
- deleted
author: Ansible Security Automation Team (@justjais) <https://github.com/ansible-security>
"""
EXAMPLES = """
# Using MERGED state
# -------------------
- name: DISABLE Rule 'Ansible Example DDoS Rule'
ibm.qradar.qradar_analytics_rules:
config:
name: 'Ansible Example DDOS Rule'
enabled: false
state: merged
# RUN output:
# -----------
# qradar_analytics_rules:
# after:
# average_capacity: null
# base_capacity: null
# base_host_id: null
# capacity_timestamp: null
# creation_date: 1658929682568
# enabled: false
# id: 100443
# identifier: ae5a1268-02a0-4976-84c5-dbcbcf854b9c
# linked_rule_identifier: null
# modification_date: 1658929682567
# name: Ansible Example DDOS Rule
# origin: USER
# owner: admin
# type: EVENT
# before:
# average_capacity: null
# base_capacity: null
# base_host_id: null
# capacity_timestamp: null
# creation_date: 1658929682568
# enabled: true
# id: 100443
# identifier: ae5a1268-02a0-4976-84c5-dbcbcf854b9c
# linked_rule_identifier: null
# modification_date: 1658929682567
# name: Ansible Example DDOS Rule
# origin: USER
# owner: admin
# type: EVENT
# Using GATHERED state
# --------------------
- name: Get information about the Rule named "Ansible Example DDOS Rule"
ibm.qradar.qradar_analytics_rules:
config:
name: "Ansible Example DDOS Rule"
state: gathered
# RUN output:
# -----------
# gathered:
# average_capacity: null
# base_capacity: null
# base_host_id: null
# capacity_timestamp: null
# creation_date: 1658918848694
# enabled: true
# id: 100443
# identifier: d6d37942-ba28-438f-b909-120df643a992
# linked_rule_identifier: null
# modification_date: 1658918848692
# name: Ansible Example DDOS Rule
# origin: USER
# owner: admin
# type: EVENT
- name: Get information about the Rule with ID 100443
ibm.qradar.qradar_analytics_rules:
config:
id: 100443
state: gathered
# RUN output:
# -----------
# gathered:
# average_capacity: null
# base_capacity: null
# base_host_id: null
# capacity_timestamp: null
# creation_date: 1658918848694
# enabled: true
# id: 100443
# identifier: d6d37942-ba28-438f-b909-120df643a992
# linked_rule_identifier: null
# modification_date: 1658918848692
# name: Ansible Example DDOS Rule
# origin: USER
# owner: admin
# type: EVENT
- name: TO Get information about the Rule ID with a range
ibm.qradar.qradar_analytics_rules:
config:
range: 100300-100500
fields:
- name
- origin
- owner
state: gathered
# RUN output:
# -----------
# gathered:
# - name: Devices with High Event Rates
# origin: SYSTEM
# owner: admin
# - name: Excessive Database Connections
# origin: SYSTEM
# owner: admin
# - name: 'Anomaly: Excessive Firewall Accepts Across Multiple Hosts'
# origin: SYSTEM
# owner: admin
# - name: Excessive Firewall Denies from Single Source
# origin: SYSTEM
# owner: admin
# - name: 'AssetExclusion: Exclude DNS Name By IP'
# origin: SYSTEM
# owner: admin
# - name: 'AssetExclusion: Exclude DNS Name By MAC Address'
# origin: SYSTEM
# owner: admin
- name: Delete custom Rule by NAME
ibm.qradar.qradar_analytics_rules:
config:
name: 'Ansible Example DDOS Rule'
state: deleted
# RUN output:
# -----------
# qradar_analytics_rules:
# after: {}
# before:
# average_capacity: null
# base_capacity: null
# base_host_id: null
# capacity_timestamp: null
# creation_date: 1658929431239
# enabled: true
# id: 100444
# identifier: 3c2cbd9d-d141-49fc-b5d5-29009a9b5308
# linked_rule_identifier: null
# modification_date: 1658929431238
# name: Ansible Example DDOS Rule
# origin: USER
# owner: admin
# type: EVENT
# Using DELETED state
# -------------------
- name: Delete custom Rule by ID
ibm.qradar.qradar_analytics_rules:
config:
id: 100443
state: deleted
# RUN output:
# -----------
# qradar_analytics_rules:
# after: {}
# before:
# average_capacity: null
# base_capacity: null
# base_host_id: null
# capacity_timestamp: null
# creation_date: 1658929431239
# enabled: true
# id: 100443
# identifier: 3c2cbd9d-d141-49fc-b5d5-29009a9b5308
# linked_rule_identifier: null
# modification_date: 1658929431238
# name: Ansible Example DDOS Rule
# origin: USER
# owner: admin
# type: EVENT
"""
RETURN = """
before:
description: The configuration as structured data prior to module invocation.
returned: always
type: dict
sample: The configuration returned will always be in the same format of the parameters above.
after:
description: The configuration as structured data after module completion.
returned: when changed
type: dict
sample: The configuration returned will always be in the same format of the parameters above.
"""

View File

@@ -0,0 +1,89 @@
#!/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: deploy
short_description: Trigger a qradar configuration deployment
description:
- This module allows for INCREMENTAL or FULL deployments
version_added: "1.0.0"
options:
type:
description:
- Type of deployment
required: false
type: str
choices:
- "INCREMENTAL"
- "FULL"
default: "INCREMENTAL"
notes:
- This module does not support check mode because the QRadar REST API does not offer stateful inspection of configuration deployments
author: "Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>"
"""
EXAMPLES = """
- name: run an incremental deploy
ibm.qradar.deploy:
type: INCREMENTAL
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
def main():
argspec = dict(
type=dict(
choices=["INCREMENTAL", "FULL"],
required=False,
default="INCREMENTAL",
)
)
module = AnsibleModule(argument_spec=argspec, supports_check_mode=False)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["state", "type_name", "identifier"],
)
qradar_return_data = qradar_request.post_by_path(
"api/staged_config/deploy_status"
)
if "message" in qradar_return_data and (
to_text("No changes to deploy")
in to_text(qradar_return_data["message"])
):
module.exit_json(
msg="No changes to deploy",
qradar_return_data=qradar_return_data,
changed=False,
)
else:
module.exit_json(
msg="Successfully initiated {0} deployment.".format(
module.params["type"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,263 @@
#!/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: log_source_management
short_description: Manage Log Sources in QRadar
description:
- This module allows for addition, deletion, or modification of Log Sources in QRadar
version_added: "1.0.0"
deprecated:
alternative: qradar_log_sources_management
why: Newer and updated modules released with more functionality.
removed_at_date: '2024-09-01'
options:
name:
description:
- Name of Log Source
required: true
type: str
state:
description:
- Add or remove a log source.
required: true
choices: [ "present", "absent" ]
type: str
type_name:
description:
- Type of resource by name
required: false
type: str
type_id:
description:
- Type of resource by id, as defined in QRadar Log Source Types Documentation
required: false
type: int
protocol_type_id:
description:
- Type of protocol by id, as defined in QRadar Log Source Types Documentation
required: false
type: int
identifier:
description:
- Log Source Identifier (Typically IP Address or Hostname of log source)
required: true
type: str
description:
description:
- Description of log source
required: true
type: str
notes:
- Either C(type) or C(type_id) is required
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
"""
EXAMPLES = """
- name: Add a snort log source to IBM QRadar
ibm.qradar.log_source_management:
name: "Snort logs"
type_name: "Snort Open Source IDS"
state: present
description: "Snort IDS remote logs from rsyslog"
identifier: "192.168.1.101"
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
find_dict_in_list,
)
import json
def set_log_source_values(module, qradar_request):
if module.params["type_name"]:
code, query_response = qradar_request.get(
"/api/config/event_sources/log_source_management/log_source_types?filter={0}".format(
quote('name="{0}"'.format(module.params["type_name"]))
)
)
log_source_type_found = query_response[0]
if module.params["type_id"]:
code, query_response = qradar_request.get(
"/api/config/event_sources/log_source_management/log_source_types?filter={0}".format(
quote('name="{0}"'.format(module.params["type_name"]))
)
)
code, log_source_type_found = query_response[0]
if log_source_type_found:
if not module.params["type_id"]:
module.params["type_id"] = log_source_type_found["id"]
else:
module.fail_json(
msg="Incompatible type provided, please consult QRadar Documentation for Log Source Types"
)
if module.params["protocol_type_id"]:
found_dict_in_list, _fdil_index = find_dict_in_list(
log_source_type_found["protocol_types"],
"protocol_id",
module.params["protocol_type_id"],
)
if not found_dict_in_list:
module.fail_json(
msg="Incompatible protocol_type_id provided, please consult QRadar Documentation for Log Source Types"
)
else:
# Set it to the default as provided by the QRadar Instance
module.params["protocol_type_id"] = log_source_type_found[
"protocol_types"
][0]["protocol_id"]
module.params["protocol_parameters"] = [
{
"id": module.params["protocol_type_id"],
"name": "identifier",
"value": module.params["identifier"],
}
]
def main():
argspec = dict(
name=dict(required=True, type="str"),
state=dict(choices=["present", "absent"], required=True),
type_name=dict(required=False, type="str"),
type_id=dict(required=False, type="int"),
identifier=dict(required=True, type="str"),
protocol_type_id=dict(required=False, type="int"),
description=dict(required=True, type="str"),
)
module = AnsibleModule(
argument_spec=argspec,
required_one_of=[("type_name", "type_id")],
mutually_exclusive=[("type_name", "type_id")],
supports_check_mode=True,
)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["state", "type_name", "identifier"],
)
code, log_source_exists = qradar_request.get(
"/api/config/event_sources/log_source_management/log_sources?filter={0}".format(
quote('name="{0}"'.format(module.params["name"]))
)
)
if log_source_exists:
if module.params["state"] == "present":
(
existing_log_source_protocol_identifier,
_elspi_index,
) = find_dict_in_list(
log_source_exists[0]["protocol_parameters"],
"name",
"identifier",
)
set_log_source_values(module, qradar_request)
comparison_map = [
existing_log_source_protocol_identifier["value"]
== module.params["identifier"],
log_source_exists[0]["name"] == module.params["name"],
log_source_exists[0]["type_id"] == module.params["type_id"],
to_text(log_source_exists[0]["description"])
== to_text(module.params["description"]),
]
if all(comparison_map):
module.exit_json(changed=False, msg="Nothing to do.")
else:
log_source_exists[0]["protocol_parameters"][
_elspi_index
] = module.params["protocol_parameters"][0]
log_source_exists[0]["name"] = module.params["name"]
log_source_exists[0]["type_id"] = module.params["type_id"]
log_source_exists[0]["description"] = module.params[
"description"
]
if module.check_mode:
qradar_return_data = {
"EMPTY": "IN CHECK MODE, NO TRANSACTION TOOK PLACE"
}
else:
code, qradar_return_data = qradar_request.create_update(
"api/config/event_sources/log_source_management/log_sources",
data=json.dumps(log_source_exists),
)
module.exit_json(
msg="Successfully updated log source: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["state"] == "absent":
if module.check_mode:
qradar_return_data = {
"EMPTY": "IN CHECK MODE, NO TRANSACTION TOOK PLACE"
}
else:
code, qradar_return_data = qradar_request.delete(
"/api/config/event_sources/log_source_management/log_sources/{0}".format(
log_source_exists[0]["id"]
)
)
module.exit_json(
msg="Successfully deleted log source: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
if module.params["state"] == "present":
set_log_source_values(module, qradar_request)
if module.check_mode:
qradar_return_data = {
"EMPTY": "IN CHECK MODE, NO TRANSACTION TOOK PLACE"
}
else:
code, qradar_return_data = qradar_request.create_update(
"api/config/event_sources/log_source_management/log_sources",
data=json.dumps([qradar_request.get_data()]),
)
module.exit_json(
msg="Successfully created log source: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["state"] == "absent":
module.exit_json(changed=False, msg="Nothing to do.")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,522 @@
#!/usr/bin/python
# Copyright: Ansible Project
# 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: qradar_log_sources_management
short_description: Qradar Log Sources Management resource module
description:
- This module allows for addition, deletion, or modification of Log Sources in QRadar
version_added: "2.1.0"
options:
config:
description: A dictionary of Qradar Log Sources options
type: list
elements: dict
suboptions:
name:
description:
- Name of Log Source
type: str
description:
description:
- Description of log source
type: str
type_name:
description:
- Type of resource by name
type: str
type_id:
description:
- The type of the log source. Must correspond to an existing log source type.
type: int
identifier:
description:
- Log Source Identifier (Typically IP Address or Hostname of log source)
type: str
protocol_type_id:
description:
- Type of protocol by id, as defined in QRadar Log Source Types Documentation
type: int
enabled:
description:
- If the log source is enabled, the condition is set to 'true'; otherwise,
the condition is set to 'false'.
type: bool
gateway:
description:
- If the log source is configured as a gateway, the condition is set to 'true';
otherwise, the condition is set to 'false'. A gateway log source is a stand-alone
protocol configuration. The log source receives no events itself, and serves as a
host for a protocol configuration that retrieves event data to feed other log sources.
It acts as a "gateway" for events from multiple systems to enter the event pipeline.
type: bool
internal:
description:
- If the log source is internal (when the log source type is defined as internal),
the condition is set to 'true'.
type: bool
target_event_collector_id:
description:
- The ID of the event collector where the log source sends its data.
The ID must correspond to an existing event collector.
type: int
coalesce_events:
description:
- If events collected by this log source are coalesced based on common properties,
the condition is set to 'true'. If each individual event is stored,
then the condition is set to 'false'.
type: bool
store_event_payload:
description:
- If the payloads of events that are collected by this log source are stored,
the condition is set to 'true'. If only the normalized event records are stored,
then the condition is set to 'false'.
type: bool
language_id:
description:
- The language of the events that are being processed by this log source.
Must correspond to an existing log source language. Individual log source types
can support only a subset of all available log source languages,
as indicated by the supported_language_ids field of the log source type structure
type: int
group_ids:
description:
- The set of log source group IDs this log source is a member of.
Each ID must correspond to an existing log source group.
type: list
elements: str
requires_deploy:
description:
- Set to 'true' if you need to deploy changes to enable the log source for use;
otherwise, set to 'false' if the log source is already active.
type: bool
status:
description:
- The status of the log source.
type: dict
suboptions:
last_updated:
description: last_updated
type: int
messages:
description: last_updated
type: str
status:
description: last_updated
type: str
average_eps:
description:
- The average events per second (EPS) rate of the log source over the last 60 seconds.
type: int
protocol_parameters:
description:
- The set of protocol parameters
- If not provided module will set the protocol parameters by itself
- Note, parameter will come to use mostly in case when facts are gathered and fired
with some modifications to params or in case of round trip scenarios.
type: list
elements: dict
suboptions:
id:
description: The ID of the protocol type.
type: int
name:
description: The unique name of the protocol type.
type: str
value:
description: The allowed protocol value.
type: str
state:
description:
- The state the configuration should be left in
- The state I(gathered) will get the module API configuration from the device
and transform it into structured data in the format as per the module argspec
and the value is returned in the I(gathered) key within the result.
type: str
choices:
- merged
- replaced
- gathered
- deleted
author: Ansible Security Automation Team (@justjais) <https://github.com/ansible-security>
"""
EXAMPLES = """
# Using MERGED state
# -------------------
- name: Add Snort n Apache log sources to IBM QRadar
ibm.qradar.qradar_log_sources_management:
config:
- name: "Snort logs"
type_name: "Snort Open Source IDS"
description: "Snort IDS remote logs from rsyslog"
identifier: "192.0.2.1"
- name: "Apache HTTP Server logs"
type_name: "Apache HTTP Server"
description: "Apache HTTP Server remote logs from rsyslog"
identifier: "198.51.100.1"
state: merged
# RUN output:
# -----------
# qradar_log_sources_management:
# after:
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727311444
# credibility: 5
# description: Snort IDS remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 181
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654727311444
# name: Snort logs
# protocol_parameters:
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# - id: 0
# name: identifier
# value: 192.0.2.1
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 2
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727311462
# credibility: 5
# description: Apache HTTP Server remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 182
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654727311462
# name: Apache HTTP Server logs
# protocol_parameters:
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# - id: 0
# name: identifier
# value: 198.51.100.1
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 10
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
# before: []
# Using REPLACED state
# --------------------
- name: Replace existing Log sources to IBM QRadar
ibm.qradar.qradar_log_sources_management:
state: replaced
config:
- name: "Apache HTTP Server logs"
type_name: "Apache HTTP Server"
description: "REPLACED Apache HTTP Server remote logs from rsyslog"
identifier: "192.0.2.1"
# RUN output:
# -----------
# qradar_log_sources_management:
# after:
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727944017
# credibility: 5
# description: REPLACED Apache HTTP Server remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 183
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654727944017
# name: Apache HTTP Server logs
# protocol_parameters:
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# - id: 0
# name: identifier
# value: 192.0.2.1
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 10
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
# before:
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727311462
# credibility: 5
# description: Apache HTTP Server remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 182
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654727311462
# name: Apache HTTP Server logs
# protocol_parameters:
# - name: identifier
# value: 198.51.100.1
# - name: incomingPayloadEncoding
# value: UTF-8
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 10
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
# Using GATHERED state
# --------------------
- name: Gather Snort n Apache log source from IBM QRadar
ibm.qradar.qradar_log_sources_management:
config:
- name: "Snort logs"
- name: "Apache HTTP Server logs"
state: gathered
# RUN output:
# -----------
# gathered:
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727311444
# credibility: 5
# description: Snort IDS remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 181
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654728103340
# name: Snort logs
# protocol_parameters:
# - id: 0
# name: identifier
# value: 192.0.2.1
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 2
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727944017
# credibility: 5
# description: Apache HTTP Server remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 183
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654728103353
# name: Apache HTTP Server logs
# protocol_parameters:
# - id: 0
# name: identifier
# value: 192.0.2.1
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 10
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
- name: TO Gather ALL log sources from IBM QRadar
tags: gather_log_all
ibm.qradar.qradar_log_sources_management:
state: gathered
# Using DELETED state
# -------------------
- name: Delete Snort n Apache log source from IBM QRadar
ibm.qradar.qradar_log_sources_management:
config:
- name: "Snort logs"
- name: "Apache HTTP Server logs"
state: deleted
# RUN output:
# -----------
# qradar_log_sources_management:
# after: []
# before:
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727311444
# credibility: 5
# description: Snort IDS remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 181
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654728103340
# name: Snort logs
# protocol_parameters:
# - id: 0
# name: identifier
# value: 192.0.2.1
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 2
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
# - auto_discovered: false
# average_eps: 0
# coalesce_events: true
# creation_date: 1654727944017
# credibility: 5
# description: Apache HTTP Server remote logs from rsyslog
# enabled: true
# gateway: false
# group_ids:
# - 0
# id: 183
# internal: false
# language_id: 1
# last_event_time: 0
# log_source_extension_id: null
# modified_date: 1654728103353
# name: Apache HTTP Server logs
# protocol_parameters:
# - id: 0
# name: identifier
# value: 192.0.2.1
# - id: 1
# name: incomingPayloadEncoding
# value: UTF-8
# protocol_type_id: 0
# requires_deploy: true
# status:
# last_updated: 0
# messages: null
# status: NA
# store_event_payload: true
# target_event_collector_id: 7
# type_id: 10
# wincollect_external_destination_ids: null
# wincollect_internal_destination_id: null
"""
RETURN = """
before:
description: The configuration as structured data prior to module invocation.
returned: always
type: list
sample: The configuration returned will always be in the same format of the parameters above.
after:
description: The configuration as structured data after module completion.
returned: when changed
type: list
sample: The configuration returned will always be in the same format of the parameters above.
"""

View File

@@ -0,0 +1,201 @@
#!/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_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
set_offense_values,
)
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']))
code, 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()

View File

@@ -0,0 +1,216 @@
#!/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_info
short_description: Obtain information about one or many QRadar Offenses, with filter options
description:
- This module allows to obtain information about one or many QRadar Offenses, with filter options
version_added: "1.0.0"
options:
id:
description:
- Obtain only information of the Offense with provided ID
required: false
type: int
name:
description:
- Obtain only information of the Offense that matches the provided name
required: false
type: str
status:
description:
- Obtain only information of Offenses of a certain status
required: false
choices: [ "open", "OPEN", "hidden", "HIDDEN", "closed", "CLOSED" ]
default: "open"
type: str
assigned_to:
description:
- Obtain only information of Offenses assigned to a certain user
required: false
type: str
closing_reason:
description:
- Obtain only information of Offenses that were closed by a specific closing reason
required: false
type: str
closing_reason_id:
description:
- Obtain only information of Offenses that were closed by a specific closing reason ID
required: false
type: int
follow_up:
description:
- Obtain only information of Offenses that are marked with the follow up flag
required: false
type: bool
protected:
description:
- Obtain only information of Offenses that are protected
required: false
type: bool
notes:
- You may provide many filters and they will all be applied, except for C(id)
as that will return only
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
"""
# FIXME - provide correct example here
RETURN = """
offenses:
description: Information
returned: always
type: list
elements: dict
contains:
qradar_offenses:
description: IBM QRadar Offenses found based on provided filters
returned: always
type: complex
contains:
source:
description: Init system of the service. One of C(systemd), C(sysv), C(upstart).
returned: always
type: str
sample: sysv
state:
description: State of the service. Either C(running), C(stopped), or C(unknown).
returned: always
type: str
sample: running
status:
description: State of the service. Either C(enabled), C(disabled), or C(unknown).
returned: systemd systems or RedHat/SUSE flavored sysvinit/upstart
type: str
sample: enabled
name:
description: Name of the service.
returned: always
type: str
sample: arp-ethers.service
"""
EXAMPLES = """
- name: Get list of all currently OPEN IBM QRadar Offenses
ibm.qradar.offense_info:
status: OPEN
register: offense_list
- name: display offense information for debug purposes
debug:
var: offense_list
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
find_dict_in_list,
set_offense_values,
)
def main():
argspec = dict(
id=dict(required=False, type="int"),
name=dict(required=False, type="str"),
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", default=None),
protected=dict(required=False, type="bool", default=None),
status=dict(
required=False,
choices=["open", "OPEN", "hidden", "HIDDEN", "closed", "CLOSED"],
default="open",
type="str",
),
)
module = AnsibleModule(
argument_spec=argspec,
mutually_exclusive=[("closing_reason", "closing_reason_id")],
supports_check_mode=True,
)
qradar_request = QRadarRequest(module)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME NATIVELY VIA REST API (DOESN'T EXIST YET)
# found_offense = qradar_request.get('/api/siem/offenses?filter={0}'.format(module.params['name']))
set_offense_values(module, qradar_request)
if module.params["id"]:
code, offenses = qradar_request.get(
"/api/siem/offenses/{0}".format(module.params["id"])
)
else:
query_strs = []
if module.params["status"]:
query_strs.append(
quote("status={0}".format(to_text(module.params["status"])))
)
if module.params["assigned_to"]:
query_strs.append(
quote("assigned_to={0}".format(module.params["assigned_to"]))
)
if module.params["closing_reason_id"]:
query_strs.append(
quote(
"closing_reason_id={0}".format(
module.params["closing_reason_id"]
)
)
)
if module.params["follow_up"] is not None:
query_strs.append(
quote("follow_up={0}".format(module.params["follow_up"]))
)
if module.params["protected"] is not None:
query_strs.append(
quote("protected={0}".format(module.params["protected"]))
)
if query_strs:
code, offenses = qradar_request.get(
"/api/siem/offenses?filter={0}".format("&".join(query_strs))
)
else:
code, offenses = qradar_request.get("/api/siem/offenses")
if module.params["name"]:
named_offense = find_dict_in_list(
offenses, "description", module.params["name"]
)
if named_offense:
offenses = named_offense
else:
offenses = []
module.exit_json(offenses=offenses, changed=False)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,189 @@
#!/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_note
short_description: Create or update a QRadar Offense Note
description:
- This module allows to create a QRadar Offense note
version_added: "1.0.0"
options:
id:
description:
- Offense ID to operate on
required: true
type: int
note_text:
description: The note's text contents
required: true
type: str
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
# offense_name:
# description:
# - Name of Offense
# required: true
# type: str
# FIXME - WOULD LIKE TO MANAGE STATE
# state:
# description: Define state of the note: present or absent
# required: false
# choices: ["present", "absent"]
# default: "present"
"""
EXAMPLES = """
- name: Add a note to QRadar Offense ID 1
ibm.qradar.offense_note:
id: 1
note_text: This an example note entry that should be made on offense id 1
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
def set_offense_values(module, qradar_request):
if module.params["closing_reason"]:
code, found_closing_reason = qradar_request.get(
"/api/siem/offense_closing_reasons?filter={0}".format(
quote('text="{0}"'.format(module.params["closing_reason"]))
)
)
if found_closing_reason:
module.params["closing_reason_id"] = found_closing_reason[0]["id"]
else:
module.fail_json(
"Unable to find closing_reason text: {0}".format(
module.params["closing_reason"]
)
)
if module.params["status"]:
module.params["status"] = module.params["status"].upper()
def main():
argspec = dict(
# state=dict(required=False, choices=["present", "absent"], type='str', default="present"),
id=dict(required=True, type="int"),
note_text=dict(required=True, type="str"),
)
module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["state", "id"],
)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME
# found_offense = qradar_request.get('/api/siem/offenses?filter={0}'.format(module.params['name']))
# FIXME - once this is sorted, add it to module_utils
code, found_notes = qradar_request.get(
"/api/siem/offenses/{0}/notes?filter={1}".format(
module.params["id"],
quote('note_text="{0}"'.format(module.params["note_text"])),
)
)
# if module.params['state'] == 'present':
if found_notes:
# The note we want exists either by ID or by text name, verify
note = found_notes[0]
if note["note_text"] == module.params["note_text"]:
module.exit_json(
msg="No changes necessary. Nothing to do.", changed=False
)
else:
if module.check_mode:
module.exit_json(
msg="A change would have occured but did not because Check Mode",
changed=True,
)
qradar_return_data = qradar_request.post_by_path(
"api/siem/offenses/{0}/notes?note_text={1}".format(
module.params["id"],
quote("{0}".format(module.params["note_text"])),
),
data=False,
)
module.exit_json(
msg="Successfully created Offense Note ID: {0}".format(
qradar_return_data["id"]
),
qradar_return_data=qradar_return_data,
changed=False,
)
else:
if module.check_mode:
module.exit_json(
msg="A change would have occured but did not because Check Mode",
changed=True,
)
qradar_return_data = qradar_request.post_by_path(
"api/siem/offenses/{0}/notes?note_text={1}".format(
module.params["id"],
quote("{0}".format(module.params["note_text"])),
),
data=False,
)
module.exit_json(
msg="Successfully created Offense Note ID: {0}".format(
qradar_return_data["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
module.exit_json(msg="No changes necessary. Nothing to do.", changed=False)
# FIXME FIXME FIXME - can we actually delete these via the REST API?
# if module.params['state'] == 'absent':
# if not found_notes:
# module.exit_json(msg="No changes necessary. Nothing to do.", changed=False)
# else:
# if module.check_mode:
# module.exit_json(msg="A change would have occured but did not because Check Mode", changed=True)
# # FIXME: fix the POST here to actually delete
# qradar_return_data = qradar_request.post_by_path(
# 'api/siem/offenses/{0}/notes?note_text={1}'.format(
# module.params['id'],
# quote("{0}".format(module.params['note_text'])),
# ),
# data=False
# )
# module.exit_json(
# msg="Successfully created Offense Note ID: {0}".format(qradar_return_data['id']),
# qradar_return_data=qradar_return_data,
# changed=True
# )
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,262 @@
#!/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: rule
short_description: Manage state of QRadar Rules, with filter options
description:
- Manage state of QRadar Rules, with filter options
version_added: "1.0.0"
deprecated:
alternative: qradar_analytics_rules
why: Newer and updated modules released with more functionality.
removed_at_date: '2024-09-01'
options:
id:
description:
- Manage state of a QRadar Rule by ID
required: false
type: int
name:
description:
- Manage state of a QRadar Rule by name
required: false
type: str
state:
description:
- Manage state of a QRadar Rule
required: True
choices: [ "enabled", "disabled", "absent" ]
type: str
owner:
description:
- Manage ownership of a QRadar Rule
required: false
type: str
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
"""
# FIXME - provide correct example here
RETURN = """
"""
EXAMPLES = """
- name: Enable Rule 'Ansible Example DDoS Rule'
qradar_rule:
name: 'Ansible Example DDOS Rule'
state: enabled
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
import json
def main():
argspec = dict(
id=dict(required=False, type="int"),
name=dict(required=False, type="str"),
state=dict(
required=True,
choices=["enabled", "disabled", "absent"],
type="str",
),
owner=dict(required=False, type="str"),
)
module = AnsibleModule(
argument_spec=argspec,
supports_check_mode=True,
required_one_of=[("name", "id")],
mutually_exclusive=[("name", "id")],
)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["id", "name", "state", "owner"],
)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME NATIVELY VIA REST API (DOESN'T EXIST YET)
# found_offense = qradar_request.get('/api/analytics/rules?filter={0}'.format(module.params['name']))
module.params["rule"] = {}
if module.params["id"]:
code, module.params["rule"] = qradar_request.get(
"/api/analytics/rules/{0}".format(module.params["id"])
)
elif module.params["name"]:
code, rules = qradar_request.get(
"/api/analytics/rules?filter={0}".format(
quote('"{0}"'.format(module.params["name"]))
)
)
if rules:
module.params["rule"] = rules[0]
module.params["id"] = rules[0]["id"]
if module.params["state"] == "enabled":
if module.params["rule"]:
if module.params["rule"]["enabled"] is True:
# Already enabled
if module.params["id"]:
module.exit_json(
msg="No change needed for rule ID: {0}".format(
module.params["id"]
),
qradar_return_data={},
changed=False,
)
if module.params["name"]:
module.exit_json(
msg="Successfully enabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data={},
changed=False,
)
else:
# Not enabled, enable It
module.params["rule"]["enabled"] = True
qradar_return_data = qradar_request.post_by_path(
"api/analytics/rules/{0}".format(
module.params["rule"]["id"]
),
data=json.dumps(module.params["rule"]),
)
if module.params["id"]:
module.exit_json(
msg="Successfully enabled rule ID: {0}".format(
module.params["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["name"]:
module.exit_json(
msg="Successfully enabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
if module.params["id"]:
module.fail_json(
msg="Unable to find rule ID: {0}".format(
module.params["id"]
)
)
if module.params["name"]:
module.fail_json(
msg='Unable to find rule named: "{0}"'.format(
module.params["name"]
)
)
elif module.params["state"] == "disabled":
if module.params["rule"]:
if module.params["rule"]["enabled"] is False:
# Already disabled
if module.params["id"]:
module.exit_json(
msg="No change needed for rule ID: {0}".format(
module.params["id"]
),
qradar_return_data={},
changed=False,
)
if module.params["name"]:
module.exit_json(
msg="Successfully enabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data={},
changed=False,
)
else:
# Not disabled, disable It
module.params["rule"]["enabled"] = False
qradar_return_data = qradar_request.post_by_path(
"api/analytics/rules/{0}".format(
module.params["rule"]["id"]
),
data=json.dumps(module.params["rule"]),
)
if module.params["id"]:
module.exit_json(
msg="Successfully disabled rule ID: {0}".format(
module.params["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["name"]:
module.exit_json(
msg="Successfully disabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
if module.params["id"]:
module.fail_json(
msg="Unable to find rule ID: {0}".format(
module.params["id"]
)
)
if module.params["name"]:
module.fail_json(
msg='Unable to find rule named: "{0}"'.format(
module.params["name"]
)
)
elif module.params["state"] == "absent":
if module.params["rule"]:
code, qradar_return_data = qradar_request.delete(
"/api/analytics/rules/{0}".format(module.params["rule"]["id"])
)
if module.params["id"]:
module.exit_json(
msg="Successfully deleted rule ID: {0}".format(
module.params["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["name"]:
module.exit_json(
msg="Successfully deleted rule named: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
module.exit_json(msg="Nothing to do, rule not found.")
module.exit_json(rules=rules, changed=False)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,143 @@
#!/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: rule_info
short_description: Obtain information about one or many QRadar Rules, with filter options
description:
- This module obtains information about one or many QRadar Rules, with filter options
version_added: "1.0.0"
deprecated:
alternative: qradar_analytics_rules
why: Newer and updated modules released with more functionality.
removed_at_date: '2024-09-01'
options:
id:
description:
- Obtain only information of the Rule with provided ID
required: false
type: int
name:
description:
- Obtain only information of the Rule that matches the provided name
required: false
type: str
type:
description:
- Obtain only information for the Rules of a certain type
required: false
choices: [ "EVENT", "FLOW", "COMMON", "USER"]
type: str
owner:
description:
- Obtain only information of Rules owned by a certain user
required: false
type: str
origin:
description:
- Obtain only information of Rules that are of a certain origin
required: false
choices: ["SYSTEM", "OVERRIDE", "USER"]
type: str
notes:
- You may provide many filters and they will all be applied, except for C(id)
as that will return only the Rule identified by the unique ID provided.
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>"
"""
# FIXME - provide correct example here
RETURN = """
"""
EXAMPLES = """
- name: Get information about the Rule named "Custom Company DDoS Rule"
ibm.qradar.rule_info:
name: "Custom Company DDoS Rule"
register: custom_ddos_rule_info
- name: debugging output of the custom_ddos_rule_info registered variable
debug:
var: custom_ddos_rule_info
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
def main():
argspec = dict(
id=dict(required=False, type="int"),
name=dict(required=False, type="str"),
owner=dict(required=False, type="str"),
type=dict(
required=False,
choices=["EVENT", "FLOW", "COMMON", "USER"],
type="str",
),
origin=dict(
required=False, choices=["SYSTEM", "OVERRIDE", "USER"], type="str"
),
)
module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)
qradar_request = QRadarRequest(module)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME NATIVELY VIA REST API (DOESN'T EXIST YET)
# found_offense = qradar_request.get('/api/analytics/rules?filter={0}'.format(module.params['name']))
if module.params["id"]:
code, rules = qradar_request.get(
"/api/analytics/rules/{0}".format(module.params["id"])
)
else:
query_strs = []
if module.params["name"]:
query_strs.append(
quote('name="{0}"'.format(to_text(module.params["name"])))
)
if module.params["owner"]:
query_strs.append(
quote("owner={0}".format(module.params["owner"]))
)
if module.params["type"]:
query_strs.append(quote("type={0}".format(module.params["type"])))
if module.params["origin"]:
query_strs.append(
quote("origin={0}".format(module.params["origin"]))
)
if query_strs:
code, rules = qradar_request.get(
"/api/analytics/rules?filter={0}".format("&".join(query_strs))
)
else:
code, rules = qradar_request.get("/api/analytics/rules")
module.exit_json(rules=rules, changed=False)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,262 @@
#!/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: rule
short_description: Manage state of QRadar Rules, with filter options
description:
- Manage state of QRadar Rules, with filter options
version_added: "1.0.0"
deprecated:
alternative: qradar_analytics_rules
why: Newer and updated modules released with more functionality.
removed_at_date: '2024-09-01'
options:
id:
description:
- Manage state of a QRadar Rule by ID
required: false
type: int
name:
description:
- Manage state of a QRadar Rule by name
required: false
type: str
state:
description:
- Manage state of a QRadar Rule
required: True
choices: [ "enabled", "disabled", "absent" ]
type: str
owner:
description:
- Manage ownership of a QRadar Rule
required: false
type: str
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>
"""
# FIXME - provide correct example here
RETURN = """
"""
EXAMPLES = """
- name: Enable Rule 'Ansible Example DDoS Rule'
qradar_rule:
name: 'Ansible Example DDOS Rule'
state: enabled
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
import json
def main():
argspec = dict(
id=dict(required=False, type="int"),
name=dict(required=False, type="str"),
state=dict(
required=True,
choices=["enabled", "disabled", "absent"],
type="str",
),
owner=dict(required=False, type="str"),
)
module = AnsibleModule(
argument_spec=argspec,
supports_check_mode=True,
required_one_of=[("name", "id")],
mutually_exclusive=[("name", "id")],
)
qradar_request = QRadarRequest(
module,
not_rest_data_keys=["id", "name", "state", "owner"],
)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME NATIVELY VIA REST API (DOESN'T EXIST YET)
# found_offense = qradar_request.get('/api/analytics/rules?filter={0}'.format(module.params['name']))
module.params["rule"] = {}
if module.params["id"]:
code, module.params["rule"] = qradar_request.get(
"/api/analytics/rules/{0}".format(module.params["id"])
)
elif module.params["name"]:
code, rules = qradar_request.get(
"/api/analytics/rules?filter={0}".format(
quote('"{0}"'.format(module.params["name"]))
)
)
if rules:
module.params["rule"] = rules[0]
module.params["id"] = rules[0]["id"]
if module.params["state"] == "enabled":
if module.params["rule"]:
if module.params["rule"]["enabled"] is True:
# Already enabled
if module.params["id"]:
module.exit_json(
msg="No change needed for rule ID: {0}".format(
module.params["id"]
),
qradar_return_data={},
changed=False,
)
if module.params["name"]:
module.exit_json(
msg="Successfully enabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data={},
changed=False,
)
else:
# Not enabled, enable It
module.params["rule"]["enabled"] = True
qradar_return_data = qradar_request.post_by_path(
"api/analytics/rules/{0}".format(
module.params["rule"]["id"]
),
data=json.dumps(module.params["rule"]),
)
if module.params["id"]:
module.exit_json(
msg="Successfully enabled rule ID: {0}".format(
module.params["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["name"]:
module.exit_json(
msg="Successfully enabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
if module.params["id"]:
module.fail_json(
msg="Unable to find rule ID: {0}".format(
module.params["id"]
)
)
if module.params["name"]:
module.fail_json(
msg='Unable to find rule named: "{0}"'.format(
module.params["name"]
)
)
elif module.params["state"] == "disabled":
if module.params["rule"]:
if module.params["rule"]["enabled"] is False:
# Already disabled
if module.params["id"]:
module.exit_json(
msg="No change needed for rule ID: {0}".format(
module.params["id"]
),
qradar_return_data={},
changed=False,
)
if module.params["name"]:
module.exit_json(
msg="Successfully enabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data={},
changed=False,
)
else:
# Not disabled, disable It
module.params["rule"]["enabled"] = False
qradar_return_data = qradar_request.post_by_path(
"api/analytics/rules/{0}".format(
module.params["rule"]["id"]
),
data=json.dumps(module.params["rule"]),
)
if module.params["id"]:
module.exit_json(
msg="Successfully disabled rule ID: {0}".format(
module.params["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["name"]:
module.exit_json(
msg="Successfully disabled rule named: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
if module.params["id"]:
module.fail_json(
msg="Unable to find rule ID: {0}".format(
module.params["id"]
)
)
if module.params["name"]:
module.fail_json(
msg='Unable to find rule named: "{0}"'.format(
module.params["name"]
)
)
elif module.params["state"] == "absent":
if module.params["rule"]:
code, qradar_return_data = qradar_request.delete(
"/api/analytics/rules/{0}".format(module.params["rule"]["id"])
)
if module.params["id"]:
module.exit_json(
msg="Successfully deleted rule ID: {0}".format(
module.params["id"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
if module.params["name"]:
module.exit_json(
msg="Successfully deleted rule named: {0}".format(
module.params["name"]
),
qradar_return_data=qradar_return_data,
changed=True,
)
else:
module.exit_json(msg="Nothing to do, rule not found.")
module.exit_json(rules=rules, changed=False)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,143 @@
#!/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: rule_info
short_description: Obtain information about one or many QRadar Rules, with filter options
description:
- This module obtains information about one or many QRadar Rules, with filter options
version_added: "1.0.0"
deprecated:
alternative: qradar_analytics_rules
why: Newer and updated modules released with more functionality.
removed_at_date: '2024-09-01'
options:
id:
description:
- Obtain only information of the Rule with provided ID
required: false
type: int
name:
description:
- Obtain only information of the Rule that matches the provided name
required: false
type: str
type:
description:
- Obtain only information for the Rules of a certain type
required: false
choices: [ "EVENT", "FLOW", "COMMON", "USER"]
type: str
owner:
description:
- Obtain only information of Rules owned by a certain user
required: false
type: str
origin:
description:
- Obtain only information of Rules that are of a certain origin
required: false
choices: ["SYSTEM", "OVERRIDE", "USER"]
type: str
notes:
- You may provide many filters and they will all be applied, except for C(id)
as that will return only the Rule identified by the unique ID provided.
author: Ansible Security Automation Team (@maxamillion) <https://github.com/ansible-security>"
"""
# FIXME - provide correct example here
RETURN = """
"""
EXAMPLES = """
- name: Get information about the Rule named "Custom Company DDoS Rule"
ibm.qradar.rule_info:
name: "Custom Company DDoS Rule"
register: custom_ddos_rule_info
- name: debugging output of the custom_ddos_rule_info registered variable
debug:
var: custom_ddos_rule_info
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.ibm.qradar.plugins.module_utils.qradar import (
QRadarRequest,
)
def main():
argspec = dict(
id=dict(required=False, type="int"),
name=dict(required=False, type="str"),
owner=dict(required=False, type="str"),
type=dict(
required=False,
choices=["EVENT", "FLOW", "COMMON", "USER"],
type="str",
),
origin=dict(
required=False, choices=["SYSTEM", "OVERRIDE", "USER"], type="str"
),
)
module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)
qradar_request = QRadarRequest(module)
# if module.params['name']:
# # FIXME - QUERY HERE BY NAME NATIVELY VIA REST API (DOESN'T EXIST YET)
# found_offense = qradar_request.get('/api/analytics/rules?filter={0}'.format(module.params['name']))
if module.params["id"]:
code, rules = qradar_request.get(
"/api/analytics/rules/{0}".format(module.params["id"])
)
else:
query_strs = []
if module.params["name"]:
query_strs.append(
quote('name="{0}"'.format(to_text(module.params["name"])))
)
if module.params["owner"]:
query_strs.append(
quote("owner={0}".format(module.params["owner"]))
)
if module.params["type"]:
query_strs.append(quote("type={0}".format(module.params["type"])))
if module.params["origin"]:
query_strs.append(
quote("origin={0}".format(module.params["origin"]))
)
if query_strs:
code, rules = qradar_request.get(
"/api/analytics/rules?filter={0}".format("&".join(query_strs))
)
else:
code, rules = qradar_request.get("/api/analytics/rules")
module.exit_json(rules=rules, changed=False)
if __name__ == "__main__":
main()