Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include Syscollector delta delete package operation support for the agent simulator #4842

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deps/wazuh_testing/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
'qa_ctl/provisioning/wazuh_deployment/templates/preloaded_vars.conf.j2',
'data/qactl_conf_validator_schema.json',
'data/all_disabled_ossec.conf',
'data/syscollector_parsed_packages.json',
'tools/migration_tool/delta_schema.json',
'tools/migration_tool/CVE_JSON_5.0_bundled.json'
]
Expand Down
2 changes: 1 addition & 1 deletion deps/wazuh_testing/wazuh_testing/data/syscollector.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"format": "<package_format>",
"groups": "editors",
"install_time": "<timestamp>",
"item_id": "<random_string>",
"item_id": "<package_item_id>",
"location": " ",
"multiarch": "null",
"name": "<package_name>",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
[
{
"vendor": "bsdi",
"product": "bsd_os",
"version": "3.1"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "1.0"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "1.1"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "1.1.5.1"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "1.2"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.0"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.0.1"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.0.5"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.1.5"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.1.6"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.1.6.1"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.1.7"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.1.7.1"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2.2"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2.3"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2.4"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2.5"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2.6"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "2.2.8"
},
{
"vendor": "freebsd",
"product": "freebsd",
"version": "3.0"
},
{
"vendor": "openbsd",
"product": "openbsd",
"version": "2.3"
},
{
"vendor": "openbsd",
"product": "openbsd",
"version": "2.4"
}
]
76 changes: 76 additions & 0 deletions deps/wazuh_testing/wazuh_testing/scripts/parse_packages_content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import argparse
import json
import logging


logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("parse_packages_content.py")


def parse_packages_content(output_file, packages_file, n_packages):
list_packages = []
config = None

with open(packages_file) as f:
for line in f:
if len(list_packages) >= n_packages:
break

if line.strip():
config = json.loads(line)

if 'payload' in config and 'containers' in config['payload'] \
and 'cna' in config['payload']['containers']:
if 'affected' in config['payload']['containers']['cna']:
for affected in config['payload']['containers']['cna']['affected']:
vendor = affected['vendor']
product = affected['product']

for affected_version in affected['versions']:
status, version = affected_version['status'], affected_version['version']

if status == 'affected':
list_packages.append({
'vendor': vendor,
'product': product,
'version': version
})
else:
logger.debug("No affected found in package: %s", config)
else:
logger.warning("No payload found for package: %s", config['id'])
logger.debug("Package: %s", config)

with open(output_file, 'w') as f:
json.dump(list_packages, f, indent=4)


def main():
arg_parser = argparse.ArgumentParser()

arg_parser.add_argument('-p', '--packages', metavar='<packages_file>', type=str, required=True,
help='Packages file', dest='packages_file')

arg_parser.add_argument('-n', '--n_packages', metavar='<n_packages>', type=int, required=True,
help='Number of packages to parse', dest='n_packages')

arg_parser.add_argument('-o', '--output', metavar='<output_file>', type=str, required=True,
help='Output file', dest='output_file')

arg_parser.add_argument('-d', '--debug', action='store_true', help='Enable debug mode', dest='debug')


args = arg_parser.parse_args()

if args.debug:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)

logging.info("Parsing packages content...")
parse_packages_content(args.output_file, args.packages_file, args.n_packages)
logging.info("Packages parsed successfully")


if __name__ == '__main__':
main()
92 changes: 78 additions & 14 deletions deps/wazuh_testing/wazuh_testing/tools/agent_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,15 +775,7 @@ def __init__(self, agent_name, event_types_list, old_format, batch_size, syscoll
}
self.syscollector_packages_vuln_content = syscollector_packages_vuln_content

self.default_package_data = {
'<package_description>': 'A low-level cryptographic library',
'<package_architecture>': 'x86_64',
'<package_format>': 'rpm',
'<package_name>': 'nettle',
'<package_source>': 'vim',
'<package_vendor>': 'Ubuntu Developers <[email protected]>',
'<package_version>': '2.7.1-9.el7_9'
}
self.packages = []

self.old_format = old_format
self.agent_name = agent_name
Expand All @@ -792,6 +784,76 @@ def __init__(self, agent_name, event_types_list, old_format, batch_size, syscoll
self.syscollector_mq = 'd'
self.current_id = 1

self.default_packages_vuln_content = os.path.join(_data_path, 'syscollector_parsed_packages.json')
self.package_index = 0

if self.syscollector_packages_vuln_content:
self.packages = self.init_package_list(self.syscollector_packages_vuln_content)
else:
self.packages = self.init_package_list(self.default_packages_vuln_content)

def parse_package_template(self, message, package_data):
"""Parse package template with package data.
Args:
message (str): Syscollector event message.
package_data (dict): Package data.
Returns:
str: Parsed syscollector event message.
"""
template_package_fields = {
'<package_description>': package_data['description'],
'<package_architecture>': package_data['architecture'],
'<package_format>': package_data['format'],
'<package_name>': package_data['product'],
'<package_source>': package_data['source'],
'<package_vendor>': package_data['vendor'],
'<package_version>': package_data['version'],
'<package_item_id>': package_data['item_id']
}

for package_key, package_value in template_package_fields.items():
message = message.replace(package_key, package_value)

return message

def get_package_data(self):
"""Get package data.
Returns:
dict: Package data.
str: Operation (INSERTED or DELETED).
"""
operation = 'DELETED' if self.packages[self.package_index]['installed'] else 'INSERTED'

package_data = self.packages[self.package_index]

self.packages[self.package_index]['installed'] = not self.packages[self.package_index]['installed']
self.package_index = (self.package_index + 1) % len(self.packages)

return package_data, operation

def init_package_list(self, packages_file):
"""Get package data from a json file.
Returns:
dict: Package data.
"""
with open(os.path.join(_data_path, packages_file), 'r') as fp:
package_data = json.load(fp)

for package in package_data:
package['installed'] = False
if 'description' not in package:
package['description'] = ''
if 'architecture' not in package:
package['architecture'] = ''
if 'format' not in package:
package['format'] = ''
if 'source' not in package:
package['source'] = ''
if 'item_id' not in package:
package['item_id'] = get_random_string(10)

return package_data

def get_event_template_legacy(self, message_type):
"""Get syscollector legacy message of the specified type.
Args:
Expand Down Expand Up @@ -831,6 +893,7 @@ def get_event_template(self, message_type):
message_operation = operation

message_data = {}
package_data = {}

if message_type == 'network':
message_data = syscollector.SYSCOLLECTOR_NETWORK_IFACE_DELTA_EVENT_TEMPLATE
Expand All @@ -847,12 +910,18 @@ def get_event_template(self, message_type):
elif message_type == 'hotfix':
message_data = syscollector.SYSCOLLECTOR_HOTFIX_DELTA_DATA_TEMPLATE

if message_type == 'packages':
package_data, message_operation = self.get_package_data()

message = '{"type": "%s", "data": %s, "operation": "%s"}' % (
message_event_type,
re.sub(r'\s', '', json.dumps(message_data)),
message_operation
)

if message_type == 'packages':
message = self.parse_package_template(message, package_data)

return message

def format_event_template(self, template, message_type=None):
Expand All @@ -869,11 +938,6 @@ def format_event_template(self, template, message_type=None):
for variable, value in generics_fields_to_replace:
message = message.replace(variable, value)

if message_type == 'packages':
if not self.syscollector_packages_vuln_content:
for package_key, package_value in self.default_package_data.items():
message = message.replace(package_key, package_value)

final_mesage = f"{self.syscollector_mq}:{self.syscollector_tag}:{message}"

return final_mesage
Expand Down
Loading