Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
robthew authored Feb 6, 2024
2 parents 5ecaf06 + 6db8e8e commit fb3a703
Show file tree
Hide file tree
Showing 61 changed files with 525 additions and 1,269 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: cti-python-stix2-extensions test harness
on:
push:
paths:
- '**.py'
pull_request:
paths:
- '**.py'

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11', '3.12']

name: Python ${{ matrix.python-version }} Build
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c
with:
python-version: ${{ matrix.python-version }}
- name: Install and update essential dependencies
run: |
pip install -U pip setuptools
pip install tox-gh-actions
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50
id: filter
with:
filters: |
incident-ef7:
- 'incident-ef7/**'
observed-string-8b1:
- 'observed-string-8b1/**'
- name: Test incident-ef7 with Tox
if: ${{ steps.filter.outputs.incident-ef7 == 'true' }}
run: |
tox -c incident-ef7/tox.ini
- name: Test observed-string-8b1 with Tox
if: ${{ steps.filter.outputs.observed-string-8b1 == 'true' }}
run: |
tox -c observed-string-8b1/tox.ini
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,4 @@ Icon
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
.apdisk
26 changes: 26 additions & 0 deletions cui-marking-definition-dff/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Controlled Unclassified Information (CUI) Data Markings

This is an implementation of the
[CUI data marking extension](https://github.com/oasis-open/cti-stix-common-objects/blob/main/extension-definition-specifications/cui-marking-definition-dff/STIX-2.1-CUI-marking.adoc) for STIX 2.1.

See example marking definitions (JSON) using this extension in the `/examples` subdirectory.

Example Python usage:

```
import stix2
from cui.cui import CUIExtension, CUI_MARKING_EXTENSION_ID
designator = stix2.Identity(name='a CUI designator')
stix2.MarkingDefinition(
extensions={
CUI_MARKING_EXTENSION_ID: CUIExtension(
control='CUI',
designator_ref=designator.id
)
}
)
```

Tests can be run with Tox by executing the `tox` command.
14 changes: 14 additions & 0 deletions cui-marking-definition-dff/examples/banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "marking-definition--bd0e84ce-2df7-421b-8de9-d026a6390b43",
"type": "marking-definition",
"spec_version": "2.1",
"created": "2023-03-04T00:00:00.000Z",
"extensions": {
"extension-definition--dff17fb3-edcb-4f99-ad1b-4b751c95738a": {
"extension_type": "property-extension",
"control": "CUI",
"categories": ["ASYL"],
"designator_ref": "identity--c069bb9f-158a-405d-92b4-858a2536df9a"
}
}
}
13 changes: 13 additions & 0 deletions cui-marking-definition-dff/examples/basic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"id": "marking-definition--331bc382-fcf1-43aa-8c04-732ff0b42c85",
"type": "marking-definition",
"spec_version": "2.1",
"created": "2023-03-04T00:00:00.000Z",
"extensions": {
"extension-definition--dff17fb3-edcb-4f99-ad1b-4b751c95738a": {
"extension_type": "property-extension",
"control": "CUI",
"designator_ref": "identity--c069bb9f-158a-405d-92b4-858a2536df9a"
}
}
}
15 changes: 15 additions & 0 deletions cui-marking-definition-dff/examples/categories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"id": "marking-definition--934ad48b-e590-464e-a814-24df9d1ee002",
"type": "marking-definition",
"spec_version": "2.1",
"created": "2023-03-04T00:00:00.000Z",
"extensions": {
"extension-definition--dff17fb3-edcb-4f99-ad1b-4b751c95738a": {
"extension_type": "property-extension",
"control": "CUI",
"categories": ["SP-SSEL", "SBIZ"],
"disseminations": ["NOFORN", "NOCON"],
"designator_ref": "identity--c069bb9f-158a-405d-92b4-858a2536df9a"
}
}
}
16 changes: 16 additions & 0 deletions cui-marking-definition-dff/examples/supplemental.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"id": "marking-definition--934ad48b-e590-464e-a814-24df9d1ee002",
"type": "marking-definition",
"spec_version": "2.1",
"created": "2023-03-04T00:00:00.000Z",
"extensions": {
"extension-definition--dff17fb3-edcb-4f99-ad1b-4b751c95738a": {
"extension_type": "property-extension",
"control": "CUI",
"categories": ["SP-SSEL", "SBIZ"],
"designator_ref": "identity--c069bb9f-158a-405d-92b4-858a2536df9a",
"required_statements": ["MARKING REQUIRED BY AUTHORITY"],
"supplemental_administrative": ["Draft"]
}
}
}
17 changes: 17 additions & 0 deletions cui-marking-definition-dff/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "stix2-cui-dff"
version = "0.1"
description = "Implementation of a Python API for the Controlled Unclassified Information extension for STIX 2.1 data markings."
dependencies = [
"stix2"
]

[project.optional-dependencies]
dev = ["pytest", "tox"]

[tool.pytest.ini_options]
addopts = "--import-mode=importlib"
6 changes: 6 additions & 0 deletions cui-marking-definition-dff/src/cui/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Trigger registration of extension with the stix2 library; make it accessible
# at the top module level.

# Don't complain about unused imports
# ruff: noqa: F401
from .cui import CUIExtension
23 changes: 23 additions & 0 deletions cui-marking-definition-dff/src/cui/cui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import stix2
from stix2.properties import (EnumProperty, ListProperty, ReferenceProperty,
StringProperty)

CUI_MARKING_EXTENSION_ID = "extension-definition--dff17fb3-edcb-4f99-ad1b-4b751c95738a"
CONTROL_ENUM = [
"CONTROLLED",
"CUI",
]


@stix2.v21.CustomExtension(
CUI_MARKING_EXTENSION_ID, [
('control', EnumProperty(CONTROL_ENUM, required=True)),
('designator_ref', ReferenceProperty(valid_types='identity', spec_version='2.1', required=True)),
('categories', ListProperty(StringProperty())),
('disseminations', ListProperty(StringProperty())),
('required_statements', ListProperty(StringProperty())),
('supplemental_administrative', ListProperty(StringProperty())),
],
)
class CUIExtension:
extension_type = 'property-extension'
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions cui-marking-definition-dff/tests/cui/test_cui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import os

import pytest
import stix2

from cui.cui import CUIExtension, CUI_MARKING_EXTENSION_ID


def test_all_props():
designator = stix2.Identity(name='a CUI designator')
stix2.MarkingDefinition(
extensions={
CUI_MARKING_EXTENSION_ID: CUIExtension(
control='CUI',
categories=["SP-SSEL", "SBIZ"],
disseminations=["NOFORN", "NOCON"],
designator_ref=designator.id,
required_statements=["MARKING REQUIRED BY AUTHORITY"],
supplemental_administrative=["Draft"],
)
}
)


@pytest.mark.parametrize(
"input_file", [
"banner.json",
"basic.json",
"categories.json",
"supplemental.json",
]
)
def test_parse_props(input_file):
filepath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'../../examples', input_file)
with open(filepath) as content:
marking = stix2.parse(content)

assert isinstance(marking, stix2.MarkingDefinition)
assert isinstance(
marking.extensions[CUI_MARKING_EXTENSION_ID],
CUIExtension
)


def test_missing_props():
with pytest.raises(stix2.exceptions.MissingPropertiesError):
stix2.MarkingDefinition(
extensions={
CUI_MARKING_EXTENSION_ID: CUIExtension(
categories=["SBIZ"],
)
}
)
16 changes: 16 additions & 0 deletions cui-marking-definition-dff/tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[tox]
envlist = py38,py39,py310,py311,py312,style

[testenv]
extras = dev
deps =
pytest-cov

commands =
python -m pytest --cov=cui --cov-report=term-missing tests/

[style]
deps =
ruff
commands =
ruff . --line-length 160
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 7 additions & 1 deletion incident/pyproject.toml → incident-ef7/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "python-stix2-incident-extension"
name = "incident-ef7"
version = "0.1"
description = "Implementation of python API for the extensions to the STIX 2.1 incident stub"
dependencies = [
Expand All @@ -15,3 +15,9 @@ dev = ["pytest", "tox"]

[tool.pytest.ini_options]
addopts = "--import-mode=importlib"

[tool.ruff.lint]
extend-select = ["E501"]

[tool.ruff.lint.pycodestyle]
max-line-length = 160
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from collections import OrderedDict

import stix2
from stix2.exceptions import ObjectConfigurationError
from stix2.properties import (BooleanProperty, EnumProperty, ListProperty,
OpenVocabProperty, ReferenceProperty,
StringProperty, TimestampProperty)
Expand Down Expand Up @@ -57,16 +57,15 @@ class EventEntry(_STIXBase21):
class Event:
def _check_object_constraints(self):
super()._check_object_constraints()
log = logging.getLogger(__name__)

validate_event_sequence(self.get("subevents"))

start_time = self.get('start_time')
end_time = self.get('end_time')

if start_time is not None and end_time is not None:
if start_time > end_time:
log.warning(
'event start time is later than end time: %s > %s',
start_time, end_time
if start_time >= end_time:
raise ObjectConfigurationError(
'event start time is equal to or later than end time:'
' {} >= {}'.format(start_time, end_time)
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
from collections import OrderedDict

import stix2
Expand Down Expand Up @@ -95,7 +94,6 @@ def _check_object_constraints(self):
class MonetaryImpactExt:
def _check_object_constraints(self):
super()._check_object_constraints()
log = logging.getLogger(__name__)

self._check_properties_dependency(
[
Expand Down Expand Up @@ -134,11 +132,11 @@ def _check_object_constraints(self):
)

if min_amount is not None and max_amount is not None:
log.warning(
"monetary impact min_amount is greater than max_amount:"
" %d > %d",
min_amount, max_amount
)
if min_amount > max_amount:
raise ObjectConfigurationError(
"monetary impact min_amount is greater than max_amount:"
" {} > {}".format(min_amount, max_amount)
)


@stix2.CustomExtension(
Expand Down Expand Up @@ -196,18 +194,17 @@ class TraceabilityImpactExt:
class Impact:
def _check_object_constraints(self):
super()._check_object_constraints()
log = logging.getLogger(__name__)

self._check_properties_dependency(["end_time"], ["superseded_by_ref"])

start_time = self.get('start_time')
end_time = self.get('end_time')

if start_time is not None and end_time is not None:
if start_time > end_time:
log.warning(
'impact start time is later than end time: %s > %s',
start_time, end_time
if start_time >= end_time:
raise ObjectConfigurationError(
'impact start time is equal to or later than end time:'
' {} > {}'.format(start_time, end_time)
)

impact_category = self["impact_category"]
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from collections import OrderedDict

import stix2
from stix2.exceptions import ObjectConfigurationError
from stix2.properties import (BooleanProperty, EnumProperty, IntegerProperty,
ListProperty, OpenVocabProperty,
ReferenceProperty, StringProperty,
Expand Down Expand Up @@ -59,16 +59,15 @@ class TaskEntry(_STIXBase21):
class Task:
def _check_object_constraints(self):
super()._check_object_constraints()
log = logging.getLogger(__name__)

util.validate_task_sequence(self.get("subtasks"))

start_time = self.get('start_time')
end_time = self.get('end_time')

if start_time is not None and end_time is not None:
if start_time > end_time:
log.warning(
'task start time is later than end time: %s > %s',
start_time, end_time
if start_time >= end_time:
raise ObjectConfigurationError(
'task start time is equal to or later than end time:'
' {} >= {}'.format(start_time, end_time),
)
File renamed without changes.
File renamed without changes.
Empty file added incident-ef7/tests/__init__.py
Empty file.
Empty file.
File renamed without changes.
Loading

0 comments on commit fb3a703

Please sign in to comment.