stix2-utils 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stix2_utils-0.0.2.dist-info/METADATA +33 -0
- stix2_utils-0.0.2.dist-info/RECORD +11 -0
- stix2_utils-0.0.2.dist-info/WHEEL +4 -0
- stix2utils/__init__.py +85 -0
- stix2utils/adapter.py +89 -0
- stix2utils/common.py +87 -0
- stix2utils/references.py +47 -0
- stix2utils/sco_models.py +819 -0
- stix2utils/sdo_models.py +253 -0
- stix2utils/sro_models.py +297 -0
- stix2utils/validator.py +32 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: stix2-utils
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Utility library for validating stix2 entities and patterns
|
|
5
|
+
Author: Daan Willems
|
|
6
|
+
Author-email: Daan Willems <daan@daan.nl>
|
|
7
|
+
Requires-Dist: pydantic
|
|
8
|
+
Requires-Dist: pytest ; extra == 'dev'
|
|
9
|
+
Requires-Python: >=3.13
|
|
10
|
+
Project-URL: Homepage, https://github.com/DaanWillems/stix2-utils
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# stix2-utils
|
|
15
|
+
A utility library for validating STIX 2.1 objects. This library used pydantic to validate STIX 2.1 objects. Later on it will also support creating objects and validating indicator patterns.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
The stix2-utils library is hosted on PyPi. The most recent version can be installed with pip:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install stix2-utils
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
You can use the library to validate STIX 2.1 objects and receive human readable errors
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
validator = STIX2Validator()
|
|
29
|
+
validation_result = validator.validate_entity(stix_obj)
|
|
30
|
+
|
|
31
|
+
print(validation_result.success)
|
|
32
|
+
print(validation_result.errors)
|
|
33
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
stix2utils/__init__.py,sha256=G7mVWt3HImYrrIiOWZVZkMW2wIXY8FyH2R5fhzOuPoI,1444
|
|
2
|
+
stix2utils/adapter.py,sha256=j9_UYnfxc-3dgQJ6AWtpVgz8xH2w8Vk1NYtrurrJnIA,1521
|
|
3
|
+
stix2utils/common.py,sha256=qKq8Jfb9nY4JZ3SdlrrPn7ozK-Q1Yjlu0MMfVoNzdRQ,2150
|
|
4
|
+
stix2utils/references.py,sha256=Ay1bcUnoumJ4FzadFguHBvWYAalSRCwtbmil1zQQBDs,2661
|
|
5
|
+
stix2utils/sco_models.py,sha256=amzTH2LLo4pkAkLPn7daY0JBrkdWIvoCB9xnkA1GUOI,28610
|
|
6
|
+
stix2utils/sdo_models.py,sha256=AijfmBPAv0zzWfojj1CYtbIlCQnxxwrnTJ8gaWN28WU,9046
|
|
7
|
+
stix2utils/sro_models.py,sha256=1lUeDk_46OhzEkETURpsNDVrZtbth0izduAsGd8Jhqc,12427
|
|
8
|
+
stix2utils/validator.py,sha256=IFeFBvppZNp4hr4B04e6BxSmN2icuzUC8CORy9YWUQU,944
|
|
9
|
+
stix2_utils-0.0.2.dist-info/WHEEL,sha256=YR4QUxGCbsyoOnWBVTv-p1I4yc3seKGPev46mvmc8Cg,81
|
|
10
|
+
stix2_utils-0.0.2.dist-info/METADATA,sha256=Zg3BVinUIjpNFUau7w7fj2EJlNAtH2B8pMdCf-L-1VQ,1015
|
|
11
|
+
stix2_utils-0.0.2.dist-info/RECORD,,
|
stix2utils/__init__.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from stix2utils.sco_models import (
|
|
2
|
+
URL,
|
|
3
|
+
Artifact,
|
|
4
|
+
AutonomousSystem,
|
|
5
|
+
Directory,
|
|
6
|
+
DomainName,
|
|
7
|
+
EmailAddress,
|
|
8
|
+
EmailMessage,
|
|
9
|
+
File,
|
|
10
|
+
IPv4Address,
|
|
11
|
+
IPv6Address,
|
|
12
|
+
MACAddress,
|
|
13
|
+
Mutex,
|
|
14
|
+
NetworkTraffic,
|
|
15
|
+
Process,
|
|
16
|
+
Software,
|
|
17
|
+
UserAccount,
|
|
18
|
+
WindowsRegistryKey,
|
|
19
|
+
X509Certificate,
|
|
20
|
+
)
|
|
21
|
+
from stix2utils.sdo_models import (
|
|
22
|
+
AttackPattern,
|
|
23
|
+
Campaign,
|
|
24
|
+
CourseOfAction,
|
|
25
|
+
Grouping,
|
|
26
|
+
Identity,
|
|
27
|
+
Indicator,
|
|
28
|
+
Infrastructure,
|
|
29
|
+
IntrusionSet,
|
|
30
|
+
Location,
|
|
31
|
+
Malware,
|
|
32
|
+
MalwareAnalysis,
|
|
33
|
+
Note,
|
|
34
|
+
ObservedData,
|
|
35
|
+
Opinion,
|
|
36
|
+
Report,
|
|
37
|
+
ThreatActor,
|
|
38
|
+
Tool,
|
|
39
|
+
Vulnerability,
|
|
40
|
+
)
|
|
41
|
+
from stix2utils.sro_models import Relationship, Sighting
|
|
42
|
+
from stix2utils.validator import STIX2ValidationResult, STIX2Validator
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
STIX2Validator,
|
|
46
|
+
STIX2ValidationResult,
|
|
47
|
+
AttackPattern,
|
|
48
|
+
Campaign,
|
|
49
|
+
CourseOfAction,
|
|
50
|
+
Grouping,
|
|
51
|
+
Identity,
|
|
52
|
+
Indicator,
|
|
53
|
+
Infrastructure,
|
|
54
|
+
IntrusionSet,
|
|
55
|
+
Location,
|
|
56
|
+
Malware,
|
|
57
|
+
MalwareAnalysis,
|
|
58
|
+
Note,
|
|
59
|
+
ObservedData,
|
|
60
|
+
Opinion,
|
|
61
|
+
Report,
|
|
62
|
+
ThreatActor,
|
|
63
|
+
Tool,
|
|
64
|
+
Vulnerability,
|
|
65
|
+
Artifact,
|
|
66
|
+
AutonomousSystem,
|
|
67
|
+
Directory,
|
|
68
|
+
DomainName,
|
|
69
|
+
EmailAddress,
|
|
70
|
+
EmailMessage,
|
|
71
|
+
File,
|
|
72
|
+
IPv4Address,
|
|
73
|
+
IPv6Address,
|
|
74
|
+
MACAddress,
|
|
75
|
+
Mutex,
|
|
76
|
+
NetworkTraffic,
|
|
77
|
+
Process,
|
|
78
|
+
Software,
|
|
79
|
+
URL,
|
|
80
|
+
UserAccount,
|
|
81
|
+
WindowsRegistryKey,
|
|
82
|
+
X509Certificate,
|
|
83
|
+
Relationship,
|
|
84
|
+
Sighting,
|
|
85
|
+
]
|
stix2utils/adapter.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
|
|
3
|
+
from pydantic import Field, TypeAdapter
|
|
4
|
+
|
|
5
|
+
from stix2utils.sco_models import (
|
|
6
|
+
URL,
|
|
7
|
+
Artifact,
|
|
8
|
+
AutonomousSystem,
|
|
9
|
+
Directory,
|
|
10
|
+
DomainName,
|
|
11
|
+
EmailAddress,
|
|
12
|
+
EmailMessage,
|
|
13
|
+
File,
|
|
14
|
+
IPv4Address,
|
|
15
|
+
IPv6Address,
|
|
16
|
+
MACAddress,
|
|
17
|
+
Mutex,
|
|
18
|
+
NetworkTraffic,
|
|
19
|
+
Process,
|
|
20
|
+
Software,
|
|
21
|
+
UserAccount,
|
|
22
|
+
WindowsRegistryKey,
|
|
23
|
+
X509Certificate,
|
|
24
|
+
)
|
|
25
|
+
from stix2utils.sdo_models import (
|
|
26
|
+
AttackPattern,
|
|
27
|
+
Campaign,
|
|
28
|
+
CourseOfAction,
|
|
29
|
+
Grouping,
|
|
30
|
+
Identity,
|
|
31
|
+
Indicator,
|
|
32
|
+
Infrastructure,
|
|
33
|
+
IntrusionSet,
|
|
34
|
+
Location,
|
|
35
|
+
Malware,
|
|
36
|
+
MalwareAnalysis,
|
|
37
|
+
Note,
|
|
38
|
+
ObservedData,
|
|
39
|
+
Opinion,
|
|
40
|
+
Report,
|
|
41
|
+
ThreatActor,
|
|
42
|
+
Tool,
|
|
43
|
+
Vulnerability,
|
|
44
|
+
)
|
|
45
|
+
from stix2utils.sro_models import Relationship, Sighting
|
|
46
|
+
|
|
47
|
+
SDO_SCO_SRO = Annotated[
|
|
48
|
+
AttackPattern
|
|
49
|
+
| Campaign
|
|
50
|
+
| CourseOfAction
|
|
51
|
+
| Grouping
|
|
52
|
+
| Identity
|
|
53
|
+
| Indicator
|
|
54
|
+
| Infrastructure
|
|
55
|
+
| IntrusionSet
|
|
56
|
+
| Location
|
|
57
|
+
| Malware
|
|
58
|
+
| MalwareAnalysis
|
|
59
|
+
| Note
|
|
60
|
+
| ObservedData
|
|
61
|
+
| Opinion
|
|
62
|
+
| Report
|
|
63
|
+
| ThreatActor
|
|
64
|
+
| Tool
|
|
65
|
+
| Vulnerability
|
|
66
|
+
| Artifact
|
|
67
|
+
| AutonomousSystem
|
|
68
|
+
| Directory
|
|
69
|
+
| DomainName
|
|
70
|
+
| EmailAddress
|
|
71
|
+
| EmailMessage
|
|
72
|
+
| File
|
|
73
|
+
| IPv4Address
|
|
74
|
+
| IPv6Address
|
|
75
|
+
| MACAddress
|
|
76
|
+
| Mutex
|
|
77
|
+
| NetworkTraffic
|
|
78
|
+
| Process
|
|
79
|
+
| Software
|
|
80
|
+
| URL
|
|
81
|
+
| UserAccount
|
|
82
|
+
| WindowsRegistryKey
|
|
83
|
+
| X509Certificate
|
|
84
|
+
| Relationship
|
|
85
|
+
| Sighting,
|
|
86
|
+
Field(discriminator="type"),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
stix_adapter = TypeAdapter(SDO_SCO_SRO)
|
stix2utils/common.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Annotated
|
|
3
|
+
|
|
4
|
+
from pydantic import Field
|
|
5
|
+
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
# Common base
|
|
8
|
+
# ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
_TIMESTAMP_RE = (
|
|
11
|
+
r"^\d{4}-\d{2}-\d{2}" # YYYY-MM-DD
|
|
12
|
+
r"T\d{2}:\d{2}:\d{2}" # THH:mm:ss
|
|
13
|
+
r"(?:\.\d+)?" # optional .s+ (dot only if digits follow)
|
|
14
|
+
r"Z$" # mandatory UTC designator
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
Timestamp = Annotated[str, Field(pattern=_TIMESTAMP_RE)]
|
|
18
|
+
|
|
19
|
+
# hex type: even number of lowercase hex characters
|
|
20
|
+
Hex = Annotated[str, Field(pattern=r"^(?:[0-9a-f]{2})+$")]
|
|
21
|
+
|
|
22
|
+
# A hashes dictionary: keys are algorithm names, values are hash strings.
|
|
23
|
+
# Keys should come from hash-algorithm-ov, dictionary keys 3-250 ASCII chars.
|
|
24
|
+
Hashes = Annotated[dict[str, str], Field(min_length=1)]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class HashAlgorithm(str, Enum):
|
|
28
|
+
MD5 = "MD5"
|
|
29
|
+
SHA_1 = "SHA-1"
|
|
30
|
+
SHA_256 = "SHA-256"
|
|
31
|
+
SHA_512 = "SHA-512"
|
|
32
|
+
SHA3_256 = "SHA3-256"
|
|
33
|
+
SHA3_512 = "SHA3-512"
|
|
34
|
+
SSDEEP = "SSDEEP"
|
|
35
|
+
TLSH = "TLSH"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
|
+
# STIX object type universe
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
SDO_TYPES: frozenset[str] = frozenset(
|
|
43
|
+
{
|
|
44
|
+
"attack-pattern",
|
|
45
|
+
"campaign",
|
|
46
|
+
"course-of-action",
|
|
47
|
+
"grouping",
|
|
48
|
+
"identity",
|
|
49
|
+
"incident",
|
|
50
|
+
"indicator",
|
|
51
|
+
"infrastructure",
|
|
52
|
+
"intrusion-set",
|
|
53
|
+
"location",
|
|
54
|
+
"malware",
|
|
55
|
+
"malware-analysis",
|
|
56
|
+
"note",
|
|
57
|
+
"observed-data",
|
|
58
|
+
"opinion",
|
|
59
|
+
"report",
|
|
60
|
+
"threat-actor",
|
|
61
|
+
"tool",
|
|
62
|
+
"vulnerability",
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
SCO_TYPES: frozenset[str] = frozenset(
|
|
67
|
+
{
|
|
68
|
+
"artifact",
|
|
69
|
+
"autonomous-system",
|
|
70
|
+
"directory",
|
|
71
|
+
"domain-name",
|
|
72
|
+
"email-addr",
|
|
73
|
+
"email-message",
|
|
74
|
+
"file",
|
|
75
|
+
"ipv4-addr",
|
|
76
|
+
"ipv6-addr",
|
|
77
|
+
"mac-addr",
|
|
78
|
+
"mutex",
|
|
79
|
+
"network-traffic",
|
|
80
|
+
"process",
|
|
81
|
+
"software",
|
|
82
|
+
"url",
|
|
83
|
+
"user-account",
|
|
84
|
+
"windows-registry-key",
|
|
85
|
+
"x509-certificate",
|
|
86
|
+
}
|
|
87
|
+
)
|
stix2utils/references.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import Annotated, TypeAlias
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
_UUID = r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _pattern(*types: str) -> str:
|
|
9
|
+
"""Build the id-regex for one or more STIX id prefixes."""
|
|
10
|
+
prefix = types[0] if len(types) == 1 else "(?:" + "|".join(types) + ")"
|
|
11
|
+
return rf"^{prefix}--{_UUID}$"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Single-type references
|
|
15
|
+
IdentityRef: TypeAlias = Annotated[str, Field(pattern=_pattern("identity"))]
|
|
16
|
+
MarkingRef: TypeAlias = Annotated[str, Field(pattern=_pattern("marking-definition"))]
|
|
17
|
+
SoftwareRef: TypeAlias = Annotated[str, Field(pattern=_pattern("software"))]
|
|
18
|
+
ObservedDataRef: TypeAlias = Annotated[str, Field(pattern=_pattern("observed-data"))]
|
|
19
|
+
|
|
20
|
+
# Multi-type references
|
|
21
|
+
SampleRef: TypeAlias = Annotated[str, Field(pattern=_pattern("file", "artifact"))] # malware / malware-analysis samples
|
|
22
|
+
IdentityOrLocationRef: TypeAlias = Annotated[str, Field(pattern=_pattern("identity", "location"))] # malware / malware-analysis samples
|
|
23
|
+
InstalledSoftwareRef: TypeAlias = Annotated[str, Field(pattern=_pattern("software"))]
|
|
24
|
+
|
|
25
|
+
# Open reference: any valid STIX object id (SDO / SCO / SRO / SMO)
|
|
26
|
+
AnyRef: TypeAlias = Annotated[str, Field(pattern=_pattern("[a-z0-9-]+"))]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Single-type references
|
|
30
|
+
ArtifactRef: TypeAlias = Annotated[str, Field(pattern=_pattern("artifact"))]
|
|
31
|
+
AutonomousSystemRef: TypeAlias = Annotated[str, Field(pattern=_pattern("autonomous-system"))]
|
|
32
|
+
DirectoryRef: TypeAlias = Annotated[str, Field(pattern=_pattern("directory"))]
|
|
33
|
+
FileRef: TypeAlias = Annotated[str, Field(pattern=_pattern("file"))]
|
|
34
|
+
MACAddrRef: TypeAlias = Annotated[str, Field(pattern=_pattern("mac-addr"))]
|
|
35
|
+
NetworkTrafficRef: TypeAlias = Annotated[str, Field(pattern=_pattern("network-traffic"))]
|
|
36
|
+
ProcessRef: TypeAlias = Annotated[str, Field(pattern=_pattern("process"))]
|
|
37
|
+
UserAccountRef: TypeAlias = Annotated[str, Field(pattern=_pattern("user-account"))]
|
|
38
|
+
|
|
39
|
+
# Multi-type references
|
|
40
|
+
DirectoryContainsRef: TypeAlias = Annotated[str, Field(pattern=_pattern("file", "directory"))]
|
|
41
|
+
DomainResolvesToRef: TypeAlias = Annotated[str, Field(pattern=_pattern("ipv4-addr", "ipv6-addr", "domain-name"))]
|
|
42
|
+
IPResolvesToRef: TypeAlias = Annotated[str, Field(pattern=_pattern("mac-addr"))]
|
|
43
|
+
IPBelongsToRef: TypeAlias = Annotated[str, Field(pattern=_pattern("autonomous-system"))]
|
|
44
|
+
EmailAddrRef: TypeAlias = Annotated[str, Field(pattern=_pattern("email-addr"))]
|
|
45
|
+
EmailFromRef: TypeAlias = Annotated[str, Field(pattern=_pattern("email-addr"))]
|
|
46
|
+
MimeBodyRawRef: TypeAlias = Annotated[str, Field(pattern=_pattern("artifact", "file"))]
|
|
47
|
+
NetworkSrcDstRef: TypeAlias = Annotated[str, Field(pattern=_pattern("ipv4-addr", "ipv6-addr", "mac-addr", "domain-name"))]
|