From f69aa45b2391f8acd7be4bd357681bb266910e16 Mon Sep 17 00:00:00 2001 From: martinboller Date: Wed, 17 Apr 2024 21:59:12 +0200 Subject: [PATCH 1/3] Additional and changed scripts for maintaining Greenbone Scanner --- scripts/USAGE.md | 231 +++++++++++++ scripts/clean-sensor.gmp.py | 150 +++++++-- scripts/create-alerts-from-csv.gmp.py | 254 ++++++++++++++ scripts/create-credentials-from-csv.gmp.py | 224 +++++++++++++ scripts/create-filters-from-csv.gmp.py | 216 ++++++++++++ scripts/create-report-format-from-csv.gmp.py | 181 ++++++++++ scripts/create-schedules-from-csv.gmp.py | 169 ++++++++++ scripts/create-tags-from-csv.gmp.py | 327 +++++++++++++++++++ scripts/create-targets-from-csv.gmp.py | 215 ++++++++++++ scripts/create-tasks-from-csv.gmp.py | 296 +++++++++++++++++ scripts/dummy_def.gmp.py | 12 + scripts/empty-trash.gmp.py | 45 +++ scripts/export-csv-report.gmp.py | 102 ++++++ scripts/export-pdf-report.gmp.py | 17 +- scripts/export-xml-report.gmp.py | 102 ++++++ scripts/list-alerts.gmp.py | 70 ++++ scripts/list-credentials.gmp.py | 79 +++++ scripts/list-feeds.gmp.py | 68 ++++ scripts/list-filters.gmp.py | 63 ++++ scripts/list-groups.gmp.py | 62 ++++ scripts/list-policies.gmp.py | 62 ++++ scripts/list-portlists.gmp.py | 64 ++++ scripts/list-report-formats.gmp.py | 61 ++++ scripts/list-reports.gmp.py | 153 +++++++++ scripts/list-roles.gmp.py | 62 ++++ scripts/list-scan-configs.gmp.py | 62 ++++ scripts/list-scanners.gmp.py | 62 ++++ scripts/list-schedules.gmp.py | 64 ++++ scripts/list-tags.gmp.py | 64 ++++ scripts/list-targets.gmp.py | 66 ++++ scripts/list-tasks.gmp.py | 27 +- scripts/list-tickets.gmp.py | 70 ++++ scripts/list-users.gmp.py | 63 ++++ scripts/start-scans-from-csv.py | 157 +++++++++ scripts/stop-all-scans.gmp.py | 53 +++ scripts/stop-scans-from-csv.py | 160 +++++++++ 36 files changed, 4089 insertions(+), 44 deletions(-) create mode 100644 scripts/USAGE.md create mode 100755 scripts/create-alerts-from-csv.gmp.py create mode 100755 scripts/create-credentials-from-csv.gmp.py create mode 100755 scripts/create-filters-from-csv.gmp.py create mode 100755 scripts/create-report-format-from-csv.gmp.py create mode 100755 scripts/create-schedules-from-csv.gmp.py create mode 100755 scripts/create-tags-from-csv.gmp.py create mode 100755 scripts/create-targets-from-csv.gmp.py create mode 100755 scripts/create-tasks-from-csv.gmp.py create mode 100644 scripts/dummy_def.gmp.py create mode 100755 scripts/empty-trash.gmp.py create mode 100755 scripts/export-csv-report.gmp.py create mode 100755 scripts/export-xml-report.gmp.py create mode 100755 scripts/list-alerts.gmp.py create mode 100755 scripts/list-credentials.gmp.py create mode 100755 scripts/list-feeds.gmp.py create mode 100755 scripts/list-filters.gmp.py create mode 100755 scripts/list-groups.gmp.py create mode 100755 scripts/list-policies.gmp.py create mode 100755 scripts/list-portlists.gmp.py create mode 100755 scripts/list-report-formats.gmp.py create mode 100755 scripts/list-reports.gmp.py create mode 100755 scripts/list-roles.gmp.py create mode 100755 scripts/list-scan-configs.gmp.py create mode 100755 scripts/list-scanners.gmp.py create mode 100755 scripts/list-schedules.gmp.py create mode 100755 scripts/list-tags.gmp.py create mode 100755 scripts/list-targets.gmp.py create mode 100755 scripts/list-tickets.gmp.py create mode 100755 scripts/list-users.gmp.py create mode 100755 scripts/start-scans-from-csv.py create mode 100755 scripts/stop-all-scans.gmp.py create mode 100755 scripts/stop-scans-from-csv.py diff --git a/scripts/USAGE.md b/scripts/USAGE.md new file mode 100644 index 00000000..ca4fe826 --- /dev/null +++ b/scripts/USAGE.md @@ -0,0 +1,231 @@ +# Greenbone Vulnerability Manager Python scripts + +## Python scripts that can be used to configure your Greenbone Community Edition Scanner + +[API Reference for GVM 22.5](https://docs.greenbone.net/API/GMP/gmp-22.5.html) + +[Python GVM API](https://greenbone.github.io/python-gvm/api/api.html) + +## Running Python GVM Scripts +For details on Python GVM, please refer to https://gvm-tools.readthedocs.io/en/latest/scripting.html#gvm-scripts, but for these scripts, use +- gvm-script --gmp-username *admin-user* --gmp-password *password* socket *script-name* - Example: +- gvm-script --gmp-username admin --gmp-password SecretPassword socket list-alerts.gmp.py +When you just want to get the XML from Greenbone to look for values/value names, it's easy to use gvm-cli, like this: +- gvm-cli --gmp-username *admin-user* --gmp-password *password* socket --xml="" + +## Python Scripts in this repo: +### clean-sensor.gmp.py +**Script provided by Greenbone as part of GVM-Tools. Used when cleaning up after testing scripts (or starting over)** +- Usage: gvm-script --gmp-username admin --gmp-password '0f6fa69b-32bb-453a-9aa4-b8c9e56b3d00' socket clean-sensor.gmp.py +- clean-sensor now cleans alerts, filters, schedules and tags too. + +### create-Alerts-from-csv.gmp.py +**Creates alerts as specified in a csv-file. See alerts.csv for file format/contents.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-alerts-from-csv.gmp.py alerts.csv +- For SMB Alerts use something like %N_%CT%z in the naming of the report, as shown in the example alerts.csv +- %N is the name for the object or the associated task for reports, %C is the creation date in the format YYYYMMDD, and %c is the creation time in the format HHMMSS. +- The script only support EMAIL and SMB Alerts, please note that the fields are quite different between the two alert types, but refer to the sample alerts.csv +- The CSV must starts with name, type (EMAIL or SMB). The remaining fields then depend on the type chosen, specifically: +- EMAIL; *senders email*, *recipients email*, *mail subject*, *message body*, *notice type* (0=Report in message 1=Simple Notice or 2=Attach Report), *Report Type* (e.g. CSV Results), *Status* (Done, Requested) +- SMB; *SMB Credentials*,*SMB Share Path*,*Report Name*, *Report Folder* (if not stored in the root of the share), *Not used*, *Report Type* (e.g. CSV Results), *Status* (Done, Requested) +- A simple example below with 1 EMAIL alert and 1 SMB Alert. +Alert_EMAIL_Stop,EMAIL,"martin@example.org","noc@example.org","Message Subject","Message Body",1,"CSV Results","Stop Requested" +Alert_SMB_Done,SMB,"Cred_Storage_SMB","\\smbserver\share","%N_%CT%cZ","Reports",,"CSV Results","Done" + +**Note**: This script relies on credentials as/if specified in alerts.csv as well as a working SMTP server on the Greenbone primary server. If you're using SMB add the required credentials first using [create-credentials-from-csv.gmp.py](#create-credentials-from-csvgmppy). + + +### create-schedules-from-csv.gmp.py +**Creates schedules as specified in a csv-file. See schedules.csv for file format/contents.** +Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-schedules-from-csv.gmp.py ./schedules.csv +**Note**: create schedules, then credentials, then targets, then tasks and make sure to use the same names between the input csv-files. +The sample files should serve as examples, however a short explanation of a VCALENDAR stream exported from Greenbone below¹. + +Example Key:Value pair | Comment +---|--- +BEGIN:VCALENDAR | Begin VCalendar Entry +VERSION:2.0 | iCalendar Version number +PRODID:-//Greenbone.net//NONSGML Greenbone Security Manager 23.1.0//EN | As generated by Greenbone replace with something else if you want to +BEGIN:VEVENT | Start of Vevent +DTSTART:20231125T220000Z | Start date +DURATION:PT1H | Duration of scan. PT0S means "Entire Operation". S = seconds, M = minutes, H = hours +RRULE:FREQ=HOURLY;INTERVAL=4 | Frequency; Yearly, Monthly, Weekly, Hourly. Optionally Interval withs same unit +DTSTAMP:20231125T212042Z | Date stamp created +END:VEVENT | End Vevent +END:VCALENDAR | End VCalendar Entry + +¹ See also https://www.rfc-editor.org/rfc/rfc5545.txt Internet Calendaring and Scheduling Core Object Specification (iCalendar) + +### create-credentials-from-csv.gmp.py +**Creates credentials as specified in a csv-file. See credentials.csv for file format/contents.** +Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-credentials-from-csv.gmp.py ./credentials.csv +**Note**: create schedules, then credentials, then targets, then tasks and make sure to use the same names between the input csv-files. +The sample files should serve as an example. + +### create-filters-from-csv.gmp.py +**Creates filters as specified in a csv-file. See filters.csv for file format/contents.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-filters-from-csv.gmp.py ./filters.csv +- CSV-file; filterType, filterName, filterDescription, filterTerm, where + - filterType is one of Alert, Config (scan-config), Credential, Report, Scanner, Schedule, Target, or Task. + - filterName is the name of the filter. + - filterDescription is your description of the filter. + - FilterTerm is the actual term used to define the filter, such as \~Labnet. + +### create-tags-from-csv.gmp.py +**Creates tags as specified in a csv-file. See tags.csv for file format/contents.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-tags-from-csv.gmp.py ./tags.csv +- May contain up to 10 resources to assign to tag. Currently only creates tags for Credential, Target, and Tasks +- Use tag:*searchforthis* as filter. Example: *tag:bsecure* +- Will add reports when I've figured out if tags are really dynamic and a filter will do it for new reports. + +### create-targets-from-csv.gmp.py +**Creates targets as specified in a csv-file. See targets.csv for file format/contents.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-targets-from-csv.gmp.py ./targets.csv +- Alive test can be: + +No | Alive Test | Notes +---|---|--- +1 | Scan Config Default | ICMP Ping is used by default with the Built-in Scan Configurations +2 | ICMP Ping | ICMP echo request and echo reply messages +3 | TCP-ACK Service Ping | Sends TCP packets with only the ACK bit set. Target is required by [RFC 793](http://www.rfc-editor.org/rfc/rfc793.txt) to respond with a RST packet +4 | TCP-SYN Service Ping | SYN only scans (never sends an ACK even if target replies with SYN/ACK) +5 | ICMP & TCP-ACK Service Ping | ICMP & TCP-ACK tests combined +6 | ICMP & ARP Ping | ICMP Ping & sends a broadcast ARP request to solicit a reply from the host that uses the specified IP address +7 | TCP-ACK Service & ARP Ping | TCP-ACK and ARP Ping combined +8 | ICMP, TCP-ACK Service & ARP Ping | ICMP, TCP-ACK, and ARP Ping combined +9 | Consider Alive | Consider the target alive. This may take considerably longer to finish. + + +### create-tasks-from-csv.gmp.py +**Creates tasks as specified in a csv-file. See tasks.csv for file format/contents** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket create-tasks-from-csv.gmp.py ./task.csv

+- Change Hosts Scan Ordering by changing #5 within CSV to Random, Sequential or Reverse in script. +- Specify up to 5 alerts in CSV, blanks will be discarded. +**Note**: Make sure that all other configurations that the tasks may rely on are already created, including alerts, schedules, credentials, and targets, +in other words if it is referenced in tasks.csv it must already exist. + +### empty-trash.gmp.py +- Does what is says on the tin, empties the trashcan in Greenbone. +- Use it when you're testing like crazy and have a trashcan with ~ a gazillion objects +- You can also just use gvm-cli --gmp-username *admin-user* --gmp-password *password* socket --pretty --xml="" + +### export-csv-report.gmp.py +**Requests the report specified and exports it as a csv formatted report locally.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket export-csv-report.gmp.py *report_uuid* ./output.csv +- Get the *report_uuid* with list-reports.gmp.py or find it in the UI. If the output is not specified it will be named *report_uuid.csv* +- Note the only changes to this script is an added ignore_pagination=True, details=True to get the full report. + +### export-pdf-report.gmp.py +**Requests the report specified and exports it as a pdf formatted report locally.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket export-pdf-report.gmp.py *report_uuid* ./output.pdf +- Get the *report_uuid* with list-reports.gmp.py or find it in the UI. If the output is not specified it will be named *report_uuid.pdf* +**Note**: the only changes to this script is an added ignore_pagination=True, details=True to get the full report. + +## list-alerts.gmp.py +**Lists all alerts configured with name and uuid.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-alerts.gmp.py + +## list-credentials.gmp.py +**Lists all credentials configured with name and uuid.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-credentials.gmp.py +- returns Credential uuid, Name, Type, & if insecure use is allowed + +### list-feeds.gmp.py +**Lists feeds and their status.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-feeds.gmp.py + +### list-filters.gmp.py +**Lists filters.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-filters.gmp.py +- Returns Filter Name, uuid, type, and the term (filter) + +### list-groups.gmp.py +**Lists all groups** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-groups.gmp.py +- Returns Group Name, uuid, members + +### list-policies.gmp.py +**Lists compliance policies.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-policies.gmp.py + +### list-portlists.gmp.py +**Lists port lists.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-portlists.gmp.py + +### list-report-formats.gmp.py +**Lists all report formats with name and uuid.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-report-formats.gmp.py + +### list-reports.gmp.py +**Lists all reports that have specified status** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-reports.gmp.py *Status* +- where status is "All", "Requested", "Queued", "Interrupted", "Running", "Stop Requested", "Stopped", or "Done" +- Case matters, so "Done" or "Stopped" will work while "done" or "stopped" will not. +- Script now shows, in percentage, how far the scan/report is. +- There are no reports generated before at least one scan task has been started. + +### list-roles.gmp.py +**Lists all roles** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-roles.gmp.py +- Returns Role Name, uuid, members + +### list-scan-configs.gmp.py +**Lists all scan configs.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-scan-configs.gmp.py + +### list-scanners.gmp.py +**Lists all scanners currently configured.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-scanners.gmp.py +- Returns the scanners Name, uuid, & the host on which it resides (note CVE scanner does not return a host and sockets are local) + +## list-schedules.gmp.py +**Lists all schedules configured with name, uuid, timezone, and iCalendar information.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-schedules.gmp.py + +### list-tags.gmp.py +**Lists all tags currently configured.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-tags.gmp.py +- Returns Tag name, uuid, Modified Date, Value, Type, and Count of ressources assigned to tag. + +### list-targets.gmp.py +**Lists all targets currently configured.** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-targets.gmp.py +- No targets configured by default, however using the provided files in this repo, you should now have a few (5). +- Returns targets Name, uuid, number of Hosts, and credentials (SSH, SMB, ESXi, & SNMP Credentials) + +### list-tasks.gmp.py +**Lists all tasks configured** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-tasks.gmp.py +- No tasks configured by default, however using the provided files in this repo, you should now have some (9). +- Returns the tasks Name, uuid, Target, Scanner, the order in which hosts are scanned¹, and the highest severity (empty if no reports) + +### list-tickets.gmp.py +**Lists all tickets created** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-tickets.gmp.py +- Returns the tickets name, Host, Associated Task, Status, and Note (depending on status either Open-, Fixed-, or Closed note). + +### list-users.gmp.py +**Lists all users** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket list-users.gmp.py +- Returns user Name, uuid, role, groups + + +¹ The default order is "None" which equals sequential, meaning that if this field is empty scanning will be sequential as it will be if specifically set to sequential. Possible results are None, Sequential, Reverse, or Random. + +### start-scans-from-csv.gmp.py +**starts scans (tasks) specified in csv file** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket start-scans-from-csv.gmp.py *csv-file with task names* +- Starts the tasks specified in the file (example startscan.csv) +- Returns the number of tasks started. + +### stop-all-scans.gmp.py +**stops scans (tasks) that are in status running, queued, or requested** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket stop-all-scans.gmp.py +- Stops all scans +- Returns the number of tasks stopped. + +### stop-scans-from-csv.gmp.py +**stops scans (tasks) specified in csv file** +- Usage: gvm-script --gmp-username *admin-user* --gmp-password *password* socket stop-scans-from-csv.gmp.py *csv-file with task names* +- Stops the tasks specified in the file (example startscan.csv works for both scripts) +- Returns the number of tasks stopped. diff --git a/scripts/clean-sensor.gmp.py b/scripts/clean-sensor.gmp.py index 3f28cbaa..882adec0 100644 --- a/scripts/clean-sensor.gmp.py +++ b/scripts/clean-sensor.gmp.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (C) 2017-2021 Greenbone AG +# Copyright (C) 2017-2021 Greenbone Networks GmbH # # SPDX-License-Identifier: GPL-3.0-or-later # @@ -19,6 +19,7 @@ from argparse import Namespace from gvm.protocols.gmp import Gmp +from gvm.errors import GvmResponseError def clean_sensor(gmp: Gmp) -> None: @@ -28,61 +29,140 @@ def clean_sensor(gmp: Gmp) -> None: "status="Stop Requested"" ) - for task_id in tasks.xpath("task/@id"): - print(f"Removing task {task_id} ... ") - status_text = gmp.delete_task(task_id, ultimate=True).xpath( - "@status_text" - )[0] - print(status_text) + try: + for task_id in tasks.xpath("task/@id"): + print(f"Removing task {task_id} ... ") + status_text = gmp.delete_task(task_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass targets = gmp.get_targets(filter_string="rows=-1 not _owner=""") - for target_id in targets.xpath("target/@id"): - print(f"Removing target {target_id} ... ") - status_text = gmp.delete_target(target_id, ultimate=True).xpath( - "@status_text" - )[0] - print(status_text) + try: + for target_id in targets.xpath("target/@id"): + print(f"Removing target {target_id} ... ") + status_text = gmp.delete_target(target_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass configs = gmp.get_scan_configs( filter_string="rows=-1 not _owner=""" ) - for config_id in configs.xpath("config/@id"): - print(f"Removing config {config_id} ... ") - status_text = gmp.delete_scan_config(config_id, ultimate=True).xpath( - "@status_text" - )[0] - print(status_text) + try: + for config_id in configs.xpath("config/@id"): + print(f"Removing config {config_id} ... ") + status_text = gmp.delete_scan_config(config_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass port_lists = gmp.get_port_lists( filter_string="rows=-1 not _owner=""" ) - for port_list_id in port_lists.xpath("port_list/@id"): - print(f"Removing port_list {port_list_id} ... ") - status_text = gmp.delete_port_list(port_list_id, ultimate=True).xpath( - "@status_text" - )[0] - print(status_text) + try: + for port_list_id in port_lists.xpath("port_list/@id"): + print(f"Removing port_list {port_list_id} ... ") + status_text = gmp.delete_port_list(port_list_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass + + alerts = gmp.get_alerts( + filter_string="rows=-1 not _owner=""" + ) + try: + for alert_id in alerts.xpath("alert/@id"): + print(f"Removing alert {alert_id} ... ") + status_text = gmp.delete_alert(alert_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass + + schedules = gmp.get_schedules( + filter_string="rows=-1 not _owner=""" + ) + try: + for schedule_id in schedules.xpath("schedule/@id"): + print(f"Removing schedule {schedule_id} ... ") + status_text = gmp.delete_schedule(schedule_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass + + tags = gmp.get_tags( + filter_string="rows=-1 not _owner=""" + ) + try: + for tag_id in tags.xpath("tag/@id"): + print(f"Removing tag {tag_id} ... ") + status_text = gmp.delete_tag(tag_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass + + filters = gmp.get_filters( + filter_string="rows=-1 not _owner=""" + ) + try: + for filter_id in filters.xpath("filter/@id"): + print(f"Removing filter {filter_id} ... ") + status_text = gmp.delete_filter(filter_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass credentials = gmp.get_credentials( filter_string="rows=-1 not _owner=""" ) - for config_id in credentials.xpath("credential/@id"): - print(f"Removing credential {config_id} ... ") - status_text = gmp.delete_credential(config_id, ultimate=True).xpath( - "@status_text" - )[0] - print(status_text) + try: + for config_id in credentials.xpath("credential/@id"): + print(f"Removing credential {config_id} ... ") + status_text = gmp.delete_credential(config_id, ultimate=True).xpath( + "@status_text" + )[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass print("Emptying trash... ") - status_text = gmp.empty_trashcan().xpath("@status_text")[0] - print(status_text) - + try: + status_text = gmp.empty_trashcan().xpath("@status_text")[0] + print(status_text) + except GvmResponseError as gvmerr: + print(f"{gvmerr=}") + pass def main(gmp: Gmp, args: Namespace) -> None: # pylint: disable=unused-argument print( - "This script removes all resources from a sensor, except active tasks." + "This script removes all resources from a sensor, except active tasks.\n" ) clean_sensor(gmp) diff --git a/scripts/create-alerts-from-csv.gmp.py b/scripts/create-alerts-from-csv.gmp.py new file mode 100755 index 00000000..2e5e8b1f --- /dev/null +++ b/scripts/create-alerts-from-csv.gmp.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on Greenbone sample scripts +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-alerts-from-csv.gmp.py alerts.csv +# +# +# Information on Variables to be used in alerts: https://docs.greenbone.net/GSM-Manual/gos-22.04/en/scanning.html#using-alerts +# Example script: https://forum.greenbone.net/t/working-example-of-creating-an-alert-using-script/7511/2 + +import sys +import time +import csv +import json + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls alert information " + "from a csv file and creates a alert for each row. \n" + "use the same alert names when creating tasks! \n\n" + "Use example alerts.csv as a template \n\n" + "It should be rather self explanatory." +) + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 2: + message = """ + This script pulls alerts from a csv file and creates a \ +alert for each row in the csv file. + One parameter after the script name is required. + + 1. -- csv file containing names and secrets required for scan alerts + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_alerts_from_csv.gmp.py \ + + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "alert_file", + type=str, + help=("CSV File containing alerts"), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def alert_id( + gmp: Gmp, + alert_name: str, +): + response_xml = gmp.get_alerts(filter_string="rows=-1, name=" + alert_name) + alerts_xml = response_xml.xpath("alert") + alert_id = "" + + for alert in alerts_xml: + name = "".join(alert.xpath("name/text()")) + alert_id = alert.get("id") + return alert_id + +def credential_id( + gmp: Gmp, + credential_name: str, +): + response_xml = gmp.get_credentials(filter_string="rows=-1, name=" + credential_name) + credentials_xml = response_xml.xpath("credential") + credential_id = "" + + for credential in credentials_xml: + name = "".join(credential.xpath("name/text()")) + credential_id = credential.get("id") + return credential_id + +def report_format_id( + gmp: Gmp, + report_format_name: str, +): + response_xml = gmp.get_report_formats(details=True, filter_string="rows=-1, name=" + report_format_name) + report_formats_xml = response_xml.xpath("report_format") + report_format_id = "" + + for report_format in report_formats_xml: + name = "".join(report_format.xpath("name/text()")) + report_format_id = report_format.get("id") + return report_format_id + +def event_list(string): + event_list = list(string.split(" ")) + return event_list + + +def create_alerts( + gmp: Gmp, + alert_file: Path, +): + try: + numberalerts = 0 + with open(alert_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + alert_name = row[0] + str_alert_type = row[1] + strRow2 = row[2] + strRow3 = row[3] + strRow4 = row[4] + strRow5 = row[5] + strRow6 = row[6] + report_format = report_format_id(gmp, row[7]) + event_data = row[8] + + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + alert_type=getattr(gmp.types.AlertMethod, str_alert_type) + + if alert_id(gmp, alert_name): + print(f"Alert: {alert_name} exist, not creating...") + continue + + if str_alert_type == "EMAIL": + sender_email = strRow2 + recipient_email = strRow3 + subject = strRow4 + message = strRow5 + notice_type = strRow6 + try: + print("Creating alert: " + alert_name) + gmp.create_alert( + name=alert_name, + comment=comment, + event=gmp.types.AlertEvent.TASK_RUN_STATUS_CHANGED, + event_data={"status": event_data}, + condition=gmp.types.AlertCondition.ALWAYS, + method=alert_type, + method_data={ + "message": message, + "notice": notice_type, + "from_address": sender_email, + "subject": subject, + "notice_report_format": report_format, + "notice_attach_format": report_format, + "to_address": recipient_email, + }, + ) + numberalerts = numberalerts + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {alert_name}") + pass + else: + smb_credential = credential_id(gmp, strRow2) + smb_share_path = strRow3 + smb_report_name = strRow4 + smb_folder = strRow5 + smb_file_path = smb_folder + "/" + smb_report_name + + try: + print("Creating alert: " + alert_name) + gmp.create_alert( + name=alert_name, + comment=comment, + event=gmp.types.AlertEvent.TASK_RUN_STATUS_CHANGED, + event_data={"status": event_data}, + condition=gmp.types.AlertCondition.ALWAYS, + method=alert_type, + method_data={ + "smb_credential": smb_credential, + "smb_share_path": smb_share_path, + "smb_report_format": report_format, + "smb_file_path": smb_file_path, + }, + ) + numberalerts = numberalerts + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {alert_name}") + pass + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read alert_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("alerts file is empty (exit)") + + return numberalerts + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Creating alerts.\n" + ) + + numberalerts = create_alerts( + gmp, + parsed_args.alert_file, + ) + + numberalerts = str(numberalerts) + print(" [" + numberalerts + "] alert(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-credentials-from-csv.gmp.py b/scripts/create-credentials-from-csv.gmp.py new file mode 100755 index 00000000..fbbadb63 --- /dev/null +++ b/scripts/create-credentials-from-csv.gmp.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-targets-from-host-list.gmp.py +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-credentials-from-csv.gmp.py credentials.csv +# +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls Credential information " + "from a csv file and creates a credential for each row. \n" + "use the same credential names when creating targets! \n\n" + "csv file may contain Name of target, Login, password, and ssh-key \n" + "Name,Type,Login,Password,ssh-key \n\n" + "Please note: SNMP and ESX not supported yet " +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 2: + message = """ + This script pulls credentials from a csv file and creates a \ +credential for each row in the csv file. + One parameter after the script name is required. + + 1. -- csv file containing names and secrets required for scan credentials + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_credentials_from_csv.gmp.py \ + + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "cred_file", + type=str, + help=("CSV File containing credentials"), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def credential_id( + gmp: Gmp, + credName: str, +): + response_xml = gmp.get_credentials(filter_string="rows=-1, name=" + credName) + credentials_xml = response_xml.xpath("credential") + cred_id = "" + + for credential in credentials_xml: + name = "".join(credential.xpath("name/text()")) + cred_id = credential.get("id") + return cred_id + +def create_credentials( + gmp: Gmp, + cred_file: Path, +): + try: + numberCredentials = 0 + with open(cred_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + cred_name = row[0] + cred_type = row[1] + userName = row[2] + userPW = row[3] + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + + if credential_id(gmp, cred_name): + print(f"Credential: {cred_name} exist, not creating...") + continue + + if cred_type == "UP": + try: + print("Creating credential: " + cred_name) + gmp.create_credential( + name=cred_name, + credential_type=gmp.types.CredentialType.USERNAME_PASSWORD, + login=userName, + password=userPW, + comment=comment, + ) + numberCredentials = numberCredentials + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {cred_name}") + pass + elif cred_type == "SSH": + with open(row[4]) as key_file: + key = key_file.read() + + try: + print("Creating credential: " + cred_name) + gmp.create_credential( + name=cred_name, + credential_type=gmp.types.CredentialType.USERNAME_SSH_KEY, + login=userName, + key_phrase=userPW, + private_key=key, + comment=comment, + ) + numberCredentials = numberCredentials + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {cred_name}") + pass + elif cred_type == "SNMP": + # Unfinished, copy of UP for now + try: + print("Creating credential: " + cred_name) + gmp.create_credential( + name=cred_name, + credential_type=gmp.types.CredentialType.USERNAME_SSH_KEY, + login=userName, + key_phrase=userPW, + private_key=key, + comment=comment, + ) + numberCredentials = numberCredentials + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {cred_name}") + pass + + elif cred_type == "ESX": + # Unfinished, copy of UP for now + try: + print("Creating credential: " + cred_name) + gmp.create_credential( + name=cred_name, + credential_type=gmp.types.CredentialType.USERNAME_SSH_KEY, + login=userName, + key_phrase=userPW, + private_key=key, + comment=comment, + ) + numberCredentials = numberCredentials + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {cred_name}") + pass + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read cred_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("Credentials file is empty (exit)") + + return numberCredentials + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Creating credentials.\n" + ) + + numberCredentials = create_credentials( + gmp, + parsed_args.cred_file, + ) + + numberCredentials = str(numberCredentials) + print(" [" + numberCredentials + "] Credential(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-filters-from-csv.gmp.py b/scripts/create-filters-from-csv.gmp.py new file mode 100755 index 00000000..5d48a9f8 --- /dev/null +++ b/scripts/create-filters-from-csv.gmp.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-filterw-from-host-list +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-filters-from-csv.gmp.py hostname-server filters.csv +# +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls filtername, hostnames/IP addresses, and credentials " + "from a csv file and creates a filter for each row. \n\n" + "csv file to contain name of filter, ips, and up to 4 credentials previously created \n" + "name,ip-addresses,credential1,credential2,credential3,credential4" +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 1: + message = """ + This script pulls filter names from a csv file and creates a filter \ +for each row. + One parameter after the script name is required. + + 1. -- text file containing filtername and hostnames or IP-addresses + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_filters_from_csv.gmp + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "filters_csv_file", + type=str, + help=("File containing host names / IPs"), + ) + + script_args, _ = parser.parse_known_args(args) + return script_args + +def filter_id( + gmp: Gmp, + filter_name: str, +): + response_xml = gmp.get_filters(filter_string="rows=-1, name=" + filter_name) + filters_xml = response_xml.xpath("filter") + filter_id = "" + + for filter in filters_xml: + name = "".join(filter.xpath("name/text()")) + filter_id = filter.get("id") + return filter_id + +def create_filters( + gmp: Gmp, + filter_csv_file: Path, +): + try: + numberfilters = 0 + with open(filter_csv_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + filterType = row[0] + filterName = row[1] + filterDescription = row[2] + filterTerm = row[3] + filterNameFull = filterName + ":" + filterDescription + ":" + filterType + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + filterResources = [] + if filterType == "FAIL!": + print(filterType.upper()) + elif filterType.upper() == "ALERT": + resource_type=gmp.types.FilterType.ALERT + elif filterType.upper() == "ASSET": + resource_type=gmp.types.FilterType.ASSET + elif filterType.upper() == "CONFIG": + resource_type=gmp.types.FilterType.SCAN_CONFIG + elif filterType.upper() == "CREDENTIAL": + resource_type=gmp.types.FilterType.CREDENTIAL + elif filterType.upper() == "HOST": + resource_type=gmp.types.FilterType.HOST + elif filterType.upper() == "SECINFO": + resource_type=gmp.types.FilterType.ALL_SECINFO + elif filterType.upper() == "NOTE": + resource_type=gmp.types.FilterType.NOTE + elif filterType.upper() == "OS": + resource_type=gmp.types.FilterType.OPERATING_SYSTEM + elif filterType.upper() == "OVERRIDE": + resource_type=gmp.types.FilterType.OVERRIDE + elif filterType.upper() == "PERMISSION": + resource_type=gmp.types.FilterType.PERMISSION + elif filterType.upper() == "PORT_LIST": + resource_type=gmp.types.FilterType.PORT_LIST + elif filterType.upper() == "REPORT": + resource_type=gmp.types.FilterType.REPORT + elif filterType.upper() == "REPORT_FORMAT": + resource_type=gmp.types.FilterType.REPORT_FORMAT + elif filterType.upper() == "RESULT": + resource_type=gmp.types.FilterType.RESULT + elif filterType.upper() == "ROLE": + resource_type=gmp.types.FilterType.ROLE + elif filterType.upper() == "SCHEDULE": + resource_type=gmp.types.FilterType.SCHEDULE + elif filterType.upper() == "TAG": + resource_type=gmp.types.FilterType.TAG + elif filterType.upper() == "TARGET": + resource_type=gmp.types.FilterType.TARGET + elif filterType.upper() == "TASK": + resource_type=gmp.types.FilterType.TASK + elif filterType.upper() == "TICKET": + resource_type=gmp.types.FilterType.TICKET + elif filterType.upper() == "TLS_CERTIFICATE": + resource_type=gmp.types.FilterType.TLS_CERTIFICATE + elif filterType.upper() == "USER": + resource_type=gmp.types.FilterType.USER + elif filterType.upper() == "VULNERABILITY": + resource_type=gmp.types.FilterType.VULNERABILITY + else: + print("FilterType: " + filterType.upper() + " Not supported") + try: + if filter_id(gmp, filterNameFull): + print(f"Filter: {filterNameFull} exist, not creating...") + continue + + print("Creating filter: " + filterNameFull) + gmp.create_filter( + name=filterNameFull, comment=comment, filter_type=resource_type, term=filterTerm, + ) + numberfilters = numberfilters + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {filterNameFull}") + pass + csvFile.close() #close the csv file + except IOError as e: + error_and_exit(f"Failed to read filter_csv_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("filter file is empty (exit)") + + return numberfilters + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Creating filters.\n" + ) + + numberfilters = create_filters( + gmp, + parsed_args.filters_csv_file, + ) + + numberfilters = str(numberfilters) + print(" [" + numberfilters + "] filter(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-report-format-from-csv.gmp.py b/scripts/create-report-format-from-csv.gmp.py new file mode 100755 index 00000000..2a1285b4 --- /dev/null +++ b/scripts/create-report-format-from-csv.gmp.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-targets-from-host-list.gmp.py +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-report_formats-from-csv.gmp.py report_formats.csv +# +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls report-format information " + "from a csv file and creates a report-format for each row. \n" + "csv file may contain Name of target, Login, password, and ssh-key \n" + "Name,Type,Login,Password,ssh-key \n\n" + "Please note: SNMP and ESX not supported yet " +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 2: + message = """ + This script pulls report-format data from a csv file and creates a \ +report-format for each row in the csv file. + One parameter after the script name is required. + + 1. -- csv file containing names and secrets required for scan report_formats + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_report_formats_from_csv.gmp.py \ + + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "cred_file", + type=str, + help=("CSV File containing report_formats"), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def create_report_formats( + gmp: Gmp, + cred_file: Path, +): + try: + numberreport_formats = 0 + with open(cred_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + numberreport_formats = numberreport_formats + 1 + REPORT_FORMAT_XML_STRING = ( + '' + '' + "CSV vulnscan.dk" + 'name=CSV first=1 rows=10 sort=name' + '' + '' + 'name' + '=' + 'CSV' + '' + '' + 'first' + '=' + '1' + '' + '' + 'rows' + '=' + '10' + '' + '' + 'sort' + '=' + 'name' + '' + '' + 'csv' + 'text/csv' + "vulnscan.dk CSV Report Format. Version 2023-03-31." + "vulnscan.dk CSV Report Format" + 'Complete scan report in GMP XML format. Version 20200827.' + '1' + '0' + '1' + '1' + "2024-03-31T10:48:03Z" + "2024-03-31T10:48:03Z" + '' + '500' + "" + "" + ) + + rf_copy = "c1645568-627a-11e3-a660-406186ea4fc5" + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + + gmp.import_report_format( + REPORT_FORMAT_XML_STRING + ) + + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read cred_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("report_formats file is empty (exit)") + + return numberreport_formats + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + numberreport_formats = create_report_formats( + gmp, + parsed_args.cred_file, + ) + + numberreport_formats = str(numberreport_formats) + print(" \n [" + numberreport_formats + "] report_format(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-schedules-from-csv.gmp.py b/scripts/create-schedules-from-csv.gmp.py new file mode 100755 index 00000000..ddc3b2f7 --- /dev/null +++ b/scripts/create-schedules-from-csv.gmp.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-targets-from-host-list.gmp.py +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-schedules-from-csv.gmp.py schedules.csv +# +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls schedule information " + "from a csv file and creates a schedule for each row. \n" + "use the same schedule names when creating tasks! \n\n" + "csv file may contain Name of schedule, Timezone, Icalendar entry \n" + "Use example schedules.csv as a template \n\n" + "It should be rather self explanatory." +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 2: + message = """ + This script pulls schedules from a csv file and creates a \ +schedule for each row in the csv file. + One parameter after the script name is required. + + 1. -- csv file containing names and secrets required for scan schedules + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_schedules_from_csv.gmp.py \ + + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "sched_file", + type=str, + help=("CSV File containing schedules"), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def schedule_id( + gmp: Gmp, + schedule_name: str, +): + response_xml = gmp.get_schedules(filter_string="rows=-1, name=" + schedule_name) + schedules_xml = response_xml.xpath("schedule") + schedule_id = "" + + for schedule in schedules_xml: + name = "".join(schedule.xpath("name/text()")) + schedule_id = schedule.get("id") + return schedule_id + + +def create_schedules( + gmp: Gmp, + sched_file: Path, +): + try: + numberschedules = 0 + with open(sched_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + sched_name = row[0] + sched_tz = row[1] + sched_ical = row[2] + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + try: + if schedule_id(gmp, sched_name): + print(f"Schedule: {sched_name} exist, not creating...") + continue + print("Creating schedule: " + sched_name) + gmp.create_schedule( + name=sched_name, + timezone=sched_tz, + icalendar=sched_ical, + comment=comment + ) + numberschedules = numberschedules + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {sched_name}") + pass + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read sched_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("schedules file is empty (exit)") + + return numberschedules + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Creating schedules.\n" + ) + + numberschedules = create_schedules( + gmp, + parsed_args.sched_file, + ) + + numberschedules = str(numberschedules) + print(" [" + numberschedules + "] schedule(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-tags-from-csv.gmp.py b/scripts/create-tags-from-csv.gmp.py new file mode 100755 index 00000000..8c06431d --- /dev/null +++ b/scripts/create-tags-from-csv.gmp.py @@ -0,0 +1,327 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-tagw-from-host-list +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-tags-from-csv.gmp.py hostname-server tags.csv +# +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List + +from gvm.protocols.gmp import Gmp +from gvm.errors import GvmResponseError +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls tagname, hostnames/IP addresses, and credentials " + "from a csv file and creates a tag for each row. \n\n" + "csv file to contain name of tag, ips, and up to 4 credentials previously created \n" + "name,ip-addresses,credential1,credential2,credential3,credential4" +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 1: + message = """ + This script pulls tag names from a csv file and creates a tag \ +for each row. + One parameter after the script name is required. + + 1. -- text file containing tagname and hostnames or IP-addresses + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_tags_from_csv.gmp + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "tags_csv_file", + type=str, + help=("File containing host names / IPs"), + ) + + script_args, _ = parser.parse_known_args(args) + return script_args + +def config_id( + gmp: Gmp, + config_name: str, +): + response_xml = gmp.get_scan_configs(filter_string="rows=-1, name= " + config_name) + scan_configs_xml = response_xml.xpath("config") + config_id = "" + + for scan_config in scan_configs_xml: + name = "".join(scan_config.xpath("name/text()")) + config_id = scan_config.get("id") + return config_id + +def alert_id( + gmp: Gmp, + alert_name: str, +): + response_xml = gmp.get_alerts(filter_string="rows=-1, name=" + alert_name) + alerts_xml = response_xml.xpath("alert") + alert_id = "" + + for alert in alerts_xml: + name = "".join(alert.xpath("name/text()")) + alert_id = alert.get("id") + return alert_id + +def credential_id( + gmp: Gmp, + credName: str, +): + response_xml = gmp.get_credentials(filter_string="rows=-1, name=" + credName) + credentials_xml = response_xml.xpath("credential") + cred_id = "" + + for credential in credentials_xml: + name = "".join(credential.xpath("name/text()")) + cred_id = credential.get("id") + return cred_id + +def target_id( + gmp: Gmp, + targetName: str, +): + response_xml = gmp.get_targets(filter_string="rows=-1, name=" + targetName) + targets_xml = response_xml.xpath("target") + target_id = "" + + for target in targets_xml: + name = "".join(target.xpath("name/text()")) + target_id = target.get("id") + return target_id + +def task_id( + gmp: Gmp, + taskName: str, +): + response_xml = gmp.get_tasks(filter_string="rows=-1, name=" + taskName) + tasks_xml = response_xml.xpath("task") + task_id = "" + + for task in tasks_xml: + name = "".join(task.xpath("name/text()")) + task_id = task.get("id") + return task_id + +def tag_id( + gmp: Gmp, + tagName: str, +): + response_xml = gmp.get_tags(filter_string="rows=-1, name=" + tagName) + tags_xml = response_xml.xpath("tag") + tag_id = "" + + for tag in tags_xml: + name = "".join(tag.xpath("name/text()")) + tag_id = tag.get("id") + return tag_id + +def scanner_id( + gmp: Gmp, + scanner_name: str, +): + response_xml = gmp.get_scanners(filter_string="rows=-1, name=" + scanner_name) + scanners_xml = response_xml.xpath("scanner") + scanner_id = "" + + for scanner in scanners_xml: + name = "".join(scanner.xpath("name/text()")) + scanner_id = scanner.get("id") + return scanner_id + +def schedule_id( + gmp: Gmp, + schedule_name: str, +): + response_xml = gmp.get_schedules(filter_string="rows=-1, name=" + schedule_name) + schedules_xml = response_xml.xpath("schedule") + schedule_id = "" + + for schedule in schedules_xml: + name = "".join(schedule.xpath("name/text()")) + schedule_id = schedule.get("id") + return schedule_id + +def create_tags( + gmp: Gmp, + tag_csv_file: Path, +): + try: + numbertags = 0 + with open(tag_csv_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + tagType = row[0] + tagName = row[1] + tagDescription = row[2] + tagNameFull = tagName + ":" + tagDescription + ":" + tagType + if tag_id(gmp, tagNameFull): + print(f"Tag: {tagNameFull} already exist") + continue + # Up to ten resources (rows 3 - 12) + tagResources = [] + if tagType.upper() == "FAIL!": + print("Failed!") + elif tagType.upper() == "ALERT": + getUUID=alert_id + resource_type=gmp.types.EntityType.ALERT + elif tagType.upper() == "CONFIG": + getUUID=config_id + resource_type=gmp.types.EntityType.SCAN_CONFIG + elif tagType.upper() == "CREDENTIAL": + getUUID=credential_id + resource_type=gmp.types.EntityType.CREDENTIAL + elif tagType.upper() == "REPORT": + filter = "~" + tagName + resource_type=gmp.types.EntityType.REPORT + elif tagType.upper() == "SCANNER": + getUUID=scanner_id + resource_type=gmp.types.EntityType.SCANNER + elif tagType.upper() == "SCHEDULE": + getUUID=schedule_id + resource_type=gmp.types.EntityType.SCHEDULE + elif tagType.upper() == "TARGET": + getUUID=target_id + resource_type=gmp.types.EntityType.TARGET + elif tagType.upper() == "TASK": + getUUID=task_id + resource_type=gmp.types.EntityType.TASK + else: + print("Only alert, config, credential, report, scanner, schedule, target, and task supported") + exit() + + if len(row[3]) >= 1: + tagResource = (getUUID(gmp, row[3])) + tagResources.append(tagResource) + if len(row[4]) >= 1: + tagResource = (getUUID(gmp, row[4])) + tagResources.append(tagResource) + if len (row[5]) >= 1: + tagResource = (getUUID(gmp, row[5])) + tagResources.append(tagResource) + if len(row[6]) >= 1: + tagResource = (getUUID(gmp, row[6])) + tagResources.append(tagResource) + if len(row[7]) >= 1: + tagResource = (getUUID(gmp, row[7])) + tagResources.append(tagResource) + if len (row[8]) >= 1: + tagResource = (getUUID(gmp, row[8])) + tagResources.append(tagResource) + if len(row[9]) >= 1: + tagResource = (getUUID(gmp, row[9])) + tagResources.append(tagResource) + tagResource = (getUUID(gmp, row[10])) + if len(row[10]) >= 1: + tagResources.append(tagResource) + if len(row[11]) >= 1: + tagResource = (getUUID(gmp, row[11])) + tagResources.append(tagResource) + if len(row[12]) >= 1: + tagResource = (getUUID(gmp, row[12])) + tagResources.append(tagResource) + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + + if tagType.upper() == "REPORT": + try: + print("Creating tag: " + tagNameFull) + gmp.create_tag( + name=tagNameFull, comment=comment, value=tagName, resource_type=resource_type, resource_filter=filter, + ) + numbertags = numbertags + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {tagNameFull}") + pass + else: + try: + print("Creating tag: " + tagNameFull) + gmp.create_tag( + name=tagNameFull, comment=comment, value=tagName, resource_type=resource_type, resource_ids=tagResources, + ) + numbertags = numbertags + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {tagNameFull}") + pass + csvFile.close() #close the csv file + except IOError as e: + error_and_exit(f"Failed to read tag_csv_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("tag file is empty (exit)") + + return numbertags + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Creating tags.\n" + ) + + numbertags = create_tags( + gmp, + parsed_args.tags_csv_file, + ) + + numbertags = str(numbertags) + print(" [" + numbertags + "] tag(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-targets-from-csv.gmp.py b/scripts/create-targets-from-csv.gmp.py new file mode 100755 index 00000000..203920ff --- /dev/null +++ b/scripts/create-targets-from-csv.gmp.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-targetw-from-host-list +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-targets-from-csv.gmp.py hostname-server targets.csv +# +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError +from gvm.protocols.gmp import Gmp +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls targetname, hostnames/IP addresses, and credentials " + "from a csv file and creates a target for each row. \n\n" + "csv file to contain name of target, ips, and up to 4 credentials previously created \n" + "name,ip-addresses,credential1,credential2,credential3,credential4" +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 1: + message = """ + This script pulls target names from a csv file and creates a target \ +for each row. + One parameter after the script name is required. + + 1. -- text file containing Targetname and hostnames or IP-addresses + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_targets_from_csv.gmp + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "targets_csv_file", + type=str, + help=("File containing host names / IPs"), + ) + + ports = parser.add_mutually_exclusive_group() + ports.add_argument( + "+pl", + "++port-list-id", + type=str, + dest="port_list_id", + help="UUID of existing port list.", + ) + ports.add_argument( + "+pr", + "++port-range", + dest="port_range", + type=str, + help=( + "Port range to create port list from, e.g. " + "T:1-1234 for ports 1-1234/TCP" + ), + ) + + ports.set_defaults( + port_list_id="730ef368-57e2-11e1-a90f-406186ea4fc5" + ) # All TCP and Nmap top 100 UDP + # Default portlists see also script list-portlists.gmp.py + # | Name | ID + # - | ----------------------------- | ------------------------------------ + # 1 | All IANA assigned TCP | 33d0cd82-57c6-11e1-8ed1-406186ea4fc5 + # 2 | All IANA assigned TCP and UDP | 4a4717fe-57d2-11e1-9a26-406186ea4fc5 + # 3 | All TCP and Nmap top 100 UDP | 730ef368-57e2-11e1-a90f-406186ea4fc5 + + script_args, _ = parser.parse_known_args(args) + return script_args + +def credential_id( + gmp: Gmp, + credName: str, +): + response_xml = gmp.get_credentials(filter_string="rows=-1, name=" + credName) + credentials_xml = response_xml.xpath("credential") + cred_id = "" + + for credential in credentials_xml: + name = "".join(credential.xpath("name/text()")) + cred_id = credential.get("id") + return cred_id + +def target_id( + gmp: Gmp, + targetName: str, +): + response_xml = gmp.get_targets(filter_string="rows=-1, name=" + targetName) + targets_xml = response_xml.xpath("target") + target_id = "" + + for target in targets_xml: + name = "".join(target.xpath("name/text()")) + target_id = target.get("id") + return target_id + +def create_targets( + gmp: Gmp, + target_csv_file: Path, + port_list_id: str, +): + try: + numberTargets = 0 + with open(target_csv_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + name = row[0] + hosts = [row[1]] + smbCred = credential_id(gmp, row[2]) + sshCred = credential_id(gmp, row[3]) + snmpCred = credential_id(gmp, row[4]) + esxCred = credential_id(gmp, row[5]) + aliveTest = row[6] + if not aliveTest: + aliveTest = "Scan Config Default" + alive_test = gmp.types.AliveTest( + (aliveTest) + ) + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + try: + if target_id(gmp, name): + print(f"Target: {name} exist, not creating...") + continue + + print("Creating target: " + name) + gmp.create_target( + name=name, comment=comment, hosts=hosts, port_list_id=port_list_id, smb_credential_id=smbCred, ssh_credential_id=sshCred, alive_test=alive_test + ) + numberTargets = numberTargets + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {name}") + pass + csvFile.close() #close the csv file + except IOError as e: + error_and_exit(f"Failed to read target_csv_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("Host file is empty (exit)") + + return numberTargets + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + #port_list_id="4a4717fe-57d2-11e1-9a26-406186ea4fc5" + + print( + "Creating targets.\n" + ) + + numberTargets = create_targets( + gmp, + parsed_args.targets_csv_file, + parsed_args.port_list_id + ) + + numberTargets = str(numberTargets) + print(" [" + numberTargets + "] Target(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/create-tasks-from-csv.gmp.py b/scripts/create-tasks-from-csv.gmp.py new file mode 100755 index 00000000..e03ebd0b --- /dev/null +++ b/scripts/create-tasks-from-csv.gmp.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on the create-targets-from-host-list +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket create-tasks-from-csv.gmp.py hostname-server tasks.csv +# +# +# Note: for some weird reason theres a space in front of the default scan config " Full and fast" +# Examples of all defaults in tasks.csv +# + +import sys +import time +import csv + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.protocols.gmpv208.entities.hosts import HostsOrdering #Only available in version 20.8 +from gvm.protocols.gmp import Gmp +from gvm.errors import GvmResponseError +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls taskname, scanner, & scan config " + "from a csv file and creates a task for each row. \n\n" + "csv file to contain name of task, target name, scanner name, and scan config name \n" + "name,target,scanner,scan config" +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 1: + message = """ + This script pulls taskinformation from a csv file and creates a task \ +for each row. + One parameter after the script name is required. + + 1. -- text file containing taskname, target name, scanner name, and scan config name + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/create_tasks_from_csv.gmp + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "tasks_csv_file", + type=str, + help=("File containing host names / IPs"), + ) + + ports = parser.add_mutually_exclusive_group() + ports.add_argument( + "+pl", + "++port-list-id", + type=str, + dest="port_list_id", + help="UUID of existing port list.", + ) + ports.add_argument( + "+pr", + "++port-range", + dest="port_range", + type=str, + help=( + "Port range to create port list from, e.g. " + "T:1-1234 for ports 1-1234/TCP" + ), + ) + + ports.set_defaults( + port_list_id="730ef368-57e2-11e1-a90f-406186ea4fc5" + ) # All IANA assigned TCP and Top 100 UDP, use the list-portlists.gmp.py script to get the UUID for all. + # Defaults are + # # | Name | ID + # - | ----------------------------- | ------------------------------------ + # 1 | All IANA assigned TCP | 33d0cd82-57c6-11e1-8ed1-406186ea4fc5 + # 2 | All IANA assigned TCP and UDP | 4a4717fe-57d2-11e1-9a26-406186ea4fc5 + # 3 | All TCP and Nmap top 100 UDP | 730ef368-57e2-11e1-a90f-406186ea4fc5 + + script_args, _ = parser.parse_known_args(args) + return script_args + +def config_id( + gmp: Gmp, + config_name: str, +): + response_xml = gmp.get_scan_configs(filter_string="rows=-1, name= " + config_name +) + scan_configs_xml = response_xml.xpath("config") + config_id = "" + + for scan_config in scan_configs_xml: + name = "".join(scan_config.xpath("name/text()")) + config_id = scan_config.get("id") + return config_id + +def alert_id( + gmp: Gmp, + alert_name: str, +): + response_xml = gmp.get_alerts(filter_string="rows=-1, name=" + alert_name) + alerts_xml = response_xml.xpath("alert") + alert_id = "" + + for alert in alerts_xml: + name = "".join(alert.xpath("name/text()")) + alert_id = alert.get("id") + return alert_id + +def target_id( + gmp: Gmp, + target_name: str, +): + response_xml = gmp.get_targets(filter_string="rows=-1, name=" + target_name) + targets_xml = response_xml.xpath("target") + target_id = "" + + for target in targets_xml: + name = "".join(target.xpath("name/text()")) + target_id = target.get("id") + return target_id + +def scanner_id( + gmp: Gmp, + scanner_name: str, +): + response_xml = gmp.get_scanners(filter_string="rows=-1, name=" + scanner_name) + scanners_xml = response_xml.xpath("scanner") + scanner_id = "" + + for scanner in scanners_xml: + name = "".join(scanner.xpath("name/text()")) + scanner_id = scanner.get("id") + return scanner_id + +def schedule_id( + gmp: Gmp, + schedule_name: str, +): + response_xml = gmp.get_schedules(filter_string="rows=-1, name=" + schedule_name) + schedules_xml = response_xml.xpath("schedule") + schedule_id = "" + + for schedule in schedules_xml: + name = "".join(schedule.xpath("name/text()")) + schedule_id = schedule.get("id") + return schedule_id + +def task_id( + gmp: Gmp, + taskName: str, +): + response_xml = gmp.get_tasks(filter_string="rows=-1, name=" + taskName) + tasks_xml = response_xml.xpath("task") + task_id = "" + + for task in tasks_xml: + name = "".join(task.xpath("name/text()")) + task_id = task.get("id") + return task_id + +def create_tasks( + gmp: Gmp, + task_csv_file: Path, + port_list_id: str, +): + try: + numberTasks = 0 + with open(task_csv_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + for row in content: #loop through each row + if len(row) == 0: + continue + name = row[0] + targetId = target_id(gmp, row[1]) + scannerId = scanner_id(gmp, row[2]) + alterable = "True" + configId = config_id(gmp, row[3]) + scheduleId = schedule_id(gmp, row[4]) + + newOrder = row[5].upper() + if newOrder == "RANDOM": + order = HostsOrdering.RANDOM + elif newOrder == "SEQUENTIAL": + order = HostsOrdering.SEQUENTIAL + elif newOrder == "REVERSE": + order = HostsOrdering.REVERSE + else: + order = HostsOrdering.RANDOM + + alerts = [] + if len(row[6]) > 1: + alert = alert_id(gmp, row[6]) + alerts.append(alert) + if len(row[7]) > 1: + alert = alert_id(gmp, row[7]) + alerts.append(alert) + if len (row[8]) > 1: + alert = alert_id(gmp, row[8]) + alerts.append(alert) + if len(row[9]) > 1: + alert = alert_id(gmp, row[9]) + alerts.append(alert) + if len(row[10]) > 1: + alert = alert_id(gmp, row[10]) + alerts.append(alert) + + scanOrder = order # Use SEQUENTIAL, REVERSE, or RANDOM + comment = f"Created: {time.strftime('%Y/%m/%d-%H:%M:%S')}" + + try: + if task_id(gmp, name): + print(f"Task: {name} exist already") + continue + print("Creating task: " + name) + gmp.create_task( + name=name, comment=comment, config_id=configId, target_id=targetId, hosts_ordering=scanOrder, scanner_id=scannerId, alterable=alterable, schedule_id=scheduleId, alert_ids=alerts + ) + numberTasks = numberTasks + 1 + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, name: {name}") + pass + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read task_csv_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("Host file is empty (exit)") + + return numberTasks + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + #port_list_id="4a4717fe-57d2-11e1-9a26-406186ea4fc5" + + print( + "Creating tasks\n" + ) + + numberTasks = create_tasks( + gmp, + parsed_args.tasks_csv_file, + parsed_args.port_list_id + ) + + numberTasks = str(numberTasks) + print(" [" + numberTasks + "] task(s) created!\n") + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/dummy_def.gmp.py b/scripts/dummy_def.gmp.py new file mode 100644 index 00000000..d53b4f81 --- /dev/null +++ b/scripts/dummy_def.gmp.py @@ -0,0 +1,12 @@ +def alert_id( + gmp: Gmp, + alert_name: str, +): + response_xml = gmp.get_alerts(filter_string="rows=-1, name=" + alert_name) + alerts_xml = response_xml.xpath("alert") + alert_id = "" + + for alert in alerts_xml: + name = "".join(alert.xpath("name/text()")) + alert_id = alert.get("id") + return alert_id diff --git a/scripts/empty-trash.gmp.py b/scripts/empty-trash.gmp.py new file mode 100755 index 00000000..66dbb5ef --- /dev/null +++ b/scripts/empty-trash.gmp.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + + +def main(gmp: Gmp, args: Namespace) -> None: + + print( + "Emptying Trash...\n" + ) + + try: + status_text = gmp.empty_trashcan().xpath("@status_text")[0] + print(status_text) + except: + pass + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/export-csv-report.gmp.py b/scripts/export-csv-report.gmp.py new file mode 100755 index 00000000..807b0100 --- /dev/null +++ b/scripts/export-csv-report.gmp.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# +# Based on the Greenbone export-pdf-report script and modified to +# create csv and return more (all) details. +# Martin Boller +# +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# 2022-11-02 - Martin B +# Added ignore_pagination=True, details=True to get the full report +# + +import sys + +from base64 import b64decode +from pathlib import Path +from argparse import Namespace +from gvm.protocols.gmp import Gmp + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args < 1: + message = """ + This script requests the given report and exports it as a csv + file locally. It requires one parameter after the script name. + + 1. -- ID of the report + + Optional a file name to save the csv in. + + Examples: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/export-csv-report.gmp.py + $ gvm-script --gmp-username admin --gmp-password '0f6fa69b-32bb-453a-9aa4-b8c9e56b3d00' socket export-csv-report.gmp.py b26229cd-94c8-44f8-9cb6-27486a3dedad ./test.csv + """ + print(message) + sys.exit() + + +def main(gmp: Gmp, args: Namespace) -> None: + # check if report id and CSV filename are provided to the script + # argv[0] contains the script name + check_args(args) + + report_id = args.argv[1] + if len(args.argv) == 3: + csv_filename = args.argv[2] + ".csv" + else: + csv_filename = args.argv[1] + ".csv" + + csv_report_format_id = "c1645568-627a-11e3-a660-406186ea4fc5" + + response = gmp.get_report( + report_id=report_id, report_format_id=csv_report_format_id, ignore_pagination=True, details=True + ) + + report_element = response.find("report") + # get the full content of the report element + content = report_element.find("report_format").tail + + if not content: + print( + 'Requested report is empty. Either the report does not contain any ' + ' results or the necessary tools for creating the report are ' + 'not installed.', + file=sys.stderr, + ) + sys.exit(1) + + # convert content to 8-bit ASCII bytes + binary_base64_encoded_csv = content.encode('ascii') + + # decode base64 + binary_csv = b64decode(binary_base64_encoded_csv) + + # write to file and support ~ in filename path + csv_path = Path(csv_filename).expanduser() + + csv_path.write_bytes(binary_csv) + + print('Done. CSV created: ' + str(csv_path)) + + +if __name__ == '__gmp__': + main(gmp, args) + diff --git a/scripts/export-pdf-report.gmp.py b/scripts/export-pdf-report.gmp.py index 3465ee74..3bd0af96 100644 --- a/scripts/export-pdf-report.gmp.py +++ b/scripts/export-pdf-report.gmp.py @@ -1,5 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (C) 2019-2021 Greenbone AG +# +# Based on the Greenbone export-pdf-report script and modified to +# return more (all) details. +# Martin Boller +# +# Copyright (C) 2019-2021 Greenbone Networks GmbH # # SPDX-License-Identifier: GPL-3.0-or-later # @@ -15,6 +20,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# +# 2022-11-02 - Martin B +# Added ignore_pagination=True, details=True to get the full report +# import sys from argparse import Namespace @@ -50,14 +59,14 @@ def main(gmp: Gmp, args: Namespace) -> None: report_id = args.argv[1] if len(args.argv) == 3: - pdf_filename = args.argv[2] + pdf_filename = args.argv[2] + ".pdf" else: pdf_filename = args.argv[1] + ".pdf" pdf_report_format_id = "c402cc3e-b531-11e1-9163-406186ea4fc5" response = gmp.get_report( - report_id=report_id, report_format_id=pdf_report_format_id + report_id=report_id, report_format_id=pdf_report_format_id, ignore_pagination=True, details=True ) report_element = response.find("report") @@ -67,7 +76,7 @@ def main(gmp: Gmp, args: Namespace) -> None: if not content: print( "Requested report is empty. Either the report does not contain any " - " results or the necessary tools for creating the report are " + "results or the necessary tools for creating the report are " "not installed.", file=sys.stderr, ) diff --git a/scripts/export-xml-report.gmp.py b/scripts/export-xml-report.gmp.py new file mode 100755 index 00000000..9e0e377d --- /dev/null +++ b/scripts/export-xml-report.gmp.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# +# Based on the Greenbone export-xml-report script and modified to +# return more (all) details. +# Martin Boller +# +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# 2022-11-02 - Martin B +# Added ignore_pagination=True, details=True to get the full report +# + +import sys +from argparse import Namespace +from base64 import b64decode +from pathlib import Path + +from gvm.protocols.gmp import Gmp + +from gvm.xml import pretty_print + +def check_args(args): + len_args = len(args.script) - 1 + if len_args < 1: + message = """ + This script requests the given report and exports it as a xml + file locally. It requires one parameters after the script name. + + 1. -- ID of the report + + Optional a file name to save the xml in. + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/export-xml-report.gmp.py + """ + print(message) + sys.exit() + + +def main(gmp: Gmp, args: Namespace) -> None: + # check if report id and xml filename are provided to the script + # argv[0] contains the script name + check_args(args) + + report_id = args.argv[1] + if len(args.argv) == 3: + xml_filename = args.argv[2] + ".xml" + else: + xml_filename = args.argv[1] + ".xml" + + xml_report_format_id = "5057e5cc-b825-11e4-9d0e-28d24461215b" + + response = gmp.get_report( + report_id=report_id, report_format_id=xml_report_format_id, ignore_pagination=True, details=True + ) + + report_element = response.find("report") + data = pretty_print(report_element) + # get the full content of the report element + content = report_element.find("report_format").tail + + if not content: + print( + "Requested report is empty. Either the report does not contain any" + " results or the necessary tools for creating the report are " + "not installed.", + file=sys.stderr, + ) + sys.exit(1) + + # convert content to 8-bit ASCII bytes + binary_base64_encoded_xml = content.encode("ascii") + + # decode base64 + binary_xml = b64decode(binary_base64_encoded_xml) + + # write to file and support ~ in filename path + xml_path = Path(xml_filename).expanduser() + + xml_path.write_bytes(data) + + print("Done. xml created: " + str(xml_path)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-alerts.gmp.py b/scripts/list-alerts.gmp.py new file mode 100755 index 00000000..a8ce6e3f --- /dev/null +++ b/scripts/list-alerts.gmp.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_alerts(filter_string="rows=-1") + alerts_xml = response_xml.xpath("alert") + + heading = ["#", "Name", "Id", "Event", "Event type", "Method", "Condition", "In use"] + + rows = [] + numberRows = 0 + + print( + "Listing alerts.\n" + ) + + for alert in alerts_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(alert.xpath("name/text()")) + alert_id = alert.get("id") + alert_condition = "".join(alert.xpath("condition/text()")) + alert_method = "".join(alert.xpath("method/text()")) + alert_event_type = "".join(alert.xpath("event/data/text()")) + alert_event = "".join(alert.xpath("event/text()")) + alert_inuse = "".join(alert.xpath("in_use/text()")) + if alert_inuse == "1": + alert_inuse = "Yes" + else: + alert_inuse = "No" + + rows.append([rowNumber, name, alert_id, alert_event, alert_event_type, alert_method, alert_condition, alert_inuse]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-credentials.gmp.py b/scripts/list-credentials.gmp.py new file mode 100755 index 00000000..65cd4f47 --- /dev/null +++ b/scripts/list-credentials.gmp.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_credentials(filter_string="rows=-1") + credentials_xml = response_xml.xpath("credential") + + heading = ["#", "Id", "Name", "Type", "Insecure use"] + + rows = [] + numberRows = 0 + + print( + "Listing credentials.\n" + ) + + for credential in credentials_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(credential.xpath("name/text()")) + credential_id = credential.get("id") + cred_type = "".join(credential.xpath("type/text()")) + if cred_type.upper() == "UP": + cred_type = "Username + Password (up)" + elif cred_type.upper() == "USK": + cred_type = "Username + SSH Key (usk)" + elif cred_type.upper() == "SMIME": + cred_type = "S/MIME Certificate (smime)" + elif cred_type.upper() == "PGP": + cred_type = "PGP Encryption Key (pgp)" + elif cred_type.upper() == "SNMP": + cred_type = "Simple Network Management Protocol (snmp)" + elif cred_type.upper() == "PW": + cred_type = "Password only (pw)" + cred_insecureuse = "".join(credential.xpath("allow_insecure/text()")) + if cred_insecureuse == "1": + cred_insecureuse = "Yes" + else: + cred_insecureuse = "No" + + rows.append([rowNumber, credential_id, name, cred_type, cred_insecureuse]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-feeds.gmp.py b/scripts/list-feeds.gmp.py new file mode 100755 index 00000000..94a79a37 --- /dev/null +++ b/scripts/list-feeds.gmp.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + +#from gvm.xml import pretty_print + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_feeds() + feeds_xml = response_xml.xpath("feed") + heading = ["#", "Name", "Version", "Status"] + rows = [] + numberRows = 0 +# pretty_print(feeds_xml) + + print( + "Listing feeds and their status.\n" + ) + + for feed in feeds_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + name = "".join(feed.xpath("name/text()")) + version = "".join(feed.xpath("version/text()")) + type = "".join(feed.xpath("type/text()")) + status = "".join(feed.xpath("currently_syncing/timestamp/text()")) + if not status: + status = "Up-to-date..." + else: + status = "Update in progress..." + + + rows.append([rowNumber, name, version, status]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-filters.gmp.py b/scripts/list-filters.gmp.py new file mode 100755 index 00000000..18f69886 --- /dev/null +++ b/scripts/list-filters.gmp.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_filters(filter_string="rows=-1") + filters_xml = response_xml.xpath("filter") + + heading = ["#", "Name", "Id", "Modified", "Type", "Term"] + + rows = [] + numberRows = 0 + + print( + "Listing filters.\n" + ) + + for filter in filters_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(filter.xpath("name/text()")) + modified = "".join(filter.xpath("modification_time/text()")) + term = "".join(filter.xpath("term/text()")) + type = "".join(filter.xpath("type/text()")) + filter_id = filter.get("id") + rows.append([rowNumber, name, filter_id, modified, type, term]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-groups.gmp.py b/scripts/list-groups.gmp.py new file mode 100755 index 00000000..6146981b --- /dev/null +++ b/scripts/list-groups.gmp.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_groups(filter_string="rows=-1") + groups_xml = response_xml.xpath("group") + + heading = ["#", "Name", "Id", "Members"] + + rows = [] + numberRows = 0 + + print( + "Listing groups.\n" + ) + + for group in groups_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(group.xpath("name/text()")) + group_id = group.get("id") + group_members = "".join(group.xpath("users/text()")) + + rows.append([rowNumber, name, group_id, group_members]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-policies.gmp.py b/scripts/list-policies.gmp.py new file mode 100755 index 00000000..10429e6a --- /dev/null +++ b/scripts/list-policies.gmp.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_policies(filter_string="rows=-1") + policies_xml = response_xml.xpath("config") + + heading = ["#", "Name", "Id", "NVT Count"] + + rows = [] + numberRows = 0 + + print( + "Listing compliance policies.\n" + ) + + for policy in policies_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(policy.xpath("name/text()")) + policy_id = policy.get("id") + policy_nvt = "".join(policy.xpath("nvt_count/text()")) + + rows.append([rowNumber, name, policy_id, policy_nvt]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-portlists.gmp.py b/scripts/list-portlists.gmp.py new file mode 100755 index 00000000..4a01857c --- /dev/null +++ b/scripts/list-portlists.gmp.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_port_lists(filter_string="rows=-1") + portlists_xml = response_xml.xpath("port_list") + + heading = ["#", "Name", "Id", "Ports All", "Ports TCP", "Ports UDP"] + + rows = [] + numberRows = 0 + + print( + "Listing portlists.\n" + ) + + for portlist in portlists_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(portlist.xpath("name/text()")) + port_list_id = portlist.get("id") + port_all = "".join(portlist.xpath("port_count/all/text()")) + port_tcp = "".join(portlist.xpath("port_count/tcp/text()")) + port_udp = "".join(portlist.xpath("port_count/udp/text()")) + + rows.append([rowNumber, name, port_list_id, port_all, port_tcp, port_udp]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-report-formats.gmp.py b/scripts/list-report-formats.gmp.py new file mode 100755 index 00000000..93314c37 --- /dev/null +++ b/scripts/list-report-formats.gmp.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_report_formats(details=True, filter_string="rows=-1") + report_formats_xml = response_xml.xpath("report_format") + heading = ["#", "Name", "Id", "Summary"] + rows = [] + numberRows = 0 + + print( + "Listing report formats.\n" + ) + + for report_format in report_formats_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + name = "".join(report_format.xpath("name/text()")) + report_format_id = report_format.get("id") + report_format_summary = "".join(report_format.xpath("summary/text()")) + report_format_description = "".join(report_format.xpath("description/text()")) + + rows.append([rowNumber, name, report_format_id, report_format_summary]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-reports.gmp.py b/scripts/list-reports.gmp.py new file mode 100755 index 00000000..e8cb1e20 --- /dev/null +++ b/scripts/list-reports.gmp.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller 2023-05-15 +# +# run script with e.g. gvm-script --gmp-username username --gmp-password password socket list-reports.gmp.py All +# + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter + +HELP_TEXT = ( + "This script list reports with the status " + "defined on the commandline. Status can be: \n" + "Requested, Queued, Interrupted, Running, or Done \n" + "Note: Case matters. E.g. - done - won't work, but - Done - will" +) + + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 1: + message = """ + This script lists all reports depending on status. + One parameter after the script name is required. + + 1. Status -- Either \"All\", \"Requested\", \"Queued\", \"Interrupted\", \"Running\", \"StopRequested\", \"Stopped\", or \"Done\" + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +socket list-reports.gmp.py Done \n + """ + print(message) + sys.exit() + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "status_cmd", + type=str, + help=("Status: \"All\", \"Queued\", \"Requested\", \"Interrupted\", \"Running\", \"Stop Requested\", \"Stopped\" or \"Done\""), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def list_reports ( + gmp: Gmp, + status: str, +): + str_status = status + if status.upper() == "ALL": + status = "All" + elif status.upper() == "REQUESTED": + str_status = "Requested" + elif status.upper() == "INTERRUPTED": + str_status = "Interrupted" + elif status.upper() == "QUEUED": + str_status = "Queued" + elif status.upper()[:6] == "STOPRE": + str_status = "Stop Requested" + elif status.upper()[:6] == "STOP R": + str_status = "Stop Requested" + elif status.upper() == "DONE": + str_status = "Done" + elif status.upper() == "RUNNING": + str_status = "Running" + elif status.upper() == "STOPPED": + str_status = "Stopped" + else: + str_status="All" + + print("Reports with status: " + str_status + "\n") + + if str_status == "All": + response_xml = gmp.get_reports(ignore_pagination=True, details=True, filter_string="rows=-1") + else: + response_xml = gmp.get_reports(ignore_pagination=True, details=True, filter_string="status=" + str_status + " and sort-reverse=name and rows=-1") + + reports_xml = response_xml.xpath("report") + heading = ["#", "Id", "Creation Time", "Modification Time", "Task Name", "Status", "Progress"] + rows = [] + numberRows = 0 + + for report in reports_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + creation_time = "".join(report.xpath("creation_time/text()")) + #report_name = "".join(report.xpath("name/text()")) # Report name is the same as Creation Time + report_id = report.get("id") + report_task = "".join(report.xpath("task/name/text()")) + mod_time = "".join(report.xpath("modification_time/text()")) + report_status = "".join(report.xpath("report/scan_run_status/text()")) + report_progress = "".join(report.xpath("report/task/progress/text()")) + "%" + rows.append([rowNumber, report_id, creation_time, mod_time, report_task, report_status, report_progress]) + + print(Table(heading=heading, rows=rows)) + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args = args) + + print( + "Listing reports.\n" + ) + + list_reports ( + gmp, + parsed_args.status_cmd + ) + +if __name__ == "__gmp__": + main(gmp, args) + diff --git a/scripts/list-roles.gmp.py b/scripts/list-roles.gmp.py new file mode 100755 index 00000000..eebea991 --- /dev/null +++ b/scripts/list-roles.gmp.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_roles(filter_string="rows=-1") + roles_xml = response_xml.xpath("role") + + heading = ["#", "Name", "Id", "Members"] + + rows = [] + numberRows = 0 + + print( + "Listing roles.\n" + ) + + for role in roles_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(role.xpath("name/text()")) + role_id = role.get("id") + role_members = "".join(role.xpath("users/text()")) + + rows.append([rowNumber, name, role_id, role_members]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-scan-configs.gmp.py b/scripts/list-scan-configs.gmp.py new file mode 100755 index 00000000..6bd66490 --- /dev/null +++ b/scripts/list-scan-configs.gmp.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_scan_configs(filter_string="rows=-1") + scan_configs_xml = response_xml.xpath("config") + + heading = ["#", "Name", "Id", "NVT Count"] + + rows = [] + numberRows = 0 + + print( + "Listing scan configurations.\n" + ) + + for scan_config in scan_configs_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(scan_config.xpath("name/text()")) + scan_config_id = scan_config.get("id") + scan_config_nvt = "".join(scan_config.xpath("nvt_count/text()")) + + rows.append([rowNumber, name, scan_config_id, scan_config_nvt]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-scanners.gmp.py b/scripts/list-scanners.gmp.py new file mode 100755 index 00000000..8c2aebe4 --- /dev/null +++ b/scripts/list-scanners.gmp.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_scanners(filter_string="rows=-1") + scanners_xml = response_xml.xpath("scanner") + + heading = ["#", "Name", "Id", "host"] + + rows = [] + numberRows = 0 + + print( + "Listing scanners.\n" + ) + + for scanner in scanners_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(scanner.xpath("name/text()")) + scanner_id = scanner.get("id") + host = "".join(scanner.xpath("host/text()")) + + rows.append([rowNumber, name, scanner_id, host]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-schedules.gmp.py b/scripts/list-schedules.gmp.py new file mode 100755 index 00000000..fd731d0f --- /dev/null +++ b/scripts/list-schedules.gmp.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_schedules(filter_string="rows=-1") + schedules_xml = response_xml.xpath("schedule") + + heading = ["#", "Name", "Id", "TZ", "iCalendar"] + + rows = [] + numberRows = 0 + + print( + "Listing schedules.\n" + ) + + for schedule in schedules_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(schedule.xpath("name/text()")) + schedule_id = schedule.get("id") + icalendar = "".join(schedule.xpath("icalendar/text()")) + timezone = "".join(schedule.xpath("timezone/text()")) + rows.append([rowNumber, name, schedule_id, timezone, icalendar]) + #print(icalendar) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) + diff --git a/scripts/list-tags.gmp.py b/scripts/list-tags.gmp.py new file mode 100755 index 00000000..ad2e0155 --- /dev/null +++ b/scripts/list-tags.gmp.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_tags(filter_string="rows=-1") + tags_xml = response_xml.xpath("tag") + + heading = ["#", "Name", "Id", "Modified", "Value", "Type", "Count"] + + rows = [] + numberRows = 0 + + print( + "Listing tags.\n" + ) + + for tag in tags_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(tag.xpath("name/text()")) + modified = "".join(tag.xpath("modification_time/text()")) + value = "".join(tag.xpath("value/text()")) + type = "".join(tag.xpath("resources/type/text()")) + count = "".join(tag.xpath("resources/count/total/text()")) + tag_id = tag.get("id") + rows.append([rowNumber, name, tag_id, modified, value, type, count]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-targets.gmp.py b/scripts/list-targets.gmp.py new file mode 100755 index 00000000..5ccfbfaf --- /dev/null +++ b/scripts/list-targets.gmp.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_targets(filter_string="rows=-1") + targets_xml = response_xml.xpath("target") + + heading = ["#", "Name", "Id", "Count", "SSH Credential", "SMB Cred", "ESXi Cred", "SNMP Cred", "Alive test"] + + rows = [] + numberRows = 0 + + print( + "Listing targets.\n" + ) + + for target in targets_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(target.xpath("name/text()")) + maxhosts = "".join(target.xpath("max_hosts/text()")) + sshcred = "".join(target.xpath("ssh_credential/name/text()")) + smbcred = "".join(target.xpath("smb_credential/name/text()")) + esxicred = "".join(target.xpath("esxi_credential/name/text()")) + snmpcred = "".join(target.xpath("snmp_credential/name/text()")) + target_id = target.get("id") + alive_test = "".join(target.xpath("alive_tests/text()")) + rows.append([rowNumber, name, target_id, maxhosts, sshcred, smbcred, esxicred, snmpcred, alive_test]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-tasks.gmp.py b/scripts/list-tasks.gmp.py index a5f2bc1e..05ebe5fa 100644 --- a/scripts/list-tasks.gmp.py +++ b/scripts/list-tasks.gmp.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (C) 2019-2021 Greenbone AG +# Copyright (C) 2019-2021 Greenbone Networks GmbH # # SPDX-License-Identifier: GPL-3.0-or-later # @@ -15,6 +15,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# from argparse import Namespace @@ -26,19 +31,31 @@ def main(gmp: Gmp, args: Namespace) -> None: # pylint: disable=unused-argument - response_xml = gmp.get_tasks() + response_xml = gmp.get_tasks(details=True, filter_string="rows=-1") tasks_xml = response_xml.xpath("task") - heading = ["ID", "Name", "Severity"] + heading = ["#", "Name", "Id", "Target", "Scanner", "Scan Order", "Severity"] rows = [] + numberRows = 0 + + print( + "Listing tasks.\n" + ) for task in tasks_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + name = "".join(task.xpath("name/text()")) task_id = task.get("id") + targetname = "".join(task.xpath("target/name/text()")) + scanner = "".join(task.xpath("scanner/name/text()")) severity = "".join(task.xpath("last_report/report/severity/text()")) - - rows.append([task_id, name, severity]) + order = "".join(task.xpath("hosts_ordering/text()")) + rows.append([rowNumber, name, task_id, targetname, scanner, order, severity]) print(Table(heading=heading, rows=rows)) diff --git a/scripts/list-tickets.gmp.py b/scripts/list-tickets.gmp.py new file mode 100755 index 00000000..84e7bd15 --- /dev/null +++ b/scripts/list-tickets.gmp.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_tickets(filter_string="rows=-1") + tickets_xml = response_xml.xpath("ticket") + + heading = ["#", "Name", "Host", "Task", "Status", "Note"] + + rows = [] + numberRows = 0 + + print( + "Listing tickets.\n" + ) + + for ticket in tickets_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(ticket.xpath("name/text()")) + ticket_id = ticket.get("id") + ticket_status = "".join(ticket.xpath("status/text()")) + ticket_task = "".join(ticket.xpath("task/name/text()")) + ticket_host = "".join(ticket.xpath("host/text()")) + if ticket_status.upper() == "OPEN": + ticket_note = "".join(ticket.xpath("open_note/text()")) + elif ticket_status.upper() == "FIXED": + ticket_note = "".join(ticket.xpath("fixed_note/text()")) + elif ticket_status.upper() == "CLOSED": + ticket_note = "".join(ticket.xpath("closed_note/text()")) + + rows.append([rowNumber, name, ticket_host, ticket_task, ticket_status, ticket_note]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/list-users.gmp.py b/scripts/list-users.gmp.py new file mode 100755 index 00000000..99c3e906 --- /dev/null +++ b/scripts/list-users.gmp.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=unused-argument + + response_xml = gmp.get_users(filter_string="rows=-1") + users_xml = response_xml.xpath("user") + + heading = ["#", "Name", "Id", "Role", "Groups"] + + rows = [] + numberRows = 0 + + print( + "Listing users.\n" + ) + + for user in users_xml: + # Count number of reports + numberRows = numberRows + 1 + # Cast/convert to text to show in list + rowNumber = str(numberRows) + + name = "".join(user.xpath("name/text()")) + user_id = user.get("id") + user_role = "".join(user.xpath("role/name/text()")) + user_groups = "".join(user.xpath("groups/group/name/text()")) + + rows.append([rowNumber, name, user_id, user_role, user_groups]) + + print(Table(heading=heading, rows=rows)) + + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/start-scans-from-csv.py b/scripts/start-scans-from-csv.py new file mode 100755 index 00000000..a10e5b6d --- /dev/null +++ b/scripts/start-scans-from-csv.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on Greenbone sample scripts +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket start-scans-from-csv.gmp.py startscans.csv +# + +import sys +import time +import csv +import json + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls task names from a csv file and starts the tasks listed in every row. \n" +) + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 2: + message = """ + This script pulls tasks from a csv file and creates a \ +task for each row in the csv file. + One parameter after the script name is required. + + 1. -- csv file containing names and secrets required for scan tasks + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/start_tasks_from_csv.gmp.py \ + + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "task_file", + type=str, + help=("CSV File containing tasks"), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def task_id( + gmp: Gmp, + task_name: str, +): + response_xml = gmp.get_tasks(filter_string="rows=-1, not status=Running and " + "not status=Requested and not " + "status=Queued " + "and name=" + task_name) + tasks_xml = response_xml.xpath("task") + task_id = "" + + for task in tasks_xml: + name = "".join(task.xpath("name/text()")) + task_id = task.get("id") + #print("Requesting start of task: " + task_name + " Task UUID: " + task_id) + return task_id + +def start_tasks( + gmp: Gmp, + task_file: Path, +): + try: + numbertasks = 0 + with open(task_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + try: + for row in content: #loop through each row + if len(row) == 0: + continue + task_start = task_id(gmp, row[0]) + if task_start: + numbertasks = numbertasks + 1 + print(f"Starting task name: {row[0]} with uuid: {task_start} ...") + status_text = gmp.start_task(task_start).xpath( + "@status_text" + )[0] + print(status_text) + else: + print("Task " + row[0] + " is either in status Requested, Queued, Running, or does not exist on this system.\n") + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, task: {task_start}") + pass + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read task_file: {str(e)} (exit)") + + return numbertasks + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Starting tasks.\n" + ) + + numbertasks = start_tasks( + gmp, + parsed_args.task_file, + ) + + numbertasks = str(numbertasks) + print(" \n [" + numbertasks + "] task(s)/scan(s) started!\n") + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/stop-all-scans.gmp.py b/scripts/stop-all-scans.gmp.py new file mode 100755 index 00000000..2feffc79 --- /dev/null +++ b/scripts/stop-all-scans.gmp.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2019-2021 Greenbone Networks GmbH +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Based on other Greenbone scripts +# +# Martin Boller +# + +from argparse import Namespace + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import Table + +def stop_tasks(gmp: Gmp) -> None: + tasks = gmp.get_tasks( + filter_string="rows=-1 status=Running or status=Requested or status=Queued" + ) + try: + for task_id in tasks.xpath("task/@id"): + print(f"Stopping task {task_id} ... ") + gmp.stop_task(task_id).xpath( + "@status_text" + )[0] + print(status_text) + except: + pass + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + print( + "This script stops all tasks on the system.\n" + ) + + stop_tasks(gmp) + +if __name__ == "__gmp__": + main(gmp, args) diff --git a/scripts/stop-scans-from-csv.py b/scripts/stop-scans-from-csv.py new file mode 100755 index 00000000..c80ee3c5 --- /dev/null +++ b/scripts/stop-scans-from-csv.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# +# Loosely based on Greenbone sample scripts +# As provided by Greenbone in the gvm-tools repo +# +# Martin Boller +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Run with gvm-script --gmp-username admin-user --gmp-password password socket start-scans-from-csv.gmp.py startscans.csv +# + +import sys +import time +import csv +import json + +from argparse import ArgumentParser, Namespace, RawTextHelpFormatter +from pathlib import Path +from typing import List +from gvm.errors import GvmResponseError + +from gvm.protocols.gmp import Gmp + +from gvmtools.helper import error_and_exit + +HELP_TEXT = ( + "This script pulls task names from a csv file and starts the tasks listed in every row. \n" +) + +def check_args(args): + len_args = len(args.script) - 1 + if len_args != 2: + message = """ + This script pulls tasks from a csv file and creates a \ +task for each row in the csv file. + One parameter after the script name is required. + + 1. -- csv file containing names and secrets required for scan tasks + + Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/stop_tasks_from_csv.gmp.py \ + + """ + print(message) + sys.exit() + + +def parse_args(args: Namespace) -> Namespace: # pylint: disable=unused-argument + """Parsing args ...""" + + parser = ArgumentParser( + prefix_chars="+", + add_help=False, + formatter_class=RawTextHelpFormatter, + description=HELP_TEXT, + ) + + parser.add_argument( + "+h", + "++help", + action="help", + help="Show this help message and exit.", + ) + + parser.add_argument( + "task_file", + type=str, + help=("CSV File containing tasks"), + ) + script_args, _ = parser.parse_known_args(args) + return script_args + +def task_id( + gmp: Gmp, + task_name: str, +): + response_xml = gmp.get_tasks(filter_string="rows=-1, status=Running " + "or status=Requested " + "or status=Queued " + "and name=" + task_name) + tasks_xml = response_xml.xpath("task") + task_id = "" + + for task in tasks_xml: + name = "".join(task.xpath("name/text()")) + task_id = task.get("id") + #print("Requesting stop of task: " + task_name + " Task UUID: " + task_id) + return task_id + +def stop_tasks( + gmp: Gmp, + task_file: Path, +): + try: + numbertasks = 0 + with open(task_file, encoding="utf-8") as csvFile: + content = csv.reader(csvFile, delimiter=',') #read the data + try: + for row in content: #loop through each row + if len(row) == 0: + continue + task_stop = task_id(gmp, row[0]) + if task_stop: + numbertasks = numbertasks + 1 + print(f"Stopping task name: {row[0]} with uuid: {task_stop} ...") + status_text = gmp.stop_task(task_stop).xpath( + "@status_text" + )[0] + print(status_text) + else: + print("Task " + row[0] + " is either in status Stopped, Stop Requested, or does not exist on this system.\n") + except GvmResponseError as gvmerr: + print(f"{gvmerr=}, task: {task_stop}") + pass + csvFile.close() #close the csv file + + except IOError as e: + error_and_exit(f"Failed to read task_file: {str(e)} (exit)") + + if len(row) == 0: + error_and_exit("tasks file is empty (exit)") + + return numbertasks + +def main(gmp: Gmp, args: Namespace) -> None: + # pylint: disable=undefined-variable + if args.script: + args = args.script[1:] + + parsed_args = parse_args(args=args) + + print( + "Stopping tasks.\n" + ) + + numbertasks = stop_tasks( + gmp, + parsed_args.task_file, + ) + + numbertasks = str(numbertasks) + print(" \n [" + numbertasks + "] task(s)/scan(s) stopped!\n") + +if __name__ == "__gmp__": + main(gmp, args) From 84379cb13ddf8f1116506ec0acf2ca255a6fae06 Mon Sep 17 00:00:00 2001 From: Martin Boller Date: Fri, 3 May 2024 19:50:21 +0200 Subject: [PATCH 2/3] Update scripts/create-alerts-from-csv.gmp.py Co-authored-by: Jaspar S. --- scripts/create-alerts-from-csv.gmp.py | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/scripts/create-alerts-from-csv.gmp.py b/scripts/create-alerts-from-csv.gmp.py index 2e5e8b1f..3a4633dd 100755 --- a/scripts/create-alerts-from-csv.gmp.py +++ b/scripts/create-alerts-from-csv.gmp.py @@ -1,24 +1,10 @@ -# -*- coding: utf-8 -*- -# -# Loosely based on Greenbone sample scripts -# As provided by Greenbone in the gvm-tools repo -# -# Martin Boller +# SPDX-FileCopyrightText: 2024 Martin Boller # # SPDX-License-Identifier: GPL-3.0-or-later # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . + +# Loosely based on Greenbone sample scripts +# As provided by Greenbone in the gvm-tools repo # # Run with gvm-script --gmp-username admin-user --gmp-password password socket create-alerts-from-csv.gmp.py alerts.csv # From 6c6daca975d388433009bc5da093e1ade6576bc1 Mon Sep 17 00:00:00 2001 From: Martin Boller Date: Fri, 3 May 2024 19:50:48 +0200 Subject: [PATCH 3/3] Update scripts/create-alerts-from-csv.gmp.py Co-authored-by: Jaspar S. --- scripts/create-alerts-from-csv.gmp.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/create-alerts-from-csv.gmp.py b/scripts/create-alerts-from-csv.gmp.py index 3a4633dd..bffe009a 100755 --- a/scripts/create-alerts-from-csv.gmp.py +++ b/scripts/create-alerts-from-csv.gmp.py @@ -223,9 +223,7 @@ def main(gmp: Gmp, args: Namespace) -> None: parsed_args = parse_args(args=args) - print( - "Creating alerts.\n" - ) + print("Creating alerts.\n") numberalerts = create_alerts( gmp,