Usage

Introduction

To communicate with a remote server via one of the GVM protocols it is required to decide which transport protocol should be used for the connection. Currently two protocols – namely GMP and OSP – and three connection types – namely TLS, SSH and Unix domain socket – are available.

Using GMP

The Greenbone Management Protocol (GMP) is the protocol implemented by the Greenbone Vulnerability Manager Daemon – gvmd. It is also used by the Greenbone Security Assistant Daemon to request all of its information from gvmd.

Making a Simple Request

To create a request, a connection type has to be chosen. The decision depends on the location and configuration of the remote gvmd server. For local communication Unix domain socket fits best. The simplest command is to request the GMP version used by the remote gvmd.

Step by Step

The following shows the process of a simple request in more detail.

  1. Import the necessary classes:

from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
  1. Specify the path to the Unix domain socket in the file system:

Note

If gvmd is provided by a package of the distribution, it should be /run/gvmd/gvmd.sock. If gvmd was built from source and did not set a prefix, the default path can be used by setting path = None.

path = '/run/gvmd/gvmd.sock'
  1. Create a connection and a gmp object:

connection = UnixSocketConnection(path=path)
  1. Establish a connection to be able to make a request on gvmd. To automatically connect and disconnect, a Python with statement should be used.

Note

By default all request methods of the gmp object return the response as UTF-8 encoded string.

  1. Obtain the protocol version of the gvmd by printing the response of the unprivileged command *get_version*:

with Gmp(connection=connection) as gmp:
    print(gmp.get_version())

Full Example

from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp

# path to unix socket
path = '/run/gvmd/gvmd.sock'
connection = UnixSocketConnection(path=path)

# using the with statement to automatically connect and disconnect to gvmd
with Gmp(connection=connection) as gmp:
    # get the response message returned as a utf-8 encoded string
    response = gmp.get_version()

    # print the response message
    print(response)

On success the response will look as follows:

<get_version_response status="200" status_text="OK"><version>9.0</version></get_version_response>

Privileged Request

Most requests to gvmd require permissions to access data. Therefore it is required to authenticate against gvmd.

Step by Step

  1. Import the necessary classes:

from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
  1. Create a connection:

path = '/run/gvmd/gvmd.sock'
connection = UnixSocketConnection(path=path)
  1. In this case, an Etree Element should be obtained from the response to be able to extract specific information.

    To do so, pass a transform to the Gmp constructor. Additionally, a GvmError should be raised if the status of the response was not ok. Therefore choose a EtreeCheckCommandTransform:

from gvm.transforms import EtreeCheckCommandTransform

transform = EtreeCheckCommandTransform()

Note

By choosing a EtreeCheckCommandTransform it is ensured that calling a privileged command always fails, e.g. calling

with Gmp(connection=connection, transform=transform) as gmp:
   gmp.get_task()

without being authenticated will throw an error now.

  1. Set a user name and a password for authentication:

username = 'foo'
password = 'bar'
  1. Create a connection, do the authentication, request all tasks with ‘weekly’ in their name and list their full names:

from gvm.errors import GvmError

try:
    with Gmp(connection=connection, transform=transform) as gmp:
        gmp.authenticate(username, password)

        tasks = gmp.get_tasks(filter_string='name~weekly')

        for task in tasks.xpath('task'):
            print(task.find('name').text)

except GvmError as e:
    print('An error occurred', e)

Full Example

import sys

from gvm.connections import UnixSocketConnection
from gvm.errors import GvmError
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeCheckCommandTransform

path = '/run/gvmd/gvmd.sock'
connection = UnixSocketConnection(path=path)
transform = EtreeCheckCommandTransform()

username = 'foo'
password = 'bar'

try:
    tasks = []

    with Gmp(connection=connection, transform=transform) as gmp:
        gmp.authenticate(username, password)

        tasks = gmp.get_tasks(filter_string='name~weekly')

        for task in tasks.xpath('task'):
            print(task.find('name').text)

except GvmError as e:
    print('An error occurred', e, file=sys.stderr)

Using OSP

The Open Scanner Protocol (OSP) is a communication protocol implemented by a base class for scanner wrappers Open Scanner Protocol Daemon – ospd. OSP creates a unified interface for different security scanners and makes their control flow and scan results consistently available under the Greenbone Vulnerability Manager Daemon – gvmd. In many ways, OSP is similar to Greenbone Management Protocol (GMP): XML-based, stateless and with a non-permanent connection.

Making a Simple Request

To create a request you have to choose a connection type. The decision depends on the location and configuration of the remote ospd-wrapper server. For local communication Unix domain socket fits best, but also a secure TLS connection is possible. The simplest command is to request the server version.

Step by Step

  1. Import the necessary classes:

from gvm.connections import UnixSocketConnection
from gvm.protocols.latest import Osp
  1. The path to the Unix domain socket in the file system is given during the start of the ospd-wrapper.

    Specify the path to the Unix domain socket in the file system:

path = '/tmp/ospd-wrapper.sock'
  1. Create a connection and an osp object:

connection = UnixSocketConnection(path=path)
osp = Osp(connection=connection)
  1. Establish a connection to be able to make a request on ospd-wrapper. To automatically connect and disconnect, a Python with statement should be used.

Note

By default all request methods of the osp object return the response as UTF-8 encoded string.

  1. Obtain the OSP protocol version, the ospd base implementation class and the ospd-wrapper server version by printing the response of the command get_version:

with osp:
    print(osp.get_version())

Full Example

from gvm.connections import UnixSocketConnection
from gvm.protocols.latest import Osp

# path to unix socket
path = '/var/run/ospd-wrapper.sock'
connection = UnixSocketConnection(path=path)
osp = Osp(connection=connection)

# using the with statement to automatically connect and disconnect to ospd
with osp:
    # get the response message returned as a utf-8 encoded string
    response = osp.get_version()

    # print the response message
    print(response)

On success the response will look as follows:

<get_version_response status="200" status_text="OK"><protocol><name>OSP</name><version>1.2</version></protocol><daemon><name>OSPd</name><version>1.4b1</version></daemon><scanner><name>some-wrapper</name><version>Wrapper 6.0beta+2</version></scanner></get_version_response>

Debugging

Sometimes networking setups can be complex and hard to follow. Connections may be aborted randomly or an invalid command may have arrived at the server side. Because of this, it may be necessary to debug the connection handling and especially the protocol commands.

python-gvm uses the logging package internally. To enable a simple debug output appended to a debug.log file the following code can be used:

import logging

logging.basicConfig(filename='debug.log', level=logging.DEBUG)

With this simple addition it is already possible to debug ssh connection problems.

But what if a response did not contain the expected data and it is important to know in detail which command has been send to the server?

In this case it is necessary to wrap the actual connection in a DebugConnection class.

Example using GMP:

from gvm.connections import UnixSocketConnection, DebugConnection
from gvm.protocols.gmp import Gmp

path = '/run/gvmd/gvmd.sock'
socketconnection = UnixSocketConnection(path=path)
connection = DebugConnection(socketconnection)

with Gmp(connection=connection) as gmp:
    gmp.get_version()

With this change the file debug.log will contain something as follows:

DEBUG:gvm.connections:Sending 14 characters. Data <get_version/>
DEBUG:gvm.connections:Read 97 characters. Data <get_version_response status="200" status_text="OK"><version>9.0</version></get_version_response>