mal-toolbox 1.0.3__tar.gz → 1.0.5__tar.gz
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.
- {mal_toolbox-1.0.3/mal_toolbox.egg-info → mal_toolbox-1.0.5}/PKG-INFO +12 -6
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/README.md +8 -4
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5/mal_toolbox.egg-info}/PKG-INFO +12 -6
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/mal_toolbox.egg-info/requires.txt +3 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/__init__.py +2 -2
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/attackgraph/attackgraph.py +4 -1
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/attackgraph/node.py +1 -1
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/language/languagegraph.py +14 -132
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/model.py +29 -1
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/pyproject.toml +8 -2
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/tests/test_model.py +6 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/AUTHORS +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/LICENSE +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/mal_toolbox.egg-info/SOURCES.txt +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/mal_toolbox.egg-info/dependency_links.txt +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/mal_toolbox.egg-info/entry_points.txt +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/mal_toolbox.egg-info/top_level.txt +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/__main__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/attackgraph/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/attackgraph/analyzers/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/exceptions.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/file_utils.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/language/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/language/compiler/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/language/compiler/mal_lexer.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/language/compiler/mal_parser.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/patternfinder/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/patternfinder/attackgraph_patterns.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/py.typed +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/translators/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/translators/securicad.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/translators/updater.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/visualization/__init__.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/maltoolbox/visualization/graphviz_utils.py +0 -0
- {mal_toolbox-1.0.3 → mal_toolbox-1.0.5}/setup.cfg +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mal-toolbox
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: A collection of tools used to create MAL models and attack graphs.
|
|
5
|
-
Author-email: Andrei Buhaiu <buhaiu@kth.se>, Joakim Loxdal <loxdal@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Giuseppe Nebbione <nebbione@kth.se>
|
|
5
|
+
Author-email: Andrei Buhaiu <buhaiu@kth.se>, Joakim Loxdal <loxdal@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Sandor Berglund <sandor@kth.se>
|
|
6
6
|
License: Apache Software License
|
|
7
7
|
Project-URL: Homepage, https://github.com/mal-lang/mal-toolbox
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/mal-lang/mal-toolbox/issues
|
|
@@ -23,6 +23,8 @@ Requires-Dist: antlr4-tools
|
|
|
23
23
|
Requires-Dist: antlr4-python3-runtime
|
|
24
24
|
Requires-Dist: docopt
|
|
25
25
|
Requires-Dist: PyYAML
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
|
|
28
30
|
# MAL Toolbox overview
|
|
@@ -30,7 +32,7 @@ Dynamic: license-file
|
|
|
30
32
|
MAL Toolbox is a collection of python modules to help developers create and work with
|
|
31
33
|
MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
|
|
32
34
|
|
|
33
|
-
Attack graphs can be used to run simulations
|
|
35
|
+
Attack graphs can be used to run simulations in [MAL Simulator](https://github.com/mal-lang/mal-simulator) or run your own custom analysis on.
|
|
34
36
|
|
|
35
37
|
[Documentation](https://mal-lang.org/mal-toolbox/index.html)(Work in progress)
|
|
36
38
|
|
|
@@ -124,19 +126,23 @@ You can use the maltoolbox cli to:
|
|
|
124
126
|
Command-line interface for MAL toolbox operations
|
|
125
127
|
|
|
126
128
|
Usage:
|
|
127
|
-
maltoolbox attack-graph generate [options] <model_file> <lang_file>
|
|
128
129
|
maltoolbox compile <lang_file> <output_file>
|
|
130
|
+
maltoolbox generate-attack-graph [--graphviz] <model_file> <lang_file>
|
|
129
131
|
maltoolbox upgrade-model <model_file> <lang_file> <output_file>
|
|
132
|
+
maltoolbox visualize-model <model_file> <lang_file>
|
|
130
133
|
|
|
131
134
|
Arguments:
|
|
132
135
|
<model_file> Path to JSON instance model file.
|
|
133
136
|
<lang_file> Path to .mar or .mal file containing MAL spec.
|
|
134
137
|
<output_file> Path to write the result of the compilation (yml/json).
|
|
135
138
|
|
|
139
|
+
Options:
|
|
140
|
+
-h --help Show this screen.
|
|
141
|
+
-g --graphviz Visualize with graphviz
|
|
142
|
+
|
|
136
143
|
Notes:
|
|
137
144
|
- <lang_file> can be either a .mar file (generated by the older MAL
|
|
138
|
-
compiler) or a .mal file containing the DSL written in MAL
|
|
139
|
-
```
|
|
145
|
+
compiler) or a .mal file containing the DSL written in MAL.```
|
|
140
146
|
|
|
141
147
|
## Code examples / Tutorial
|
|
142
148
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
MAL Toolbox is a collection of python modules to help developers create and work with
|
|
4
4
|
MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
|
|
5
5
|
|
|
6
|
-
Attack graphs can be used to run simulations
|
|
6
|
+
Attack graphs can be used to run simulations in [MAL Simulator](https://github.com/mal-lang/mal-simulator) or run your own custom analysis on.
|
|
7
7
|
|
|
8
8
|
[Documentation](https://mal-lang.org/mal-toolbox/index.html)(Work in progress)
|
|
9
9
|
|
|
@@ -97,19 +97,23 @@ You can use the maltoolbox cli to:
|
|
|
97
97
|
Command-line interface for MAL toolbox operations
|
|
98
98
|
|
|
99
99
|
Usage:
|
|
100
|
-
maltoolbox attack-graph generate [options] <model_file> <lang_file>
|
|
101
100
|
maltoolbox compile <lang_file> <output_file>
|
|
101
|
+
maltoolbox generate-attack-graph [--graphviz] <model_file> <lang_file>
|
|
102
102
|
maltoolbox upgrade-model <model_file> <lang_file> <output_file>
|
|
103
|
+
maltoolbox visualize-model <model_file> <lang_file>
|
|
103
104
|
|
|
104
105
|
Arguments:
|
|
105
106
|
<model_file> Path to JSON instance model file.
|
|
106
107
|
<lang_file> Path to .mar or .mal file containing MAL spec.
|
|
107
108
|
<output_file> Path to write the result of the compilation (yml/json).
|
|
108
109
|
|
|
110
|
+
Options:
|
|
111
|
+
-h --help Show this screen.
|
|
112
|
+
-g --graphviz Visualize with graphviz
|
|
113
|
+
|
|
109
114
|
Notes:
|
|
110
115
|
- <lang_file> can be either a .mar file (generated by the older MAL
|
|
111
|
-
compiler) or a .mal file containing the DSL written in MAL
|
|
112
|
-
```
|
|
116
|
+
compiler) or a .mal file containing the DSL written in MAL.```
|
|
113
117
|
|
|
114
118
|
## Code examples / Tutorial
|
|
115
119
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mal-toolbox
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: A collection of tools used to create MAL models and attack graphs.
|
|
5
|
-
Author-email: Andrei Buhaiu <buhaiu@kth.se>, Joakim Loxdal <loxdal@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Giuseppe Nebbione <nebbione@kth.se>
|
|
5
|
+
Author-email: Andrei Buhaiu <buhaiu@kth.se>, Joakim Loxdal <loxdal@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Sandor Berglund <sandor@kth.se>
|
|
6
6
|
License: Apache Software License
|
|
7
7
|
Project-URL: Homepage, https://github.com/mal-lang/mal-toolbox
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/mal-lang/mal-toolbox/issues
|
|
@@ -23,6 +23,8 @@ Requires-Dist: antlr4-tools
|
|
|
23
23
|
Requires-Dist: antlr4-python3-runtime
|
|
24
24
|
Requires-Dist: docopt
|
|
25
25
|
Requires-Dist: PyYAML
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
|
|
28
30
|
# MAL Toolbox overview
|
|
@@ -30,7 +32,7 @@ Dynamic: license-file
|
|
|
30
32
|
MAL Toolbox is a collection of python modules to help developers create and work with
|
|
31
33
|
MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
|
|
32
34
|
|
|
33
|
-
Attack graphs can be used to run simulations
|
|
35
|
+
Attack graphs can be used to run simulations in [MAL Simulator](https://github.com/mal-lang/mal-simulator) or run your own custom analysis on.
|
|
34
36
|
|
|
35
37
|
[Documentation](https://mal-lang.org/mal-toolbox/index.html)(Work in progress)
|
|
36
38
|
|
|
@@ -124,19 +126,23 @@ You can use the maltoolbox cli to:
|
|
|
124
126
|
Command-line interface for MAL toolbox operations
|
|
125
127
|
|
|
126
128
|
Usage:
|
|
127
|
-
maltoolbox attack-graph generate [options] <model_file> <lang_file>
|
|
128
129
|
maltoolbox compile <lang_file> <output_file>
|
|
130
|
+
maltoolbox generate-attack-graph [--graphviz] <model_file> <lang_file>
|
|
129
131
|
maltoolbox upgrade-model <model_file> <lang_file> <output_file>
|
|
132
|
+
maltoolbox visualize-model <model_file> <lang_file>
|
|
130
133
|
|
|
131
134
|
Arguments:
|
|
132
135
|
<model_file> Path to JSON instance model file.
|
|
133
136
|
<lang_file> Path to .mar or .mal file containing MAL spec.
|
|
134
137
|
<output_file> Path to write the result of the compilation (yml/json).
|
|
135
138
|
|
|
139
|
+
Options:
|
|
140
|
+
-h --help Show this screen.
|
|
141
|
+
-g --graphviz Visualize with graphviz
|
|
142
|
+
|
|
136
143
|
Notes:
|
|
137
144
|
- <lang_file> can be either a .mar file (generated by the older MAL
|
|
138
|
-
compiler) or a .mal file containing the DSL written in MAL
|
|
139
|
-
```
|
|
145
|
+
compiler) or a .mal file containing the DSL written in MAL.```
|
|
140
146
|
|
|
141
147
|
## Code examples / Tutorial
|
|
142
148
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# MAL Toolbox v1.0.
|
|
2
|
+
# MAL Toolbox v1.0.5
|
|
3
3
|
# Copyright 2025, Andrei Buhaiu.
|
|
4
4
|
#
|
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -21,7 +21,7 @@ MAL-Toolbox Framework
|
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
__title__ = "maltoolbox"
|
|
24
|
-
__version__ = "1.0.
|
|
24
|
+
__version__ = "1.0.5"
|
|
25
25
|
__authors__ = [
|
|
26
26
|
"Andrei Buhaiu",
|
|
27
27
|
"Giuseppe Nebbione",
|
|
@@ -192,7 +192,10 @@ class AttackGraph():
|
|
|
192
192
|
node_id = node_dict['id'],
|
|
193
193
|
model_asset = node_asset,
|
|
194
194
|
ttc_dist = node_dict['ttc'],
|
|
195
|
-
existence_status =
|
|
195
|
+
existence_status = (
|
|
196
|
+
bool(node_dict['existence_status'])
|
|
197
|
+
if 'existence_status' in node_dict else None
|
|
198
|
+
)
|
|
196
199
|
)
|
|
197
200
|
ag_node.tags = list(node_dict.get('tags', []))
|
|
198
201
|
ag_node.extras = node_dict.get('extras', {})
|
|
@@ -56,7 +56,7 @@ class AttackGraphNode:
|
|
|
56
56
|
if self.model_asset is not None:
|
|
57
57
|
node_dict['asset'] = str(self.model_asset.name)
|
|
58
58
|
if self.existence_status is not None:
|
|
59
|
-
node_dict['existence_status'] =
|
|
59
|
+
node_dict['existence_status'] = self.existence_status
|
|
60
60
|
if self.tags:
|
|
61
61
|
node_dict['tags'] = list(self.tags)
|
|
62
62
|
if self.extras:
|
|
@@ -10,7 +10,7 @@ import zipfile
|
|
|
10
10
|
|
|
11
11
|
from dataclasses import dataclass, field
|
|
12
12
|
from functools import cached_property
|
|
13
|
-
from typing import Any, Optional
|
|
13
|
+
from typing import Any, Literal, Optional
|
|
14
14
|
|
|
15
15
|
from maltoolbox.file_utils import (
|
|
16
16
|
load_dict_from_yaml_file, load_dict_from_json_file,
|
|
@@ -26,131 +26,6 @@ from ..exceptions import (
|
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
28
28
|
|
|
29
|
-
predef_ttcs: dict[str, dict] = {
|
|
30
|
-
'EasyAndUncertain':
|
|
31
|
-
{
|
|
32
|
-
'arguments': [0.5],
|
|
33
|
-
'name': 'Bernoulli',
|
|
34
|
-
'type': 'function'
|
|
35
|
-
},
|
|
36
|
-
'HardAndUncertain':
|
|
37
|
-
{
|
|
38
|
-
'lhs':
|
|
39
|
-
{
|
|
40
|
-
'arguments': [0.1],
|
|
41
|
-
'name': 'Exponential',
|
|
42
|
-
'type': 'function'
|
|
43
|
-
},
|
|
44
|
-
'rhs':
|
|
45
|
-
{
|
|
46
|
-
'arguments': [0.5],
|
|
47
|
-
'name': 'Bernoulli',
|
|
48
|
-
'type': 'function'
|
|
49
|
-
},
|
|
50
|
-
'type': 'multiplication'
|
|
51
|
-
},
|
|
52
|
-
'VeryHardAndUncertain':
|
|
53
|
-
{
|
|
54
|
-
'lhs':
|
|
55
|
-
{
|
|
56
|
-
'arguments': [0.01],
|
|
57
|
-
'name': 'Exponential',
|
|
58
|
-
'type': 'function'
|
|
59
|
-
},
|
|
60
|
-
'rhs':
|
|
61
|
-
{
|
|
62
|
-
'arguments': [0.5],
|
|
63
|
-
'name': 'Bernoulli',
|
|
64
|
-
'type': 'function'
|
|
65
|
-
},
|
|
66
|
-
'type': 'multiplication'
|
|
67
|
-
},
|
|
68
|
-
'EasyAndCertain':
|
|
69
|
-
{
|
|
70
|
-
'arguments': [1.0],
|
|
71
|
-
'name': 'Exponential',
|
|
72
|
-
'type': 'function'
|
|
73
|
-
},
|
|
74
|
-
'HardAndCertain':
|
|
75
|
-
{
|
|
76
|
-
'arguments': [0.1],
|
|
77
|
-
'name': 'Exponential',
|
|
78
|
-
'type': 'function'
|
|
79
|
-
},
|
|
80
|
-
'VeryHardAndCertain':
|
|
81
|
-
{
|
|
82
|
-
'arguments': [0.01],
|
|
83
|
-
'name': 'Exponential',
|
|
84
|
-
'type': 'function'
|
|
85
|
-
},
|
|
86
|
-
'Enabled':
|
|
87
|
-
{
|
|
88
|
-
'arguments': [1.0],
|
|
89
|
-
'name': 'Bernoulli',
|
|
90
|
-
'type': 'function'
|
|
91
|
-
},
|
|
92
|
-
'Instant':
|
|
93
|
-
{
|
|
94
|
-
'arguments': [1.0],
|
|
95
|
-
'name': 'Bernoulli',
|
|
96
|
-
'type': 'function'
|
|
97
|
-
},
|
|
98
|
-
'Disabled':
|
|
99
|
-
{
|
|
100
|
-
'arguments': [0.0],
|
|
101
|
-
'name': 'Bernoulli',
|
|
102
|
-
'type': 'function'
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
def get_ttc_distribution(
|
|
107
|
-
step_dict: dict,
|
|
108
|
-
defense_default_ttc = None,
|
|
109
|
-
attack_default_ttc = None
|
|
110
|
-
) -> Optional[dict]:
|
|
111
|
-
"""Convert step TTC to a TTC distribution if needed
|
|
112
|
-
|
|
113
|
-
- If no TTC is set, set return default TTC.
|
|
114
|
-
- If the TTC provided is a predefined name replace it with the
|
|
115
|
-
probability distribution it corresponds to.
|
|
116
|
-
- Otherwise return the TTC distribution as is.
|
|
117
|
-
|
|
118
|
-
Arguments:
|
|
119
|
-
step_dict - A dict with the attack step data
|
|
120
|
-
defense_default_ttc - the value to give a defense ttc if none is set
|
|
121
|
-
attack_default_ttc - the value to give an attack ttc if none is set
|
|
122
|
-
|
|
123
|
-
Returns:
|
|
124
|
-
A dict with the steps TTC distribution, or None if the step is not
|
|
125
|
-
a defense or attack step
|
|
126
|
-
"""
|
|
127
|
-
|
|
128
|
-
if defense_default_ttc is None:
|
|
129
|
-
defense_default_ttc = predef_ttcs['Disabled'].copy()
|
|
130
|
-
if attack_default_ttc is None:
|
|
131
|
-
attack_default_ttc = predef_ttcs['Instant'].copy()
|
|
132
|
-
|
|
133
|
-
step_ttc = step_dict['ttc']
|
|
134
|
-
|
|
135
|
-
if step_dict['type'] == 'defense':
|
|
136
|
-
if step_ttc is None:
|
|
137
|
-
# No step ttc set in language for defense
|
|
138
|
-
step_ttc = defense_default_ttc
|
|
139
|
-
elif step_dict['type'] in ('or', 'and'):
|
|
140
|
-
if step_ttc is None:
|
|
141
|
-
# No step ttc set in language for attack
|
|
142
|
-
step_ttc = attack_default_ttc
|
|
143
|
-
else:
|
|
144
|
-
# No TTC for other step types
|
|
145
|
-
return None
|
|
146
|
-
|
|
147
|
-
if 'name' in step_ttc and step_ttc['name'] in predef_ttcs:
|
|
148
|
-
# Predefined step ttc set in language, fetch from dict
|
|
149
|
-
step_ttc = predef_ttcs[step_ttc['name']].copy()
|
|
150
|
-
|
|
151
|
-
return step_ttc
|
|
152
|
-
|
|
153
|
-
|
|
154
29
|
|
|
155
30
|
def disaggregate_attack_step_full_name(
|
|
156
31
|
attack_step_full_name: str) -> list[str]:
|
|
@@ -347,7 +222,7 @@ class LanguageGraphAsset:
|
|
|
347
222
|
return self_superassets.intersection(other_superassets)
|
|
348
223
|
|
|
349
224
|
|
|
350
|
-
@dataclass
|
|
225
|
+
@dataclass(frozen=True)
|
|
351
226
|
class LanguageGraphAssociationField:
|
|
352
227
|
"""A field in an association"""
|
|
353
228
|
asset: LanguageGraphAsset
|
|
@@ -356,7 +231,7 @@ class LanguageGraphAssociationField:
|
|
|
356
231
|
maximum: int
|
|
357
232
|
|
|
358
233
|
|
|
359
|
-
@dataclass
|
|
234
|
+
@dataclass(frozen=True, eq=True)
|
|
360
235
|
class LanguageGraphAssociation:
|
|
361
236
|
"""
|
|
362
237
|
An association type between asset types as defined in the MAL language
|
|
@@ -364,7 +239,7 @@ class LanguageGraphAssociation:
|
|
|
364
239
|
name: str
|
|
365
240
|
left_field: LanguageGraphAssociationField
|
|
366
241
|
right_field: LanguageGraphAssociationField
|
|
367
|
-
info: dict = field(default_factory = dict)
|
|
242
|
+
info: dict = field(default_factory = dict, compare=False)
|
|
368
243
|
|
|
369
244
|
def to_dict(self) -> dict:
|
|
370
245
|
"""Convert LanguageGraphAssociation to dictionary"""
|
|
@@ -481,7 +356,7 @@ class LanguageGraphAttackStep:
|
|
|
481
356
|
An attack step belonging to an asset type in the MAL language
|
|
482
357
|
"""
|
|
483
358
|
name: str
|
|
484
|
-
type:
|
|
359
|
+
type: Literal["or", "and", "defense", "exist", "notExist"]
|
|
485
360
|
asset: LanguageGraphAsset
|
|
486
361
|
ttc: Optional[dict] = field(default_factory = dict)
|
|
487
362
|
overrides: bool = False
|
|
@@ -864,6 +739,13 @@ class LanguageGraph():
|
|
|
864
739
|
|
|
865
740
|
return serialized_graph
|
|
866
741
|
|
|
742
|
+
@property
|
|
743
|
+
def associations(self) -> set[LanguageGraphAssociation]:
|
|
744
|
+
"""
|
|
745
|
+
Return all associations in the language graph.
|
|
746
|
+
"""
|
|
747
|
+
return {assoc for asset in self.assets.values() for assoc in asset.associations.values()}
|
|
748
|
+
|
|
867
749
|
@staticmethod
|
|
868
750
|
def _link_association_to_assets(
|
|
869
751
|
assoc: LanguageGraphAssociation,
|
|
@@ -998,7 +880,7 @@ class LanguageGraph():
|
|
|
998
880
|
name = attack_step_dict['name'],
|
|
999
881
|
type = attack_step_dict['type'],
|
|
1000
882
|
asset = asset,
|
|
1001
|
-
ttc =
|
|
883
|
+
ttc = attack_step_dict['ttc'],
|
|
1002
884
|
overrides = attack_step_dict['overrides'],
|
|
1003
885
|
own_children = {},
|
|
1004
886
|
own_parents = {},
|
|
@@ -1716,7 +1598,7 @@ class LanguageGraph():
|
|
|
1716
1598
|
name = attack_step_attribs['name'],
|
|
1717
1599
|
type = attack_step_attribs['type'],
|
|
1718
1600
|
asset = asset,
|
|
1719
|
-
ttc =
|
|
1601
|
+
ttc = attack_step_attribs['ttc'],
|
|
1720
1602
|
overrides = (
|
|
1721
1603
|
attack_step_attribs['reaches']['overrides']
|
|
1722
1604
|
if attack_step_attribs['reaches'] else False
|
|
@@ -3,7 +3,6 @@ MAL-Toolbox Model Module
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
|
-
from dataclasses import dataclass, field
|
|
7
6
|
import json
|
|
8
7
|
import logging
|
|
9
8
|
from typing import TYPE_CHECKING
|
|
@@ -23,6 +22,7 @@ if TYPE_CHECKING:
|
|
|
23
22
|
from .language import (
|
|
24
23
|
LanguageGraph,
|
|
25
24
|
LanguageGraphAsset,
|
|
25
|
+
LanguageGraphAssociation
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
logger = logging.getLogger(__name__)
|
|
@@ -361,6 +361,34 @@ class ModelAsset:
|
|
|
361
361
|
return (f'ModelAsset(name: "{self.name}", id: {self.id}, '
|
|
362
362
|
f'type: {self.type})')
|
|
363
363
|
|
|
364
|
+
def associations_with(
|
|
365
|
+
self, b: ModelAsset
|
|
366
|
+
) -> set[LanguageGraphAssociation]:
|
|
367
|
+
"""Returns all associations from self to `b`"""
|
|
368
|
+
assocs_in_common = set()
|
|
369
|
+
for assoc in self.lg_asset.associations.values():
|
|
370
|
+
assets_to_left = self.associated_assets.get(
|
|
371
|
+
assoc.left_field.fieldname, set()
|
|
372
|
+
)
|
|
373
|
+
assets_to_right = self.associated_assets.get(
|
|
374
|
+
assoc.right_field.fieldname, set()
|
|
375
|
+
)
|
|
376
|
+
if b in assets_to_left or b in assets_to_right:
|
|
377
|
+
assocs_in_common.add(assoc)
|
|
378
|
+
|
|
379
|
+
return assocs_in_common
|
|
380
|
+
|
|
381
|
+
def has_association_with(self, b: ModelAsset, assoc_name: str) -> bool:
|
|
382
|
+
"""
|
|
383
|
+
Returns True if association `assoc_name` exists between self and `b`
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
for fieldname, associated_assets in self.associated_assets.items():
|
|
387
|
+
assoc = self.lg_asset.associations[fieldname]
|
|
388
|
+
if assoc.name == assoc_name and b in associated_assets:
|
|
389
|
+
return True
|
|
390
|
+
|
|
391
|
+
return False
|
|
364
392
|
|
|
365
393
|
def validate_associated_assets(
|
|
366
394
|
self, fieldname: str, assets_to_add: set[ModelAsset]
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mal-toolbox"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.5"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Andrei Buhaiu", email="buhaiu@kth.se" },
|
|
6
6
|
{ name="Joakim Loxdal", email="loxdal@kth.se" },
|
|
7
7
|
{ name="Nikolaos Kakouros", email="nkak@kth.se" },
|
|
8
8
|
{ name="Jakob Nyberg", email="jaknyb@kth.se" },
|
|
9
|
-
{ name="Giuseppe Nebbione", email="nebbione@kth.se" }
|
|
9
|
+
{ name="Giuseppe Nebbione", email="nebbione@kth.se" },
|
|
10
|
+
{ name="Sandor Berglund", email="sandor@kth.se" }
|
|
10
11
|
]
|
|
11
12
|
description = "A collection of tools used to create MAL models and attack graphs."
|
|
12
13
|
readme = "README.md"
|
|
@@ -34,6 +35,11 @@ classifiers = [
|
|
|
34
35
|
"Bug Tracker" = "https://github.com/mal-lang/mal-toolbox/issues"
|
|
35
36
|
"Repository" = "https://github.com/mal-lang/mal-toolbox"
|
|
36
37
|
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
dev = [
|
|
40
|
+
"pytest",
|
|
41
|
+
]
|
|
42
|
+
|
|
37
43
|
[project.scripts]
|
|
38
44
|
"maltoolbox" = "maltoolbox.__main__:main"
|
|
39
45
|
|
|
@@ -125,6 +125,12 @@ def test_model_add_associated_asset(model: Model):
|
|
|
125
125
|
assert 'hostApp' in asset2.associated_assets
|
|
126
126
|
assert asset1 in asset2.associated_assets['hostApp']
|
|
127
127
|
|
|
128
|
+
associations_in_common = asset1.associations_with(asset2)
|
|
129
|
+
assert associations_in_common
|
|
130
|
+
|
|
131
|
+
for assoc in associations_in_common:
|
|
132
|
+
assert asset1.has_association_with(asset2, assoc.name)
|
|
133
|
+
|
|
128
134
|
|
|
129
135
|
def test_model_add_appexecution_association_two_assets(model: Model):
|
|
130
136
|
"""coreLang specifies that AppExecution only can have one 'left' asset"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|