greenbone /
gvm-tools
| 1 | # -*- coding: utf-8 -*- |
||
| 2 | # Copyright (C) 2018 inovex GmbH |
||
| 3 | # Copyright (C) 2019-2021 Greenbone Networks GmbH |
||
| 4 | # |
||
| 5 | # SPDX-License-Identifier: GPL-3.0-or-later |
||
| 6 | # |
||
| 7 | # This program is free software: you can redistribute it and/or modify |
||
| 8 | # it under the terms of the GNU General Public License as published by |
||
| 9 | # the Free Software Foundation, either version 3 of the License, or |
||
| 10 | # (at your option) any later version. |
||
| 11 | # |
||
| 12 | # This program is distributed in the hope that it will be useful, |
||
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 15 | # GNU General Public License for more details. |
||
| 16 | # |
||
| 17 | # You should have received a copy of the GNU General Public License |
||
| 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
| 19 | |||
| 20 | import sys |
||
| 21 | |||
| 22 | |||
| 23 | def check_args(args): |
||
| 24 | len_args = len(args.script) - 1 |
||
| 25 | message = """ |
||
| 26 | This script makes an alert scan |
||
| 27 | It needs two parameters after the script name. |
||
| 28 | |||
| 29 | 1. <sender_email> -- E-Mail of the sender |
||
| 30 | 2. <receiver_email> -- E-Mail of the receiver |
||
| 31 | |||
| 32 | Example: |
||
| 33 | $ gvm-script --gmp-username name --gmp-password pass \ |
||
| 34 | ssh --hostname <gsm> scripts/start-multiple-alert-scan.gmp.py <sender_email> <receiver_email> |
||
| 35 | """ |
||
| 36 | if len_args != 2: |
||
| 37 | print(message) |
||
| 38 | sys.exit() |
||
| 39 | |||
| 40 | |||
| 41 | # returns a list containing all port_list names |
||
| 42 | def get_port_list_names(gmp): |
||
| 43 | res = gmp.get_port_lists() |
||
| 44 | port_names_list = [""] |
||
| 45 | for name in res.findall("port_list/name"): |
||
| 46 | port_names_list.append(str(name.text)) |
||
| 47 | return port_names_list |
||
| 48 | |||
| 49 | |||
| 50 | def get_config(gmp, debug=False): |
||
| 51 | # get all configs of the openvas instance |
||
| 52 | res = gmp.get_configs() |
||
| 53 | |||
| 54 | # configurable template |
||
| 55 | template = "fast" |
||
| 56 | |||
| 57 | # match the config abbreviation to accepted config names |
||
| 58 | config_list = [ |
||
| 59 | 'Full and fast', |
||
| 60 | 'Full and fast ultimate', |
||
| 61 | 'Full and very deep', |
||
| 62 | 'Full and very deep ultimate', |
||
| 63 | 'System Discovery', |
||
| 64 | ] |
||
| 65 | template_abbreviation_mapper = { |
||
| 66 | "fast": config_list[0], |
||
| 67 | "fast-ulti": config_list[1], |
||
| 68 | "deep": config_list[2], |
||
| 69 | "deep-ulti": config_list[3], |
||
| 70 | "discovery": config_list[4], |
||
| 71 | } |
||
| 72 | config_id = "-" |
||
| 73 | for conf in res.xpath('config'): |
||
| 74 | cid = conf.xpath('@id')[0] |
||
| 75 | name = conf.xpath('name/text()')[0] |
||
| 76 | |||
| 77 | # get the config id of the desired template |
||
| 78 | if template_abbreviation_mapper.get(template, "-") == name: |
||
| 79 | config_id = cid |
||
| 80 | if debug: |
||
| 81 | print("%s: %s" % (name, config_id)) |
||
| 82 | break |
||
| 83 | # check for existence of the desired config |
||
| 84 | if config_id == "-": |
||
| 85 | print( |
||
| 86 | "error: could not recognize template '%s'\n" |
||
| 87 | "valid template names are: %s\n" % (template, config_list) |
||
| 88 | ) |
||
| 89 | exit() |
||
| 90 | |||
| 91 | return config_id |
||
| 92 | |||
| 93 | |||
| 94 | def get_target(gmp, debug=False): |
||
| 95 | # find a targetName |
||
| 96 | targets = gmp.get_targets() |
||
| 97 | |||
| 98 | counter = 0 |
||
| 99 | exists = True |
||
| 100 | |||
| 101 | # iterate over existing targets and find a vacant targetName |
||
| 102 | while exists: |
||
| 103 | exists = False |
||
| 104 | target_name = "targetName%s" % str(counter) |
||
| 105 | for target in targets.xpath('target'): |
||
| 106 | name = target.xpath('name/text()')[0] |
||
| 107 | if name == target_name: |
||
| 108 | exists = True |
||
| 109 | break |
||
| 110 | counter += 1 |
||
| 111 | |||
| 112 | if debug: |
||
| 113 | print("target name: %s" % target_name) |
||
| 114 | |||
| 115 | # iterate over existing port lists and find a vacant name |
||
| 116 | new_port_list_name = "portlistName" |
||
| 117 | counter = 0 |
||
| 118 | |||
| 119 | while True: |
||
| 120 | portlist_name = '%s%s' % (new_port_list_name, str(counter)) |
||
| 121 | if portlist_name not in get_port_list_names(gmp): |
||
| 122 | break |
||
| 123 | counter += 1 |
||
| 124 | |||
| 125 | # configurable port string |
||
| 126 | port_string = "T:80-80" |
||
| 127 | # create port list |
||
| 128 | portlist = gmp.create_port_list(portlist_name, port_string) |
||
| 129 | portlist_id = portlist.xpath('@id')[0] |
||
| 130 | if debug: |
||
| 131 | print("Portlist-name:\t%s" % str(portlist_name)) |
||
| 132 | print("Portlist-id:\t%s" % str(portlist_id)) |
||
| 133 | |||
| 134 | # configurable hosts |
||
| 135 | hosts = ["localhost"] |
||
| 136 | |||
| 137 | # integrate port list id into create_target |
||
| 138 | res = gmp.create_target(target_name, hosts=hosts, port_list_id=portlist_id) |
||
| 139 | return res.xpath('@id')[0] |
||
| 140 | |||
| 141 | |||
| 142 | def get_alerts(gmp, sender_email, recipient_email, debug=False): |
||
| 143 | # configurable alert name |
||
| 144 | alert_name = recipient_email |
||
| 145 | |||
| 146 | # create alert if necessary |
||
| 147 | alert_object = gmp.get_alerts(filter='name=%s' % alert_name) |
||
| 148 | alert_id = None |
||
| 149 | alert = alert_object.xpath('alert') |
||
| 150 | View Code Duplication | if len(alert) == 0: |
|
| 151 | gmp.create_alert( |
||
| 152 | alert_name, |
||
| 153 | event=gmp.types.AlertEvent.TASK_RUN_STATUS_CHANGED, |
||
| 154 | event_data={'status': 'Done'}, |
||
| 155 | condition=gmp.types.AlertCondition.ALWAYS, |
||
| 156 | method=gmp.types.AlertMethod.EMAIL, |
||
| 157 | method_data={ |
||
| 158 | """Task '$n': $e |
||
| 159 | |||
| 160 | After the event $e, |
||
| 161 | the following condition was met: $c |
||
| 162 | |||
| 163 | This email escalation is configured to attach report format '$r'. |
||
| 164 | Full details and other report formats are available on the scan engine. |
||
| 165 | |||
| 166 | $t |
||
| 167 | |||
| 168 | Note: |
||
| 169 | This email was sent to you as a configured security scan escalation. |
||
| 170 | Please contact your local system administrator if you think you |
||
| 171 | should not have received it. |
||
| 172 | """: "message", |
||
| 173 | "2": "notice", |
||
| 174 | sender_email: "from_address", |
||
| 175 | "[OpenVAS-Manager] Task": "subject", |
||
| 176 | "c402cc3e-b531-11e1-9163-406186ea4fc5": "notice_attach_format", |
||
| 177 | recipient_email: "to_address", |
||
| 178 | }, |
||
| 179 | ) |
||
| 180 | alert_object = gmp.get_alerts(filter='name=%s' % recipient_email) |
||
| 181 | alert = alert_object.xpath('alert') |
||
| 182 | alert_id = alert[0].get('id', 'no id found') |
||
| 183 | else: |
||
| 184 | alert_id = alert[0].get('id', 'no id found') |
||
| 185 | if debug: |
||
| 186 | print("alert_id: %s" % str(alert_id)) |
||
| 187 | |||
| 188 | # second configurable alert name |
||
| 189 | alert_name2 = "%s-2" % recipient_email |
||
| 190 | |||
| 191 | # create second alert if necessary |
||
| 192 | alert_object2 = gmp.get_alerts(filter='name=%s' % alert_name2) |
||
| 193 | alert_id2 = None |
||
| 194 | alert2 = alert_object2.xpath('alert') |
||
| 195 | View Code Duplication | if len(alert2) == 0: |
|
| 196 | gmp.create_alert( |
||
| 197 | alert_name2, |
||
| 198 | event=gmp.types.AlertEvent.TASK_RUN_STATUS_CHANGED, |
||
| 199 | event_data={'status': 'Done'}, |
||
| 200 | condition=gmp.types.AlertCondition.ALWAYS, |
||
| 201 | method=gmp.types.AlertMethod.EMAIL, |
||
| 202 | method_data={ |
||
| 203 | """Task '$n': $e |
||
| 204 | |||
| 205 | After the event $e, |
||
| 206 | the following condition was met: $c |
||
| 207 | |||
| 208 | This email escalation is configured to attach report format '$r'. |
||
| 209 | Full details and other report formats are available on the scan engine. |
||
| 210 | |||
| 211 | $t |
||
| 212 | |||
| 213 | Note: |
||
| 214 | This email was sent to you as a configured security scan escalation. |
||
| 215 | Please contact your local system administrator if you think you |
||
| 216 | should not have received it. |
||
| 217 | """: "message", |
||
| 218 | "2": "notice", |
||
| 219 | sender_email: "from_address", |
||
| 220 | "[OpenVAS-Manager] Task": "subject", |
||
| 221 | recipient_email: "to_address", |
||
| 222 | }, |
||
| 223 | ) |
||
| 224 | alert_object2 = gmp.get_alerts(filter='name=%s' % recipient_email) |
||
| 225 | alert2 = alert_object2.xpath('alert') |
||
| 226 | alert_id2 = alert2[0].get('id', 'no id found') |
||
| 227 | else: |
||
| 228 | alert_id2 = alert2[0].get('id', 'no id found') |
||
| 229 | if debug: |
||
| 230 | print("alert_id2: %s" % str(alert_id2)) |
||
| 231 | |||
| 232 | return (alert_id, alert_id2) |
||
| 233 | |||
| 234 | |||
| 235 | def get_scanner(gmp): |
||
| 236 | res = gmp.get_scanners() |
||
| 237 | scanner_ids = res.xpath('scanner/@id') |
||
| 238 | return scanner_ids[1] # default scanner |
||
| 239 | |||
| 240 | |||
| 241 | def create_and_start_task( |
||
| 242 | gmp, config_id, target_id, scanner_id, alerts, debug=False |
||
| 243 | ): |
||
| 244 | # Create the task |
||
| 245 | tasks = gmp.get_tasks(filter="name~ScanDoneMultipleAlert") |
||
| 246 | task_name = "ScanDoneMultipleAlert{0}".format(len(tasks.xpath('tasks/@id'))) |
||
| 247 | task_comment = "test comment" |
||
| 248 | res = gmp.create_task( |
||
| 249 | task_name, |
||
| 250 | config_id, |
||
| 251 | target_id, |
||
| 252 | scanner_id, |
||
| 253 | alert_ids=alerts, |
||
| 254 | comment=task_comment, |
||
| 255 | ) |
||
| 256 | # Start the task |
||
| 257 | task_id = res.xpath('@id')[0] |
||
| 258 | gmp.start_task(task_id) |
||
| 259 | |||
| 260 | print('Task started: %s' % task_name) |
||
| 261 | |||
| 262 | if debug: |
||
| 263 | # Stop the task (for performance reasons) |
||
| 264 | gmp.stop_task(task_id) |
||
| 265 | print('Task stopped') |
||
| 266 | |||
| 267 | |||
| 268 | def main(gmp, args): |
||
| 269 | # pylint: disable=undefined-variable |
||
| 270 | |||
| 271 | check_args(args) |
||
| 272 | |||
| 273 | sender_email = args.script[1] |
||
| 274 | recipient_email = args.script[2] |
||
| 275 | |||
| 276 | config_id = get_config(gmp) |
||
| 277 | target_id = get_target(gmp) |
||
| 278 | alerts = get_alerts(gmp, sender_email, recipient_email) |
||
| 279 | scanner_id = get_scanner(gmp) |
||
| 280 | |||
| 281 | create_and_start_task(gmp, config_id, target_id, scanner_id, alerts) |
||
| 282 | |||
| 283 | print("\nScript finished\n") |
||
| 284 | |||
| 285 | |||
| 286 | if __name__ == '__gmp__': |
||
| 287 | main(gmp, args) |
||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
Comprehensibility
Best Practice
introduced
by
|
|||
| 288 |