Skip to content

Commit a937f01

Browse files
authored
Merge pull request #16 from ScreamBun/master
Fall cleaning update for Yuuki development
2 parents 8362323 + d11faa1 commit a937f01

15 files changed

+69
-272
lines changed

README.md

+34-40
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,50 @@
11

2-
## OASIS TC Open Repository: openc2-yuuki
2+
<a href="https://openc2.org/" target="_blank">![OpenC2](https://github.com/ScreamBun/SB_Utils/blob/master/assets/images/openc2.png?raw=true)</a>
3+
4+
[![Python 3.8+](https://img.shields.io/badge/Python-3.8%2B-yellow)](https://www.python.org/downloads/release/python-3100/)
5+
[![Open2C Lang Spec](https://img.shields.io/badge/Open2C%20Lang%20Spec-1.0-brightgreen)](https://openc2.org/specifications)
36

4-
This GitHub public repository ( [https://github.com/oasis-open/openc2-yuuki](https://github.com/oasis-open/openc2-yuuki) ) was created at the request of the [OASIS Open Command and Control (OpenC2) TC](https://www.oasis-open.org/committees/openc2/) as an [OASIS TC Open Repository](https://www.oasis-open.org/resources/open-repositories/) to support development of open source resources related to Technical Committee work.
5-
While this TC Open Repository remains associated with the sponsor TC, its development priorities, leadership, intellectual property terms, participation rules, and other matters of governance are [separate and distinct](https://github.com/oasis-open/openc2-yuuki/blob/master/CONTRIBUTING.md#governance-distinct-from-oasis-tc-process) from the OASIS TC Process and related policies.
6-
All contributions made to this TC Open Repository are subject to open source license terms expressed in the [BSD-3-Clause License](https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt). That license was selected as the declared ["Applicable License"](https://www.oasis-open.org/resources/open-repositories/licenses) when the TC Open Repository was created.
7-
As documented in ["Public Participation Invited"](https://github.com/oasis-open/openc2-yuuki/blob/master/CONTRIBUTING.md#public-participation-invited), contributions to this OASIS TC Open Repository are invited from all parties, whether affiliated with OASIS or not. Participants must have a GitHub account, but no fees or OASIS membership obligations are required. Participation is expected to be consistent with the [OASIS TC Open Repository Guidelines and Procedures](https://www.oasis-open.org/policies-guidelines/open-repositories), the open source [LICENSE](https://github.com/oasis-open/openc2-yuuki/blob/master/LICENSE) designated for this particular repository, and the requirement for an [Individual Contributor License Agreement](https://www.oasis-open.org/resources/open-repositories/cla/individual-cla) that governs intellectual property.
8-
9-
[<img src="snow_yuuki.jpg" alt="Yuuki" title="Yuuki Image" width="224" height="104"/>](snow_yuuki.jpg)
10-
117
## Table of Contents
128

13-
[Introduction](#introduction)
14-
[Requirements and Setup](#requirements-and-setup)
15-
[Yuuki's Consumer Components](#components-of-a-yuuki-consumer)
16-
* [Consumers](#consumers)
17-
* [Actuators](#actuators)
18-
* [Serializations](#serializations)
19-
[Example Consumers](#examples)
20-
[Transport Functions](#transport-functions)
21-
* [HTTP](#HTTP)
22-
* [MQTT](#MQTT)
23-
* [OpenDXL(experimental)](#opendxl)
24-
[FAQ](#frequently-asked-questions)
9+
- [Introduction](#introduction)
10+
- [Requirements and Setup](#requirements-and-setup)
11+
- [Yuuki's Consumer Components](#components-of-a-yuuki-consumer)
12+
- [Consumers](#consumers)
13+
- [Actuators](#actuators)
14+
- [Serializations](#serializations)
15+
- [Example Consumers](#examples)
16+
- [Transport Functions](#transport-functions)
17+
- [HTTP](#HTTP)
18+
- [MQTT](#MQTT)
19+
- [FAQ](#frequently-asked-questions)
2520

2621

2722
## Introduction
2823
Yuuki is a tool for creating OpenC2 Consumers.
2924
Open Command and Control, or OpenC2, is a standardized language for the command and control of technologies that provide or support cyber defenses.
3025
OpenC2 Commands are sent by Producer devices to Consumers that receive and implement Commands.
31-
OpenC2 is defined in the [OpenC2 Architecture Specification](https://docs.oasis-open.org/openc2/oc2arch/v1.0/csd02/oc2arch-v1.0-csd02.md) and [OpenC2 Language Specification](https://github.com/oasis-tcs/openc2-oc2ls/blob/published/oc2ls-v1.0-cs02.md)
26+
OpenC2 is defined in the [OpenC2 Architecture Specification](https://docs.oasis-open.org/openc2/oc2arch/v1.0/csd02/oc2arch-v1.0-csd02.md) and [OpenC2 Language Specification](https://github.com/oasis-tcs/openc2-oc2ls/blob/published/oc2ls-v1.0-cs02.md).
27+
28+
### Background
29+
30+
This GitHub public repository ( [https://github.com/oasis-open/openc2-yuuki](https://github.com/oasis-open/openc2-yuuki) ) was created at the request of the [OASIS Open Command and Control (OpenC2) TC](https://www.oasis-open.org/committees/openc2/) as an [OASIS TC Open Repository](https://www.oasis-open.org/resources/open-repositories/) to support development of open source resources related to Technical Committee work.
31+
32+
While this TC Open Repository remains associated with the sponsor TC, its development priorities, leadership, intellectual property terms, participation rules, and other matters of governance are [separate and distinct](https://github.com/oasis-open/openc2-yuuki/blob/master/CONTRIBUTING.md#governance-distinct-from-oasis-tc-process) from the OASIS TC Process and related policies.
3233

33-
#### Statement of Purpose
34+
All contributions made to this TC Open Repository are subject to open source license terms expressed in the [BSD-3-Clause License](https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt). That license was selected as the declared ["Applicable License"](https://www.oasis-open.org/resources/open-repositories/licenses) when the TC Open Repository was created.
35+
36+
As documented in ["Public Participation Invited"](https://github.com/oasis-open/openc2-yuuki/blob/master/CONTRIBUTING.md#public-participation-invited), contributions to this OASIS TC Open Repository are invited from all parties, whether affiliated with OASIS or not. Participants must have a GitHub account, but no fees or OASIS membership obligations are required. Participation is expected to be consistent with the [OASIS TC Open Repository Guidelines and Procedures](https://www.oasis-open.org/policies-guidelines/open-repositories), the open source [LICENSE](https://github.com/oasis-open/openc2-yuuki/blob/master/LICENSE) designated for this particular repository, and the requirement for an [Individual Contributor License Agreement](https://www.oasis-open.org/resources/open-repositories/cla/individual-cla) that governs intellectual property.
37+
38+
39+
### Statement of Purpose
3440
Statement of Purpose for this OASIS TC Open Repository (openc2-yuuki) as [proposed](https://drive.google.com/open?id=0B-FunCZrr-vtcUJTWVBNaFNlVUE) and [approved](https://www.oasis-open.org/committees/ballot.php?id=3115) [[bis]](https://issues.oasis-open.org/browse/TCADMIN-2746) by the OpenC2 TC:
3541
The purpose of the openc2-yuuki GitHub repository is to
3642
(a) demonstrate the implementation of OpenC2 via multiple dispatch on type, and
3743
(b) provision a codebase to enable other prototype efforts.
3844
The initial codebase for the openc2-yuuki repository is imported from the OpenC2 Forum's Github repository.
3945

40-
Yuuki is designed to be a good introduction to OpenC2, to facilitate experimentation with different Actuator profiles,
41-
transfer protocols and message serializations, and to provide a simple OpenC2 Consumer for OpenC2 Producers to test against.
46+
Yuuki is designed to be a good introduction to OpenC2, to facilitate experimentation with different Actuator profiles, transfer protocols, and message serializations, and to provide a simple OpenC2 Consumer for OpenC2 Producers to test against.
47+
4248
The three main components of Yuuki are the [Consumer](consumers), [Actuator](#actuators), and [Serialization](#serializations) classes,
4349
defined respectively in the `consumer.py`, `actuator.py`, and `serialization.py` files.
4450

@@ -126,7 +132,7 @@ An Actuator is identified by a string representing the namespace identifier (`ns
126132
Actuators consist of a number of action- target pairs, and inherit from the Actuator class,
127133
giving them access to initialization, pair definition and registration, and some basic error handling.
128134

129-
For example, see the sample implementation of an Actuator based on the [Stateless Packet Filtering](https://docs.oasis-open.org/openc2/oc2slpf/v1.0/oc2slpf-v1.0.html) Actuator profile in `examples/actuators/slpf.py`
135+
For example, see the sample implementation of an Actuator based on the [Stateless Packet Filtering](https://docs.oasis-open.org/openc2/oc2slpf/v1.0/oc2slpf-v1.0.html) Actuator profile in `examples/actuators/slpf.py`.
130136
[Stateless Packet Filtering](https://docs.oasis-open.org/openc2/oc2slpf/v1.0/oc2slpf-v1.0.html) is a standard Actuator profile with the nsid: `slpf`.
131137
nsids of nonstandard Actuator profiles are prefixed with `x-`.
132138

@@ -236,8 +242,7 @@ Yuuki's Consumer functions require it has OpenC2 to read. Transport functions ar
236242
These are found under `/openc2_arch/transports` and have `__init__,` `config` and `transport` functions.
237243
These were not listed with the other core parts of Yuuki only because they interact with its Consumer logic very little.
238244
They are very important, but they deal with transporting serialized messages, not OpenC2 Commands.
239-
This is where your connection info is sent to properly establish connections.
240-
Tinker with caution!
245+
This is where your connection info is sent to properly establish connections, so tinker with caution!
241246

242247
### MQTT
243248
You can find the OpenC2 MQTT Transfer Specification [Here](https://github.com/oasis-tcs/openc2-transf-mqtt/blob/published/transf-mqtt-v1.0-cs01.md).
@@ -266,15 +271,6 @@ python examples/http_example.py
266271
python examples/producers/http_producer.py
267272
```
268273

269-
### OpenDXL
270-
271-
| :warning: | *Support for OpenDXL is experimental*|
272-
|------------------|:-------------------------------------|
273-
274-
This example uses both the Event and Request/Response messaging capabilities of OpenDXL to send and receive OpenC2 Messages.
275-
276-
An OpenDXL configuration file is required to run these examples.
277-
278274
#### Start Consumer:
279275
```sh
280276
python examples/opendxl_example.py PATH_TO_OPENDXL_CONFIG
@@ -310,10 +306,8 @@ Good Luck, and Have Fun!
310306
TC Open Repository [Maintainers](https://www.oasis-open.org/resources/open-repositories/maintainers-guide) are responsible for oversight of this project's community development activities, including evaluation of GitHub [pull requests]() and [preserving](https://www.oasis-open.org/policies-guidelines/open-repositories#repositoryManagement) open source principles of openness and fairness. Maintainers are recognized and trusted experts who serve to implement community goals and consensus design preferences.
311307
Initially, the associated TC members have designated one or more persons to serve as Maintainer(s); subsequently, participating community members may select additional or substitute Maintainers, per [consensus agreements](https://www.oasis-open.org/maintainers-guide/#additionalMaintainers).
312308
Current Maintainers of this TC Open Repository
313-
314-
* [Dave Kemp]([email protected]); GitHub ID: [https://github.com/davaya](https://github.com/davaya); WWW: [Department of Defense](www.nsa.gov)
315-
* [Joshua Brulé](mailto:[email protected]); GitHub ID: [https://github.com/jtcbrule](https://github.com/jtcbrule); WWW: [University of Maryland](https://umd.edu/)
316-
* [David Lemire](mailto:[email protected]); GitHub ID: [https://github.com/dlemire60](https://github.com/dlemire60); WWW: [National Security Agency](www.nsa.gov)
309+
310+
* [David Lemire](mailto:[email protected]); Email: [email protected]
317311
* The ScreamingBunny Development team; GitHub ID: [https://github.com/ScreamBun](https://github.com/ScreamBun)
318312

319313
#### Where can I learn about OASIS TC Open Repositories?

examples/mqtt_consumer_full.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@
1111

1212
from actuators.slpf import slpf
1313

14-
1514
consumer = Consumer(rate_limit=60, versions=['1.0'], actuators=[slpf])
1615

17-
host = "127.0.0.1"
16+
host = "test.mosquitto.org"
1817
port = 1883
19-
topics = ['oc2/cmd', 'oc2/cmd/ap/slpf', 'oc2/cmd/ap/database', 'oc2/cmd/ap/sbom']
18+
topics = ['oc2/cmd', 'oc2/cmd/ap/slpf']
2019

2120
mqtt_config = MqttConfig(
2221
broker=BrokerConfig(
@@ -25,7 +24,7 @@
2524
client_id='',
2625
keep_alive=300,
2726
authorization=MQTTAuthorization(
28-
enable=True,
27+
enable=False,
2928
username='plug',
3029
password='fest'
3130
),

examples/mqtt_consumer_er.py examples/mqtt_consumer_plugfest.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
"""
22
Example Implementation of an OpenC2 MQTT Consumer
33
"""
4-
from yuuki.transports import (
4+
from oc2_arch.transports import (
55
MqttTransport, MqttConfig, MQTTAuthorization, MQTTAuthentication, BrokerConfig, Publication, Subscription
66
)
77

8-
from yuuki import Consumer
8+
from oc2_arch import Consumer
99
# import actuator profiles for your consumer
1010

11-
12-
from actuators.er import er
11+
from actuators.database import database
12+
from actuators.sbom import sbom
1313
from actuators.slpf import slpf
1414

1515

16-
consumer = Consumer(rate_limit=60, versions=['1.0'], actuators=[er, slpf])
16+
consumer = Consumer(rate_limit=60, versions=['1.0'], actuators=[sbom, database, slpf])
1717

18-
host = "127.0.0.1"
18+
host = '35.221.11.97'
1919
port = 1883
20-
topics = ['oc2/cmd', 'oc2/cmd/ap/er']
20+
topics = ['oc2/cmd', 'oc2/cmd/ap/slpf', 'oc2/cmd/ap/database', 'oc2/cmd/ap/sbom']
2121

2222
mqtt_config = MqttConfig(
2323
broker=BrokerConfig(

examples/producers/openc2_command_er.py

-71
This file was deleted.

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
SB-Utils@git+https://github.com/ScreamBun/SB_utils.git#subdirectory=root
2+
OSQuery-ORM@git+https://github.com/ScreamBun/SB_utils.git#subdirectory=osquery_orm
23
dxlclient
34
elasticsearch
45
flask

setup.cfg

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ classifiers =
2222
[options]
2323
include_package_data = true
2424
packages = find:
25-
package_dir = src
2625
python_requires = >=3.8
2726
setup_requires = setuptools_scm
2827

setup.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ def get_requirements():
1010

1111
setup(
1212
name='Yuuki',
13-
13+
package_data={
14+
"yuuki": ["./src/yuuki/*"]
15+
},
1416
install_requires=get_requirements()
1517
)

snow_yuuki.jpg

-91.7 KB
Binary file not shown.

src/yuuki/consumer.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import json
55
import logging
66
from time import time
7-
from pprint import pformat # properly prints JSON serielized text as part of return messages, useful for SBOM etc
7+
from pprint import pformat # properly prints JSON serialized text as part of return messages, useful for SBOM etc
88
from concurrent.futures import ThreadPoolExecutor
99
from functools import partial
1010
from typing import Any, Callable, Dict, List, Union
@@ -53,7 +53,7 @@ def __init__(self, rate_limit: int, versions: List[str], actuators: List[Actuato
5353
self.add_serialization(serialization)
5454
if actuators is not None:
5555
for actuator in actuators:
56-
self.add_actuator_profile(actuator)
56+
self.add_actuator(actuator)
5757
print("Added actuator "+actuator.nsid)
5858
self.executor = ThreadPoolExecutor()
5959
print(r'''
@@ -88,6 +88,11 @@ def process_command(self, command, encode: str) -> Union[str, bytes, None]:
8888

8989
try:
9090
openc2_msg = OpenC2Msg(**message)
91+
92+
93+
print(openc2_msg)
94+
95+
9196
except ValidationError as e:
9297
#logging.error(e)
9398
openc2_rsp = OpenC2RspFields(status=StatusCode.BAD_REQUEST, status_text='Malformed OpenC2 message')
@@ -181,21 +186,21 @@ def _get_actuator_callable(self, oc2_msg: OpenC2Msg) -> Callable[[], OpenC2RspFi
181186
:return: The function with the received OpenC2 Command supplied as an argument.
182187
"""
183188
oc2_cmd = oc2_msg.body.openc2.request
184-
print(f"{oc2_cmd.action} {oc2_cmd.target_name} {oc2_cmd.actuator_name}")
189+
print(f"{oc2_cmd.action} {oc2_cmd.target_name} {oc2_cmd.profile_name}")
185190
print(self.dispatch)
186191
print(self.understood)
187192
if oc2_cmd.action == 'query' and oc2_cmd.target_name == 'features':
188193
function = self.query_features
189194
elif oc2_cmd.action in self.dispatch and oc2_cmd.target_name in self.dispatch[oc2_cmd.action]:
190-
if oc2_cmd.actuator_name is None:
195+
if oc2_cmd.profile_name is None:
191196
# Behavior of duplicate Action-Target pairs is currently undefined in the OpenC2 language.
192197
# For the time being, this is handled by calling the function of the first matching pair.
193198
function = next(iter(self.dispatch[oc2_cmd.action][oc2_cmd.target_name].values()))
194199
else:
195-
if oc2_cmd.actuator_name in self.dispatch[oc2_cmd.action][oc2_cmd.target_name]:
196-
function = self.dispatch[oc2_cmd.action][oc2_cmd.target_name][oc2_cmd.actuator_name]
200+
if oc2_cmd.profile_name in self.dispatch[oc2_cmd.action][oc2_cmd.target_name]:
201+
function = self.dispatch[oc2_cmd.action][oc2_cmd.target_name][oc2_cmd.profile_name]
197202
else:
198-
raise TypeError(f'No Actuator: {oc2_cmd.actuator_name}')
203+
raise TypeError(f'No Actuator: {oc2_cmd.profile_name}')
199204
elif oc2_cmd.action in self.understood and oc2_cmd.target_name in self.understood[oc2_cmd.action]:
200205
function = self.unimplemented_command_function
201206
else:
@@ -255,7 +260,7 @@ def unimplemented_command_function(self, oc2_cmd: OpenC2CmdFields) -> OpenC2RspF
255260
print("Command Not Implemented")
256261
return OpenC2RspFields(status=StatusCode.NOT_IMPLEMENTED, status_text='Command Not Supported')
257262

258-
def add_actuator_profile(self, actuator: Actuator) -> None:
263+
def add_actuator(self, actuator: Actuator) -> None:
259264
"""
260265
Adds the Actuator's functions to the Consumer and adds the Actuator's namespace identifier (nsid) to the
261266
list of supported profiles

src/yuuki/openc2_types/request.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ class OpenC2CmdFields(BaseModel, extra=Extra.forbid):
4646
action: str
4747
target: Dict[str, Any]
4848
args: Optional[Union[OpenC2CmdArgs, Dict[str, Any]]]
49-
actuator: Optional[Dict[str, Dict[str, Any]]]
49+
profile: Optional[Dict[str, Dict[str, Any]]]
5050
command_id: Optional[str]
5151

52-
@validator('target', 'actuator')
52+
@validator('target', 'profile')
5353
def validate_choice_length(cls, choice: Dict):
54+
5455
if len(choice) != 1:
5556
raise ValueError('Choice fields must have a length of one')
5657
return choice
@@ -60,11 +61,11 @@ def target_name(self):
6061
return next(iter(self.target))
6162

6263
@property
63-
def actuator_name(self):
64-
if self.actuator is None:
64+
def profile_name(self):
65+
if self.profile is None:
6566
return None
6667
else:
67-
return next(iter(self.actuator))
68+
return next(iter(self.profile))
6869

6970

7071
class OpenC2Cmd(BaseModel, extra=Extra.forbid):

src/yuuki/transports/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@
22
from .mqtt import (
33
MqttTransport, MqttConfig, MQTTAuthorization, MQTTAuthentication, BrokerConfig, Subscription, Publication
44
)
5-
from .opendxl import OpenDxlTransport, OpenDxlConfig

0 commit comments

Comments
 (0)