mal-toolbox 0.0.40__tar.gz → 0.1.1__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.
Files changed (42) hide show
  1. {mal_toolbox-0.0.40/mal_toolbox.egg-info → mal_toolbox-0.1.1}/PKG-INFO +38 -24
  2. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/README.md +37 -23
  3. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1/mal_toolbox.egg-info}/PKG-INFO +38 -24
  4. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/SOURCES.txt +6 -1
  5. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/__init__.py +10 -9
  6. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/__main__.py +1 -2
  7. mal_toolbox-0.1.1/maltoolbox/attackgraph/analyzers/__init__.py +0 -0
  8. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/analyzers/apriori.py +39 -22
  9. mal_toolbox-0.1.1/maltoolbox/attackgraph/attacker.py +102 -0
  10. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/attackgraph.py +330 -143
  11. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/node.py +46 -30
  12. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/query.py +62 -28
  13. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/exceptions.py +13 -0
  14. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/file_utils.py +11 -6
  15. mal_toolbox-0.1.1/maltoolbox/ingestors/__init__.py +0 -0
  16. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/ingestors/neo4j.py +68 -70
  17. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/classes_factory.py +37 -21
  18. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/__init__.py +5 -2
  19. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/mal_lexer.py +1 -1
  20. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/mal_parser.py +1 -1
  21. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/compiler/mal_visitor.py +4 -5
  22. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/languagegraph.py +268 -171
  23. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/specification.py +19 -18
  24. mal_toolbox-0.1.1/maltoolbox/model.py +743 -0
  25. mal_toolbox-0.1.1/maltoolbox/translators/__init__.py +0 -0
  26. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/translators/securicad.py +49 -33
  27. mal_toolbox-0.1.1/maltoolbox/translators/updater.py +132 -0
  28. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/wrappers.py +1 -1
  29. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/pyproject.toml +10 -1
  30. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/tests/test_model.py +172 -53
  31. mal_toolbox-0.1.1/tests/test_wrappers.py +10 -0
  32. mal_toolbox-0.0.40/maltoolbox/attackgraph/attacker.py +0 -70
  33. mal_toolbox-0.0.40/maltoolbox/model.py +0 -492
  34. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/AUTHORS +0 -0
  35. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/LICENSE +0 -0
  36. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/dependency_links.txt +0 -0
  37. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/requires.txt +0 -0
  38. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/mal_toolbox.egg-info/top_level.txt +0 -0
  39. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/attackgraph/__init__.py +0 -0
  40. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/default.conf +0 -0
  41. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/maltoolbox/language/__init__.py +0 -0
  42. {mal_toolbox-0.0.40 → mal_toolbox-0.1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mal-toolbox
3
- Version: 0.0.40
3
+ Version: 0.1.1
4
4
  Summary: A collection of tools used to create MAL models and attack graphs.
5
5
  Author-email: Andrei Buhaiu <buhaiu@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Joakim Loxdal <loxdal@kth.se>
6
6
  License: Apache Software License
@@ -25,16 +25,19 @@ Requires-Dist: antlr4-python3-runtime
25
25
  Requires-Dist: docopt
26
26
  Requires-Dist: PyYAML
27
27
 
28
- # Overview
28
+ # MAL Toolbox overview
29
29
 
30
- A collection of python modules to help developers create and work with MAL
31
- models and attack graphs.
30
+ MAL Toolbox is a collection of python modules to help developers create and work with
31
+ MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
32
32
 
33
- # The Language Module
33
+ Attack graphs can be used to run simulations (see MAL Simulator) or analysis.
34
+ MAL Toolbox also gives the ability to view the AttackGraph/Model graphically in neo4j.
35
+
36
+ ## The Language Module
34
37
 
35
38
  The language module provides various tools to process MAL languages.
36
39
 
37
- ## The Language Specification Submodule
40
+ ### The Language Specification Submodule
38
41
 
39
42
  The language specification submodule provides functions to load the
40
43
  specification from a .mar archive(`load_language_specification_from_mar`) or a
@@ -43,7 +46,7 @@ then be used to generate python classes representing the assets and
43
46
  associations of the language and to determine the attack steps for each asset
44
47
  when generating the attack graph.
45
48
 
46
- ## The Language Classes Factory Submodule
49
+ ### The Language Classes Factory Submodule
47
50
 
48
51
  The language classes factory submodule is used to generate python classes
49
52
  using the `python_jsonschema_objects` package from a language specification.
@@ -54,19 +57,23 @@ using JSON Schema validators they will enforce their restrictions when using
54
57
  the python objects created. These classes are typically used in conjunction
55
58
  with model module to create instance models.
56
59
 
57
- # The Model Module
60
+ ## The Model Module
61
+
62
+ With a MAL language a Model (a MAL instance model) can be created either
63
+ from a model file or empty.
64
+
65
+ The model class will store all of the relevant information to the MAL
66
+ instance model, most importantly the assets and associations that make it up.
67
+
68
+ Assets and associations are objects of classes created using the language
69
+ classes factory submodule in runtime. It also allows for `Attacker` objects
70
+ to be created and associated with attack steps on assets in the model.
71
+ The most relevant methods of the Model are the ones used to add different
72
+ elements to the model, `add_asset`, `add_association`, and `add_attacker`.
58
73
 
59
- The model module is used to create MAL instance models. The model class will
60
- store all of the relevant information to the MAL instance model, most
61
- importantly the assets and associations that make it up. These assets and
62
- associations should be objects created using the language classes factory
63
- submodule. It also allows for `Attacker` objects to be created and associated
64
- with attack steps on assets in the model. The most relevant functions here are
65
- the ones used to add different elements to the model, `add_asset`,
66
- `add_association`, and `add_attacker`. Model objects can be used to generate
67
- attack graphs using the attack graph module.
74
+ Model objects can be used to generate attack graphs with the AttackGraph module.
68
75
 
69
- # The Attack Graph Module
76
+ ## The Attack Graph Module
70
77
 
71
78
  The attack graph module contains tools used to generate attack graphs from
72
79
  existing MAL instance models and analyse MAL attack graphs. The function used
@@ -84,14 +91,21 @@ resulting attack graph with the instance model given as a parameter in order
84
91
  to create attack step nodes that represent the entry points of the attackers
85
92
  and attach them to the attack steps specified in the instance model.
86
93
 
87
- # Ingestors Module
94
+ ## Ingestors Module
88
95
 
89
96
  The ingestors module contains various tools that can make use of the instance
90
97
  model or attack graph. Currently the Neo4J ingestor is the only one available
91
98
  and it can be used to visualise the instance model and the attack graph.
92
99
 
93
- # Command Line Client
94
100
 
101
+ # Usage
102
+
103
+ ## Configuration
104
+ A default configuration file `default.conf` can be found in the package
105
+ directory. This contains the default values to use for logging and can also be
106
+ used to store the information needed to access the local Neo4J instance.
107
+
108
+ ## Command Line Client
95
109
  In addition to the modules that make up the MAL-Toolbox package it also
96
110
  provides a simple command line client that can be used to easily generate
97
111
  attack graphs from a .mar language specification file and a JSON instance
@@ -103,10 +117,10 @@ The usage is: `maltoolbox gen_ag [--neo4j] <model_json_file>
103
117
  If the `--neo4j` flag is specified the model and attack graph will be loaded
104
118
  into a local Neo4J instance.
105
119
 
106
- # Configuration
107
- A default configuration file `default.conf` can be found in the package
108
- directory. This contains the default values to use for logging and can also be
109
- used to store the information needed to access the local Neo4J instance.
120
+ ## Code examples / Tutorial
121
+
122
+ To find code examples and tutorials, visit the
123
+ [MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
110
124
 
111
125
  # Tests
112
126
  There are unit tests inside of ./tests.
@@ -1,13 +1,16 @@
1
- # Overview
1
+ # MAL Toolbox overview
2
2
 
3
- A collection of python modules to help developers create and work with MAL
4
- models and attack graphs.
3
+ MAL Toolbox is a collection of python modules to help developers create and work with
4
+ MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
5
5
 
6
- # The Language Module
6
+ Attack graphs can be used to run simulations (see MAL Simulator) or analysis.
7
+ MAL Toolbox also gives the ability to view the AttackGraph/Model graphically in neo4j.
8
+
9
+ ## The Language Module
7
10
 
8
11
  The language module provides various tools to process MAL languages.
9
12
 
10
- ## The Language Specification Submodule
13
+ ### The Language Specification Submodule
11
14
 
12
15
  The language specification submodule provides functions to load the
13
16
  specification from a .mar archive(`load_language_specification_from_mar`) or a
@@ -16,7 +19,7 @@ then be used to generate python classes representing the assets and
16
19
  associations of the language and to determine the attack steps for each asset
17
20
  when generating the attack graph.
18
21
 
19
- ## The Language Classes Factory Submodule
22
+ ### The Language Classes Factory Submodule
20
23
 
21
24
  The language classes factory submodule is used to generate python classes
22
25
  using the `python_jsonschema_objects` package from a language specification.
@@ -27,19 +30,23 @@ using JSON Schema validators they will enforce their restrictions when using
27
30
  the python objects created. These classes are typically used in conjunction
28
31
  with model module to create instance models.
29
32
 
30
- # The Model Module
33
+ ## The Model Module
34
+
35
+ With a MAL language a Model (a MAL instance model) can be created either
36
+ from a model file or empty.
37
+
38
+ The model class will store all of the relevant information to the MAL
39
+ instance model, most importantly the assets and associations that make it up.
40
+
41
+ Assets and associations are objects of classes created using the language
42
+ classes factory submodule in runtime. It also allows for `Attacker` objects
43
+ to be created and associated with attack steps on assets in the model.
44
+ The most relevant methods of the Model are the ones used to add different
45
+ elements to the model, `add_asset`, `add_association`, and `add_attacker`.
31
46
 
32
- The model module is used to create MAL instance models. The model class will
33
- store all of the relevant information to the MAL instance model, most
34
- importantly the assets and associations that make it up. These assets and
35
- associations should be objects created using the language classes factory
36
- submodule. It also allows for `Attacker` objects to be created and associated
37
- with attack steps on assets in the model. The most relevant functions here are
38
- the ones used to add different elements to the model, `add_asset`,
39
- `add_association`, and `add_attacker`. Model objects can be used to generate
40
- attack graphs using the attack graph module.
47
+ Model objects can be used to generate attack graphs with the AttackGraph module.
41
48
 
42
- # The Attack Graph Module
49
+ ## The Attack Graph Module
43
50
 
44
51
  The attack graph module contains tools used to generate attack graphs from
45
52
  existing MAL instance models and analyse MAL attack graphs. The function used
@@ -57,14 +64,21 @@ resulting attack graph with the instance model given as a parameter in order
57
64
  to create attack step nodes that represent the entry points of the attackers
58
65
  and attach them to the attack steps specified in the instance model.
59
66
 
60
- # Ingestors Module
67
+ ## Ingestors Module
61
68
 
62
69
  The ingestors module contains various tools that can make use of the instance
63
70
  model or attack graph. Currently the Neo4J ingestor is the only one available
64
71
  and it can be used to visualise the instance model and the attack graph.
65
72
 
66
- # Command Line Client
67
73
 
74
+ # Usage
75
+
76
+ ## Configuration
77
+ A default configuration file `default.conf` can be found in the package
78
+ directory. This contains the default values to use for logging and can also be
79
+ used to store the information needed to access the local Neo4J instance.
80
+
81
+ ## Command Line Client
68
82
  In addition to the modules that make up the MAL-Toolbox package it also
69
83
  provides a simple command line client that can be used to easily generate
70
84
  attack graphs from a .mar language specification file and a JSON instance
@@ -76,10 +90,10 @@ The usage is: `maltoolbox gen_ag [--neo4j] <model_json_file>
76
90
  If the `--neo4j` flag is specified the model and attack graph will be loaded
77
91
  into a local Neo4J instance.
78
92
 
79
- # Configuration
80
- A default configuration file `default.conf` can be found in the package
81
- directory. This contains the default values to use for logging and can also be
82
- used to store the information needed to access the local Neo4J instance.
93
+ ## Code examples / Tutorial
94
+
95
+ To find code examples and tutorials, visit the
96
+ [MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
83
97
 
84
98
  # Tests
85
99
  There are unit tests inside of ./tests.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mal-toolbox
3
- Version: 0.0.40
3
+ Version: 0.1.1
4
4
  Summary: A collection of tools used to create MAL models and attack graphs.
5
5
  Author-email: Andrei Buhaiu <buhaiu@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Joakim Loxdal <loxdal@kth.se>
6
6
  License: Apache Software License
@@ -25,16 +25,19 @@ Requires-Dist: antlr4-python3-runtime
25
25
  Requires-Dist: docopt
26
26
  Requires-Dist: PyYAML
27
27
 
28
- # Overview
28
+ # MAL Toolbox overview
29
29
 
30
- A collection of python modules to help developers create and work with MAL
31
- models and attack graphs.
30
+ MAL Toolbox is a collection of python modules to help developers create and work with
31
+ MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
32
32
 
33
- # The Language Module
33
+ Attack graphs can be used to run simulations (see MAL Simulator) or analysis.
34
+ MAL Toolbox also gives the ability to view the AttackGraph/Model graphically in neo4j.
35
+
36
+ ## The Language Module
34
37
 
35
38
  The language module provides various tools to process MAL languages.
36
39
 
37
- ## The Language Specification Submodule
40
+ ### The Language Specification Submodule
38
41
 
39
42
  The language specification submodule provides functions to load the
40
43
  specification from a .mar archive(`load_language_specification_from_mar`) or a
@@ -43,7 +46,7 @@ then be used to generate python classes representing the assets and
43
46
  associations of the language and to determine the attack steps for each asset
44
47
  when generating the attack graph.
45
48
 
46
- ## The Language Classes Factory Submodule
49
+ ### The Language Classes Factory Submodule
47
50
 
48
51
  The language classes factory submodule is used to generate python classes
49
52
  using the `python_jsonschema_objects` package from a language specification.
@@ -54,19 +57,23 @@ using JSON Schema validators they will enforce their restrictions when using
54
57
  the python objects created. These classes are typically used in conjunction
55
58
  with model module to create instance models.
56
59
 
57
- # The Model Module
60
+ ## The Model Module
61
+
62
+ With a MAL language a Model (a MAL instance model) can be created either
63
+ from a model file or empty.
64
+
65
+ The model class will store all of the relevant information to the MAL
66
+ instance model, most importantly the assets and associations that make it up.
67
+
68
+ Assets and associations are objects of classes created using the language
69
+ classes factory submodule in runtime. It also allows for `Attacker` objects
70
+ to be created and associated with attack steps on assets in the model.
71
+ The most relevant methods of the Model are the ones used to add different
72
+ elements to the model, `add_asset`, `add_association`, and `add_attacker`.
58
73
 
59
- The model module is used to create MAL instance models. The model class will
60
- store all of the relevant information to the MAL instance model, most
61
- importantly the assets and associations that make it up. These assets and
62
- associations should be objects created using the language classes factory
63
- submodule. It also allows for `Attacker` objects to be created and associated
64
- with attack steps on assets in the model. The most relevant functions here are
65
- the ones used to add different elements to the model, `add_asset`,
66
- `add_association`, and `add_attacker`. Model objects can be used to generate
67
- attack graphs using the attack graph module.
74
+ Model objects can be used to generate attack graphs with the AttackGraph module.
68
75
 
69
- # The Attack Graph Module
76
+ ## The Attack Graph Module
70
77
 
71
78
  The attack graph module contains tools used to generate attack graphs from
72
79
  existing MAL instance models and analyse MAL attack graphs. The function used
@@ -84,14 +91,21 @@ resulting attack graph with the instance model given as a parameter in order
84
91
  to create attack step nodes that represent the entry points of the attackers
85
92
  and attach them to the attack steps specified in the instance model.
86
93
 
87
- # Ingestors Module
94
+ ## Ingestors Module
88
95
 
89
96
  The ingestors module contains various tools that can make use of the instance
90
97
  model or attack graph. Currently the Neo4J ingestor is the only one available
91
98
  and it can be used to visualise the instance model and the attack graph.
92
99
 
93
- # Command Line Client
94
100
 
101
+ # Usage
102
+
103
+ ## Configuration
104
+ A default configuration file `default.conf` can be found in the package
105
+ directory. This contains the default values to use for logging and can also be
106
+ used to store the information needed to access the local Neo4J instance.
107
+
108
+ ## Command Line Client
95
109
  In addition to the modules that make up the MAL-Toolbox package it also
96
110
  provides a simple command line client that can be used to easily generate
97
111
  attack graphs from a .mar language specification file and a JSON instance
@@ -103,10 +117,10 @@ The usage is: `maltoolbox gen_ag [--neo4j] <model_json_file>
103
117
  If the `--neo4j` flag is specified the model and attack graph will be loaded
104
118
  into a local Neo4J instance.
105
119
 
106
- # Configuration
107
- A default configuration file `default.conf` can be found in the package
108
- directory. This contains the default values to use for logging and can also be
109
- used to store the information needed to access the local Neo4J instance.
120
+ ## Code examples / Tutorial
121
+
122
+ To find code examples and tutorials, visit the
123
+ [MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
110
124
 
111
125
  # Tests
112
126
  There are unit tests inside of ./tests.
@@ -19,7 +19,9 @@ maltoolbox/attackgraph/attacker.py
19
19
  maltoolbox/attackgraph/attackgraph.py
20
20
  maltoolbox/attackgraph/node.py
21
21
  maltoolbox/attackgraph/query.py
22
+ maltoolbox/attackgraph/analyzers/__init__.py
22
23
  maltoolbox/attackgraph/analyzers/apriori.py
24
+ maltoolbox/ingestors/__init__.py
23
25
  maltoolbox/ingestors/neo4j.py
24
26
  maltoolbox/language/__init__.py
25
27
  maltoolbox/language/classes_factory.py
@@ -29,5 +31,8 @@ maltoolbox/language/compiler/__init__.py
29
31
  maltoolbox/language/compiler/mal_lexer.py
30
32
  maltoolbox/language/compiler/mal_parser.py
31
33
  maltoolbox/language/compiler/mal_visitor.py
34
+ maltoolbox/translators/__init__.py
32
35
  maltoolbox/translators/securicad.py
33
- tests/test_model.py
36
+ maltoolbox/translators/updater.py
37
+ tests/test_model.py
38
+ tests/test_wrappers.py
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # MAL Toolbox v0.0.40
2
+ # MAL Toolbox v0.1.1
3
3
  # Copyright 2024, 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__ = '0.0.40'
24
+ __version__ = '0.1.1'
25
25
  __authors__ = ['Andrei Buhaiu',
26
26
  'Giuseppe Nebbione',
27
27
  'Nikolaos Kakouros',
@@ -33,7 +33,6 @@ __docformat__ = 'restructuredtext en'
33
33
  __all__ = ()
34
34
 
35
35
  import os
36
- import sys
37
36
  import configparser
38
37
  import logging
39
38
 
@@ -74,15 +73,18 @@ log_level = log_configs['log_level']
74
73
  if log_level != '':
75
74
  level = logging.getLevelName(log_level)
76
75
  logger.setLevel(level)
77
- logger.info(f'Set loggin level of {__name__} to {log_level}.')
76
+ logger.info('Set loggin level of %s to %s.', __name__, log_level)
78
77
 
79
78
  if 'neo4j' in config:
80
79
  for term in ['uri', 'username', 'password', 'dbname']:
81
80
  if term not in config['neo4j']:
82
- logger.critical('Config file is missing essential '\
83
- f'Neo4J information: {term}, cannot proceed.')
84
- raise ValueError('Config file is missing essential '\
85
- f'Neo4J information: {term}, cannot proceed.')
81
+
82
+ msg = (
83
+ 'Config file is missing essential Neo4J '
84
+ f'information: {term}, cannot proceed.'
85
+ )
86
+ logger.critical(msg)
87
+ raise ValueError(msg)
86
88
 
87
89
  neo4j_configs = {
88
90
  'uri': config['neo4j']['uri'],
@@ -90,4 +92,3 @@ if 'neo4j' in config:
90
92
  'password': config['neo4j']['password'],
91
93
  'dbname': config['neo4j']['dbname'],
92
94
  }
93
-
@@ -68,10 +68,9 @@ def generate_attack_graph(
68
68
  delete=False)
69
69
 
70
70
 
71
- def compile(lang_file, output_file):
71
+ def compile(lang_file: str, output_file: str) -> None:
72
72
  """Compile language and dump into output file"""
73
73
  compiler = MalCompiler()
74
-
75
74
  with open(output_file, "w") as f:
76
75
  json.dump(compiler.compile(lang_file), f, indent=2)
77
76
 
@@ -1,5 +1,3 @@
1
- from __future__ import annotations
2
-
3
1
  """
4
2
  MAL-Toolbox Attack Graph Apriori Analyzer Submodule
5
3
 
@@ -13,6 +11,7 @@ Currently these are:
13
11
  compromised) to compromise children attack steps.
14
12
  """
15
13
 
14
+ from __future__ import annotations
16
15
  import logging
17
16
 
18
17
  from ..attackgraph import AttackGraph
@@ -20,14 +19,16 @@ from ..node import AttackGraphNode
20
19
 
21
20
  logger = logging.getLogger(__name__)
22
21
 
23
- def propagate_viability_from_node(node: AttackGraphNode):
22
+ def propagate_viability_from_node(node: AttackGraphNode) -> None:
24
23
  """
25
24
  Arguments:
26
25
  node - the attack graph node from which to propagate the viable
27
26
  status
28
27
  """
29
- logger.debug(f'Propagate viability from {node.id} with viability'
30
- f' status {node.is_viable}.')
28
+ logger.debug(
29
+ 'Propagate viability from "%s"(%d) with viability status %s.',
30
+ node.full_name, node.id, node.is_viable
31
+ )
31
32
  for child in node.children:
32
33
  original_value = child.is_viable
33
34
  if child.type == 'or':
@@ -40,14 +41,16 @@ def propagate_viability_from_node(node: AttackGraphNode):
40
41
  if child.is_viable != original_value:
41
42
  propagate_viability_from_node(child)
42
43
 
43
- def propagate_necessity_from_node(node: AttackGraphNode):
44
+ def propagate_necessity_from_node(node: AttackGraphNode) -> None:
44
45
  """
45
46
  Arguments:
46
47
  node - the attack graph node from which to propagate the necessary
47
48
  status
48
49
  """
49
- logger.debug(f'Propagate necessity from {node.id} with necessity'
50
- f' status {node.is_necessary}.')
50
+ logger.debug(
51
+ 'Propagate necessity from "%s"(%d) with necessity status %s.',
52
+ node.full_name, node.id, node.is_necessary
53
+ )
51
54
  for child in node.children:
52
55
  original_value = child.is_necessary
53
56
  if child.type == 'or':
@@ -63,17 +66,24 @@ def propagate_necessity_from_node(node: AttackGraphNode):
63
66
  propagate_necessity_from_node(child)
64
67
 
65
68
 
66
- def evaluate_viability(node):
69
+ def evaluate_viability(node: AttackGraphNode) -> None:
67
70
  """
68
71
  Arguments:
69
72
  graph - the node to evaluate viability for.
70
73
  """
71
74
  match (node.type):
72
75
  case 'exist':
76
+ assert isinstance(node.existence_status, bool), \
77
+ f'Existence status not defined for {node.full_name}.'
73
78
  node.is_viable = node.existence_status
74
79
  case 'notExist':
80
+ assert isinstance(node.existence_status, bool), \
81
+ f'Existence status not defined for {node.full_name}.'
75
82
  node.is_viable = not node.existence_status
76
83
  case 'defense':
84
+ assert node.defense_status is not None and \
85
+ 0.0 <= node.defense_status <= 1.0, \
86
+ f'{node.full_name} defense status invalid: {node.defense_status}.'
77
87
  node.is_viable = node.defense_status != 1.0
78
88
  case 'or':
79
89
  node.is_viable = False
@@ -84,22 +94,29 @@ def evaluate_viability(node):
84
94
  for parent in node.parents:
85
95
  node.is_viable = node.is_viable and parent.is_viable
86
96
  case _:
87
- msg = f'Evaluate viability was provided node \"node.id\" which '\
88
- f'is of unknown type \"{node.type}\"'
89
- logger.error(msg)
90
- raise ValueError(msg)
97
+ msg = ('Evaluate viability was provided node "%s"(%d) which '
98
+ 'is of unknown type "%s"')
99
+ logger.error(msg, node.full_name, node.id, node.type)
100
+ raise ValueError(msg % (node.full_name, node.id, node.type))
91
101
 
92
- def evaluate_necessity(node):
102
+ def evaluate_necessity(node: AttackGraphNode) -> None:
93
103
  """
94
104
  Arguments:
95
105
  graph - the node to evaluate necessity for.
96
106
  """
97
107
  match (node.type):
98
108
  case 'exist':
109
+ assert isinstance(node.existence_status, bool), \
110
+ f'Existence status not defined for {node.full_name}.'
99
111
  node.is_necessary = not node.existence_status
100
112
  case 'notExist':
101
- node.is_necessary = node.existence_status
113
+ assert isinstance(node.existence_status, bool), \
114
+ f'Existence status not defined for {node.full_name}.'
115
+ node.is_necessary = bool(node.existence_status)
102
116
  case 'defense':
117
+ assert node.defense_status is not None and \
118
+ 0.0 <= node.defense_status <= 1.0, \
119
+ f'{node.full_name} defense status invalid: {node.defense_status}.'
103
120
  node.is_necessary = node.defense_status != 0.0
104
121
  case 'or':
105
122
  node.is_necessary = True
@@ -110,12 +127,12 @@ def evaluate_necessity(node):
110
127
  for parent in node.parents:
111
128
  node.is_necessary = node.is_necessary or parent.is_necessary
112
129
  case _:
113
- msg = f'Evaluate necessity was provided node \"node.id\" which '\
114
- f'is of unknown type \"{node.type}\"'
115
- logger.error(msg)
116
- raise ValueError(msg)
130
+ msg = ('Evaluate necessity was provided node "%s"(%d) which '
131
+ 'is of unknown type "%s"')
132
+ logger.error(msg, node.full_name, node.id, node.type)
133
+ raise ValueError(msg % (node.full_name, node.id, node.type))
117
134
 
118
- def evaluate_viability_and_necessity(node):
135
+ def evaluate_viability_and_necessity(node: AttackGraphNode) -> None:
119
136
  """
120
137
  Arguments:
121
138
  graph - the node to evaluate viability and necessity for.
@@ -123,7 +140,7 @@ def evaluate_viability_and_necessity(node):
123
140
  evaluate_viability(node)
124
141
  evaluate_necessity(node)
125
142
 
126
- def calculate_viability_and_necessity(graph: AttackGraph):
143
+ def calculate_viability_and_necessity(graph: AttackGraph) -> None:
127
144
  """
128
145
  Arguments:
129
146
  graph - the attack graph for which we wish to determine the
@@ -137,7 +154,7 @@ def calculate_viability_and_necessity(graph: AttackGraph):
137
154
  if not node.is_necessary:
138
155
  propagate_necessity_from_node(node)
139
156
 
140
- def prune_unviable_and_unnecessary_nodes(graph: AttackGraph):
157
+ def prune_unviable_and_unnecessary_nodes(graph: AttackGraph) -> None:
141
158
  """
142
159
  Arguments:
143
160
  graph - the attack graph for which we wish to remove the
@@ -0,0 +1,102 @@
1
+ """
2
+ MAL-Toolbox Attack Graph Attacker Class
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from dataclasses import dataclass, field
7
+ import logging
8
+
9
+ from typing import Optional
10
+ from typing import TYPE_CHECKING
11
+ if TYPE_CHECKING:
12
+ from .attackgraph import AttackGraphNode
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ @dataclass
17
+ class Attacker:
18
+ name: str
19
+ entry_points: list[AttackGraphNode] = field(default_factory=list)
20
+ reached_attack_steps: list[AttackGraphNode] = \
21
+ field(default_factory=list)
22
+ id: Optional[int] = None
23
+
24
+ def to_dict(self) -> dict:
25
+ attacker_dict: dict = {
26
+ 'id': self.id,
27
+ 'name': self.name,
28
+ 'entry_points': {},
29
+ 'reached_attack_steps': {}
30
+ }
31
+
32
+ for entry_point in self.entry_points:
33
+ attacker_dict['entry_points'][entry_point.id] = \
34
+ entry_point.full_name
35
+ for attack_step in self.reached_attack_steps:
36
+ attacker_dict['reached_attack_steps'][attack_step.id] = \
37
+ attack_step.full_name
38
+
39
+ return attacker_dict
40
+
41
+ def __repr__(self) -> str:
42
+ return str(self.to_dict())
43
+
44
+ def compromise(self, node: AttackGraphNode) -> None:
45
+ """
46
+ Have the attacke compromise the node given as a parameter.
47
+
48
+ Arguments:
49
+ node - the node that the attacker will compromise
50
+ """
51
+
52
+ logger.debug(
53
+ 'Attacker "%s"(%d) is compromising node "%s"(%d).',
54
+ self.name,
55
+ self.id,
56
+ node.full_name,
57
+ node.id
58
+ )
59
+ if node.is_compromised_by(self):
60
+ logger.info(
61
+ 'Attacker "%s"(%d) already compromised node "%s"(%d). '
62
+ 'Do nothing.',
63
+ self.name,
64
+ self.id,
65
+ node.full_name,
66
+ node.id
67
+ )
68
+ return
69
+
70
+ node.compromised_by.append(self)
71
+ self.reached_attack_steps.append(node)
72
+
73
+ def undo_compromise(self, node: AttackGraphNode) -> None:
74
+ """
75
+ Remove the attacker from the list of attackers that have compromised
76
+ the node given as a parameter.
77
+
78
+ Arguments:
79
+ node - the node that we wish to remove this attacker from.
80
+ """
81
+
82
+ logger.debug(
83
+ 'Removing attacker "%s"(%d) from compromised_by '
84
+ 'list of node "%s"(%d).',
85
+ self.name,
86
+ self.id,
87
+ node.full_name,
88
+ node.id
89
+ )
90
+ if not node.is_compromised_by(self):
91
+ logger.info(
92
+ 'Attacker "%s"(%d) had not compromised node "%s"(%d).'
93
+ ' Do nothing.',
94
+ self.name,
95
+ self.id,
96
+ node.full_name,
97
+ node.id
98
+ )
99
+ return
100
+
101
+ node.compromised_by.remove(self)
102
+ self.reached_attack_steps.remove(node)