The Architecture of Teatime¶
In this document we will get to know the design decisions behind Teatime and introduce the library’s primitives to make development more intuitive. There are five components to Teatime that make up its inner workings:
- Scanner: A scanner executes one or more plugins on a given target
- Plugin: Plugins are where the magic happens: They perform the checks and generate issues
- Context: The context object is passed from one scanner to the next and holds report meta data
- Report: The report object inside the context is where Plugins add their issues
- Issue: This basic building block holds data about findings such as title, severity, and much more
Scanner¶
The Scanner class is a user’s entry point to Teatime. It takes an IP, port, node type, and
a list of Plugin instances to execute on the target. Behind the scenes, it
initializes a fresh Context class, which is passed between the plugins to aggregate
report data.
In the current implementation, the Scanner class executes the given plugin list
sequentially on the target. The list order is equivalent to the execution order. This means
that a plugin could provide meta data in a report that another plugin further down the line
can use. While this is not recommended because it introduces implicit dependencies, it
can certainly be used to build highly customized and complex scanning pipelines.
After the scan is done, the Scanner class attaches the time elapsed for the
scan to the report’s meta data.
Plugin¶
The Plugin class is a base for all concrete scans of Teatime. A Plugin can
execute one or more checks on the given target. To specify your own behaviour, the
base Plugin class contains an abstract method _check that can be
overridden by the user. This method gets a Context object (hopefully)
containing all relevant meta data needed by the plugin.
For RPC interaction specifically, the Plugin class contains a helper
method to query RPC endpoints in a robust way and handle connection errors along the
way. To prevent Teatime from crashing completely in case of plugin-related errors,
it is recommended to raise and reraise a PluginException. This can be
caught easily on the top level, e.g. by the routine executing the scanner.
Context¶
The Context object contains report- and target-related information instructing
the Plugin classes. It contains the target, the Report object, node type,
and an extra data dictionary for any additional information that e.g. needs to be passed
further down the plugin pipeline. Per scan, there is only one Context instance
(initialized in the Scanner at the beginning of a scan), which gets shared
across Plugin instances as they are executed in the pipeline.
Report¶
The Report object is essentially a container for Issue objects, along
with meta data on the executed scan. It contains a UUID for traceability, the target,
a creation timestamp, a list of issues, and a meta data dictionary for any additional
information that should be communicated to the user.
The idea of wrapping issues in a report and duplicating information such as the target
is that each Report object should be independent. Thinking of developers who
might want to pass Teatime report data into a database, or export it as a file, this
is a nice property to have, because no additional data apart from the object itself is
required.
Furthermore, the Report class contains various helper methods that make
serialization and common checks, such as checking for high-severity issues, easier.
Issue¶
This is the lowest-level primitive. The Issue object can be added to a
Report instance by using its add_issue method. Each issue contains
a UUID for traceability, a title, description, severity, and a raw data field. The
latter one is meant to contain the raw RPC response. For example, if a scan has
detected an information leak, the raw data field can be populated with the actual
leaking information text, without cluttering the title or description - thus keeping
issues readable and allowing the user to omit large strings when presenting an issue
to the user.
Just like the Report class, an Issue object contains various helper
method for easier serialization, as well as determining whether the issue at hand is
severe. Wrapping issues into their own object has the advantage of enforcing a standard
format across plugins and requiring them to provide information that help the user
make sense of what has been reported.