Skip to main content

otupy: OpenC2 Utilities for Python

Description

otupy (/'əʊtu:paɪ/) is an open-source implementation of the OpenC2 language written in Python. It is particullary suited for:

  • developers that are looking for a common interface to control their remote cybersecurity functions;
  • researchers that design new profiles for cybersecurity functions;
  • system integrators that need a common language for their cybersecurity frameworks.

The otupy framework is build around a pluggable and powerful core library, designed with flexibility and extensibility in mind. Profiles, transfer protocols, serialization formats, and actuators can be easily added without impacting the core library itself. The framework currently includes:

  • the core library that implements the OpenC2 Architecture and Language Specification;
  • json/yaml/xml/cbor serialization;
  • implementation of the HTTP/MQTT transfer protocol;
  • the definition of the SLPF profile;
  • the Context Discovery profile and its actuators for OpenStack and Kubernetes;
  • a dumb implementation of an actuator for the SLPF profile.

Usage and extension of otupy have a shallow learning curve because data structures are explicitly designed to follow the language specification.

Quick start

Before using otupy you must be familiar with the OpenC2 Language Specification. Even if not strictly required to getting started with the code, the OpenC2 Architecture Specification provides a good introduction to OpenC2 architectural patterns and terminology.

While the Language Specification is somehow confusing about the concept of profile and actuator, otupy makes a sharp distinction between these terms:

  • a profile is a language extension that abstract a specific class of security functions (this is also indicated ad Actuator Profile by the standard);
  • an actuator is the concrete implementation of a profile for a specific security appliance; it may be either integrated in the appliance itself or act as a proxy to a legacy implementation (in this last case it is also referred as Actuator Manager.

Software requirements

Python 3.11+ is required to use otupy.

Download and setup

Otupy is available as source code, Python package, and docker container.

PyPi

Install it and its dependencies from PyPi:

pip install otupy

Docker container

A base docker image is provided, which can be used to build containers for specific applications (e.g., MIRANDA Connector). This image does not provide any default CMD or ENTRY_POINT. The base image is available at:

ghcr.io/mattereppe/otupy

A latest tag is available to download the latest version; additional tags are provided for main releases.

To download the latest version of the base image:

docker pull ghcr.io/mattereppe/otupy:latest

Clone repository

Alternatively, dowload it from github:

git clone https://github.com/mattereppe/openc2.git

and install the necessary dependecies:

python3 -m venv .oc2-env
. .oc2-env/bin/activate
pip install -r requirements.txt

Usage

A few scripts are available in the examples folder of the repository for sending a simple commmand from a controller to a remote server (hosting the actuator).

Basic usage consists in instantiating the Provider and Consumer classes that implements the OpenC2 Provider and Consumer role, respectively. This includes the creation of a protocol stack, namely the serialization format and transfer protocol. The Consumer also loads the available Actuators. Note that in the otupy implementation, the security services and transport protocols are already embedded in each specific transfer protocol.

Create the Server

A Server instantiates and runs the OpenC2 Consumer.

The otupy module only includes the core libraries, while all extensions for serialization, transfer protocols, profile definition, and actuator implementations are grouped in specific modules (encoders, trasfers, profiles, and actuators).

import otupy as oc2

from otupy.encoders.json_encoder import JSONEncoder
from otupy.transfers.http_transfer import HTTPTransfer

import otupy.profiles.slpf as slpf
from otupy.actuators.iptables_actuator import IptablesActuator

First, we instantiate the IptablesActuator as an implementation of the slpf profile:

 actuators = {}
 actuators[(slpf.nsid,'iptables')]=IptablesActuator()

(there is no specific configuration here because the IptablesActuator is currently a mockup)

Next, we create the Consumer by instantiating its execution environment with the list of served Actuators and the protocol stack. We also provide an identification string:

consumer = oc2.Consumer("consumer.example.net", actuators, JSONEncoder(), HTTPTransfer("127.0.0.1", 8080))

(the server will be listening on the loopback interface, port 8080)

Finally, start the server:

 consumer.run()

Create the Controller

A Controller instantiates an OpenC2 Producer and to use it to control a remote security function. Note that the Producer is totally unaware of the concrete actuators and its implementation.

from otupy.encoders.json_encoder import JSONEncoder
from otupy.transfers.http_transfer import HTTPTransfer

import otupy.profiles.slpf as slpf

producer = oc2.Producer("producer.example.net", JSONEncoder(), HTTPTransfer("127.0.0.1", 8080))

Next we create a Command, by combining the Action, Target, Arguments, and Actuator. We will query the remote slpf actuator for its capabilities. Note how we mix common language elements with specific extensions for the slpf profile, as expected by the Specification:

pf = slpf.slpf({'hostname':'firewall', 'named_group':'firewalls', 'asset_id':'iptables'})
arg = slpf.ExtArgs({'response_requested': oc2.ResponseType.complete})
 
cmd = oc2.Command(oc2.Actions.query, oc2.Features(), actuator=pf)

Finally, we send the command and catch the response:

resp = p.sendcmd(cmd)

(print out resp to check what the server returned)

A more useful implementation of a Controller would also include the business logic to update rules on specific events (even by specific input from the user).

Advanced usage

See the full documentation available from readthedocs.io.

Authors and acknowledgment

  • The Context Discovery profile, its actuators and use cases have been developed by Silvio Tanzarella.
  • The Xbom Actuator Profile and its serialization have been developed by Fabio Lorenzato.

License

Licensed under the EUPL v1.2.

Metadata

Release files for otupy 1.1.45

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for otupy 1.1.45
File Size Uploaded Provenance
otupy-1.1.45.tar.gz 7.1 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for otupy 1.1.45
File Interpreter ABI Platform
otupy-1.1.45-py3-none-any.whl Python 3 none any Details

Total release size: 7.5 MB

Release files / otupy-1.1.45.tar.gz

Download URL otupy-1.1.45.tar.gz
Size 7.1 MB
Tags Source
SHA-256 checksum
How to use checksums
b628654d8deccd8006ffb80af50dff9c991bd25241ee09f482342aa7831273b0
BLAKE2b-256 checksum
How to use checksums
0df76332668eb45d10bb3df00dc2674fd701c2d43418b4a62d33ef462cdb6d70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / otupy-1.1.45-py3-none-any.whl

Download URL otupy-1.1.45-py3-none-any.whl
Size 474.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ece108071992b2ca147fa02bd3b6805f8814cdb22464c0f29cc0846b84fb9a61
BLAKE2b-256 checksum
How to use checksums
86211373f417ddf643a030f3494f99c4bbf4b72659cf273804fc7f27f3baf1a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for otupy 1.1.45

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for otupy-1.1.45.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page