diff --git a/artifacts/definitions/SUSE/Linux/ClamAV/clamdscan.yaml b/artifacts/definitions/SUSE/Linux/ClamAV/clamdscan.yaml new file mode 100644 index 000000000..eee510b52 --- /dev/null +++ b/artifacts/definitions/SUSE/Linux/ClamAV/clamdscan.yaml @@ -0,0 +1,31 @@ +name: SUSE.Linux.ClamAV.clamdscan + +description: | + Run clamdscan on a file or directory. + +type: CLIENT + +required_permissions: + - EXECVE + +parameters: + - name: path + default: /home + description: file or directory to be scanned + - name: show_summary + type: bool + default: False + description: display scan summary + +sources: + - precondition: + SELECT OS FROM info() WHERE OS = "linux" + + query: | + LET rm_empty_opts(opts) = filter(list=opts, regex='^.+$') + + LET summaryOpt = if(condition=show_summary, then="", else="--no-summary") + + LET argv = rm_empty_opts(opts=["clamdscan", "--fdpass", "--stdout", summaryOpt, path]) + + SELECT * FROM execve(argv=argv, sep='\n') diff --git a/artifacts/definitions/SUSE/Linux/Events/ClamAvLogs.yaml b/artifacts/definitions/SUSE/Linux/Events/ClamAvLogs.yaml new file mode 100644 index 000000000..1da1ecebc --- /dev/null +++ b/artifacts/definitions/SUSE/Linux/Events/ClamAvLogs.yaml @@ -0,0 +1,26 @@ +name: SUSE.Linux.Events.ClamAvLogs + +description: | + This artifact watches the systemd journal for messages from + the ClamAV clamd service, and collects any that match the + regex filter parameter. + +type: CLIENT_EVENT + +parameters: + - name: regex_filter + type: regex + default: ".+FOUND$" + description: Filter messages to be collected + +sources: + - precondition: + SELECT OS From info() where OS = 'linux' + + query: | + SELECT + timestamp(epoch=REALTIME_TIMESTAMP) AS Time, + MESSAGE as Message + FROM watch_journal() + WHERE SYSLOG_IDENTIFIER = "clamd" + AND MESSAGE =~ regex_filter diff --git a/artifacts/definitions/SUSE/Linux/Events/ClamdAvCheckConfig.yaml b/artifacts/definitions/SUSE/Linux/Events/ClamdAvCheckConfig.yaml new file mode 100644 index 000000000..342ccdf4e --- /dev/null +++ b/artifacts/definitions/SUSE/Linux/Events/ClamdAvCheckConfig.yaml @@ -0,0 +1,100 @@ +name: SUSE.Linux.Event.ClamAVStatus + +description: | + This artifact checks the running ClamAV configuration at regular intervals. + It generates a row for each required option that is missing or has the wrong + argument, and each option that is configured but is not required. + +type: CLIENT_EVENT + +parameters: + - name: clamd_conf + description: Path to clamd.conf + type: string + default: /etc/clamd.conf + - name: check_period + description: Time between checks in seconds + type: int + default: 7200 + - name: required_options + description: Options and arguments that are required to be set in clamd.conf + type: csv + default: | + Option,Argument + LogSyslog,yes + LogFacility,LOG_MAIL + PidFile,/run/clamav/clamd.pid + LocalSocket,/run/clamav/clamd.sock + User,vscan + OnAccessIncludePath,/home + OnAccessExcludeUname,vscan + +sources: + - precondition: + SELECT OS From info() WHERE OS = 'linux' + + query: | + SELECT * FROM foreach( + row={ + SELECT * FROM clock(start=0, period=check_period) + }, + query={ + -- The query plugin is used so that the materialized queries + -- get recreated on each iteration of the foreach loop. + SELECT * FROM query(query=''' + LET status <= dict(OK=true) + + LET required_dict <= to_dict(item={ + SELECT Option AS _key, Argument AS _value FROM required_options + }) + + LET conf_exists <= if( + condition={ SELECT * from stat(filename=clamd_conf) }, + then=true, else=false + ) + + LET running_conf <= SELECT Option, Argument + FROM parse_csv(filename=clamd_conf, auto_headers=false, separator=" ", comment="#", columns=["Option", "Argument"]) + WHERE conf_exists + + LET running_dict <= to_dict(item={ + SELECT Option AS _key, Argument AS _value FROM running_conf WHERE conf_exists + }) + + SELECT * FROM chain( + a={ + SELECT + format(format="%s is missing option: \"%s %s\"", args=[clamd_conf, Option, Argument]) AS Message + FROM required_options + WHERE conf_exists + AND get(item=running_dict, field=Option) != Argument + AND set(item=status, field="OK", value=false) + }, + b={ + SELECT + format(format="%s has unrequired option: \"%s %s\"", args=[clamd_conf, Option, Argument]) AS Message + FROM running_conf + WHERE conf_exists + AND NOT get(item=required_dict, field=Option) + AND set(item=status, field="OK", value=false) + }, + c={ + SELECT + format(format="%s does not exist", args=[clamd_conf]) AS Message + FROM scope() + WHERE NOT conf_exists + AND set(item=status, field="OK", value=false) + }, + d={ + SELECT + "Configuration is good" AS Message + FROM scope() + WHERE status.OK + } + ) + + ''', + env=dict(clamd_conf=clamd_conf, required_options=required_options) + ) + } + ) diff --git a/artifacts/definitions/SUSE/Linux/Events/ClamdAvServices.yaml b/artifacts/definitions/SUSE/Linux/Events/ClamdAvServices.yaml new file mode 100644 index 000000000..040f479df --- /dev/null +++ b/artifacts/definitions/SUSE/Linux/Events/ClamdAvServices.yaml @@ -0,0 +1,48 @@ +name: SUSE.Linux.Events.ClamAVServices + +description: | + This artifact checks the ClamAV systemd services every + `check_period` seconds and generate a row for each one + found not to be running. + +type: CLIENT_EVENT + +required_permissions: + - EXECVE + +parameters: + - name: check_period + description: Time between checks in seconds. + type: int + default: 7200 + - name: services + description: List of ClamAV services to check. + type: json_array + default: '["clamd", "clamonacc", "freshclam.timer"]' + +sources: + - precondition: + SELECT OS From info() WHERE OS = 'linux' + + query: | + LET is_active(service) = SELECT * + FROM execve(argv=["systemctl", "is-active", "--quiet", service]) + WHERE ReturnCode = 0 + + SELECT * FROM foreach( + row={ + SELECT * FROM clock(start=0, period=check_period) + }, + query={ + SELECT * FROM foreach( + row={ + SELECT _value AS service FROM items(item=services) + }, + query={ + SELECT format(format="%s is not running", args=[service]) AS Message + FROM scope() + WHERE NOT is_active(service=service) + } + ) + } + )