File: cli.py

package info (click to toggle)
gvm-tools 25.4.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,480 kB
  • sloc: python: 10,611; xml: 445; makefile: 27
file content (150 lines) | stat: -rw-r--r-- 4,338 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2018-2024 Greenbone AG
#
# 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 <http://www.gnu.org/licenses/>.

import logging
import sys
import time

from gvm.errors import GvmError
from gvm.protocols.gmp import Gmp
from gvm.protocols.latest import Osp
from gvm.transforms import CheckCommandTransform
from gvm.xml import parse_xml, pretty_print

from gvmtools.helper import authenticate, do_not_run_as_root
from gvmtools.parser import (
    PROTOCOL_GMP,
    PROTOCOL_OSP,
    create_connection,
    create_parser,
)

logger = logging.getLogger(__name__)

HELP_TEXT = """
    Command line tool to access services via GMP (Greenbone Management Protocol) and OSP (Open Scanner Protocol)

    Examples:
      gvm-cli socket --help
      gvm-cli tls --help
      gvm-cli ssh --help

      gvm-cli socket --xml "<get_version/>"
      gvm-cli socket --xml "<commands><authenticate><credentials><username>myuser</username><password>mypass</password></credentials></authenticate><get_tasks/></commands>"
      gvm-cli socket --gmp-username foo --gmp-password foo myfile.xml

    The protocol specifications for GMP and OSP are available at:
      https://docs.greenbone.net/index.html#api_documentation"""  # noqa: E501


def _load_infile(filename=None):
    if not filename:
        return None

    with open(filename, encoding="utf-8") as f:
        return f.read()


def main():
    do_not_run_as_root()

    parser = create_parser(description=HELP_TEXT, logfilename="gvm-cli.log")

    parser.add_protocol_argument()

    parser.add_argument("-X", "--xml", help="XML request to send")
    parser.add_argument(
        "-r", "--raw", help="Return raw XML", action="store_true", default=False
    )
    parser.add_argument(
        "--pretty",
        help="Pretty format the returned xml",
        action="store_true",
        default=False,
    )
    parser.add_argument(
        "--duration", action="store_true", help="Measure command execution time"
    )
    parser.add_argument(
        "infile", nargs="?", help="File to read XML commands from."
    )

    args = parser.parse_args()

    # If timeout value is -1, then the socket has no timeout for this session
    if args.timeout == -1:
        args.timeout = None

    if args.xml is not None:
        xml = args.xml
    else:
        try:
            xml = _load_infile(args.infile)
        except IOError as e:
            print(e, file=sys.stderr)
            sys.exit(1)

    # If no command was given, program asks for one
    if len(xml) == 0:
        xml = input()

    try:
        parse_xml(xml)
    except GvmError as e:
        print(e, file=sys.stderr)
        sys.exit(1)

    connection = create_connection(**vars(args))

    if args.raw:
        transform = None
    else:
        transform = CheckCommandTransform()

    if args.protocol == PROTOCOL_OSP:
        protocol_class = Osp
    else:
        protocol_class = Gmp

    try:
        with protocol_class(connection, transform=transform) as protocol:
            if args.protocol == PROTOCOL_GMP:
                # Ask for password if none are given
                authenticate(protocol, args.gmp_username, args.gmp_password)

            if args.duration:
                starttime = time.time()

            result = protocol.send_command(xml)

            if args.duration:
                duration = time.time() - starttime
                print(f"Elapsed time: {duration} seconds")
            elif args.pretty:
                pretty_print(result)
            else:
                print(result)

    except Exception as e:  # pylint: disable=broad-except
        logger.error(e)
        sys.exit(1)
    sys.exit(0)


if __name__ == "__main__":
    main()