mal-toolbox 0.1.12__py3-none-any.whl → 0.2.0__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.
- {mal_toolbox-0.1.12.dist-info → mal_toolbox-0.2.0.dist-info}/METADATA +1 -1
- {mal_toolbox-0.1.12.dist-info → mal_toolbox-0.2.0.dist-info}/RECORD +15 -15
- maltoolbox/__init__.py +2 -2
- maltoolbox/attackgraph/analyzers/apriori.py +4 -1
- maltoolbox/attackgraph/attackgraph.py +294 -245
- maltoolbox/attackgraph/node.py +23 -7
- maltoolbox/file_utils.py +6 -2
- maltoolbox/language/__init__.py +5 -1
- maltoolbox/language/classes_factory.py +86 -70
- maltoolbox/language/languagegraph.py +1022 -475
- maltoolbox/model.py +44 -35
- {mal_toolbox-0.1.12.dist-info → mal_toolbox-0.2.0.dist-info}/AUTHORS +0 -0
- {mal_toolbox-0.1.12.dist-info → mal_toolbox-0.2.0.dist-info}/LICENSE +0 -0
- {mal_toolbox-0.1.12.dist-info → mal_toolbox-0.2.0.dist-info}/WHEEL +0 -0
- {mal_toolbox-0.1.12.dist-info → mal_toolbox-0.2.0.dist-info}/top_level.txt +0 -0
maltoolbox/model.py
CHANGED
|
@@ -296,7 +296,7 @@ class Model():
|
|
|
296
296
|
"""
|
|
297
297
|
|
|
298
298
|
# Optimization: only look for duplicates in associations of same type
|
|
299
|
-
association_type = association.
|
|
299
|
+
association_type = association.type
|
|
300
300
|
associations_same_type = self._type_to_association.get(
|
|
301
301
|
association_type, []
|
|
302
302
|
)
|
|
@@ -371,7 +371,7 @@ class Model():
|
|
|
371
371
|
self.associations.append(association)
|
|
372
372
|
|
|
373
373
|
# Add association to type->association mapping
|
|
374
|
-
association_type = association.
|
|
374
|
+
association_type = association.type
|
|
375
375
|
self._type_to_association.setdefault(
|
|
376
376
|
association_type, []
|
|
377
377
|
).append(association)
|
|
@@ -411,7 +411,7 @@ class Model():
|
|
|
411
411
|
self.associations.remove(association)
|
|
412
412
|
|
|
413
413
|
# Remove association from type->association mapping
|
|
414
|
-
association_type = association.
|
|
414
|
+
association_type = association.type
|
|
415
415
|
self._type_to_association[association_type].remove(
|
|
416
416
|
association
|
|
417
417
|
)
|
|
@@ -556,8 +556,9 @@ class Model():
|
|
|
556
556
|
defenses = {}
|
|
557
557
|
for key, value in asset._properties.items():
|
|
558
558
|
property_schema = (
|
|
559
|
-
self.lang_classes_factory.json_schema['definitions']
|
|
560
|
-
['
|
|
559
|
+
self.lang_classes_factory.json_schema['definitions']
|
|
560
|
+
['LanguageAsset'] ['definitions']
|
|
561
|
+
['Asset_' + asset.type]['properties'][key]
|
|
561
562
|
)
|
|
562
563
|
|
|
563
564
|
if "maximum" not in property_schema:
|
|
@@ -592,7 +593,7 @@ class Model():
|
|
|
592
593
|
A two item list containing the field names of the association.
|
|
593
594
|
"""
|
|
594
595
|
|
|
595
|
-
return association._properties.keys()
|
|
596
|
+
return list(association._properties.keys())[1:]
|
|
596
597
|
|
|
597
598
|
|
|
598
599
|
def get_associated_assets_by_field_name(
|
|
@@ -611,27 +612,14 @@ class Model():
|
|
|
611
612
|
A list of assets associated with the asset given that match the
|
|
612
613
|
field_name.
|
|
613
614
|
"""
|
|
614
|
-
|
|
615
615
|
logger.debug(
|
|
616
616
|
'Get associated assets for asset "%s"(%d) by field name %s.',
|
|
617
617
|
asset.name, asset.id, field_name
|
|
618
618
|
)
|
|
619
619
|
associated_assets = []
|
|
620
620
|
for association in asset.associations:
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
left_field_name, right_field_name = \
|
|
624
|
-
self.get_association_field_names(association)
|
|
625
|
-
|
|
626
|
-
if asset in getattr(association, left_field_name):
|
|
627
|
-
opposite_field_name = right_field_name
|
|
628
|
-
else:
|
|
629
|
-
opposite_field_name = left_field_name
|
|
630
|
-
|
|
631
|
-
if opposite_field_name == field_name:
|
|
632
|
-
associated_assets.extend(
|
|
633
|
-
getattr(association, opposite_field_name)
|
|
634
|
-
)
|
|
621
|
+
if hasattr(association, field_name):
|
|
622
|
+
associated_assets.extend(getattr(association, field_name))
|
|
635
623
|
|
|
636
624
|
return associated_assets
|
|
637
625
|
|
|
@@ -683,12 +671,12 @@ class Model():
|
|
|
683
671
|
right_field = getattr(association, right_field_name)
|
|
684
672
|
|
|
685
673
|
association_dict = {
|
|
686
|
-
association.
|
|
674
|
+
str(association.type) :
|
|
687
675
|
{
|
|
688
676
|
str(left_field_name):
|
|
689
|
-
|
|
677
|
+
{int(asset.id): str(asset.name) for asset in left_field},
|
|
690
678
|
str(right_field_name):
|
|
691
|
-
|
|
679
|
+
{int(asset.id): str(asset.name) for asset in right_field}
|
|
692
680
|
}
|
|
693
681
|
}
|
|
694
682
|
|
|
@@ -713,7 +701,8 @@ class Model():
|
|
|
713
701
|
'entry_points': {},
|
|
714
702
|
}
|
|
715
703
|
for (asset, attack_steps) in attacker.entry_points:
|
|
716
|
-
attacker_dict['entry_points'][
|
|
704
|
+
attacker_dict['entry_points'][str(asset.name)] = {
|
|
705
|
+
'asset_id': int(asset.id),
|
|
717
706
|
'attack_steps' : attack_steps
|
|
718
707
|
}
|
|
719
708
|
return (attacker.id, attacker_dict)
|
|
@@ -797,8 +786,16 @@ class Model():
|
|
|
797
786
|
}
|
|
798
787
|
)
|
|
799
788
|
|
|
800
|
-
|
|
801
|
-
asset_object['type'])
|
|
789
|
+
asset_type_class = model.lang_classes_factory.get_asset_class(
|
|
790
|
+
asset_object['type'])
|
|
791
|
+
|
|
792
|
+
# TODO: remove this when factory goes away
|
|
793
|
+
asset_type_class.__hash__ = lambda self: hash(self.name) # type: ignore[method-assign,misc]
|
|
794
|
+
|
|
795
|
+
if asset_type_class is None:
|
|
796
|
+
raise LookupError('Failed to find asset "%s" in language'
|
|
797
|
+
' classes factory' % asset_object['type'])
|
|
798
|
+
asset = asset_type_class(name = asset_object['name'])
|
|
802
799
|
|
|
803
800
|
if 'extras' in asset_object:
|
|
804
801
|
asset.extras = asset_object['extras']
|
|
@@ -810,12 +807,20 @@ class Model():
|
|
|
810
807
|
|
|
811
808
|
# Reconstruct the associations
|
|
812
809
|
for assoc_entry in serialized_object.get('associations', []):
|
|
813
|
-
assoc =
|
|
814
|
-
|
|
815
|
-
|
|
810
|
+
[(assoc, assoc_fields)] = assoc_entry.items()
|
|
811
|
+
assoc_keys_iter = iter(assoc_fields)
|
|
812
|
+
field1 = next(assoc_keys_iter)
|
|
813
|
+
field2 = next(assoc_keys_iter)
|
|
814
|
+
assoc_type_class = model.lang_classes_factory.\
|
|
815
|
+
get_association_class_by_fieldnames(assoc, field1, field2)
|
|
816
|
+
if assoc_type_class is None:
|
|
817
|
+
raise LookupError('Failed to find association "%s" with '
|
|
818
|
+
'fields "%s" and "%s" in language classes factory' %
|
|
819
|
+
(assoc, field1, field2)
|
|
820
|
+
)
|
|
821
|
+
association = assoc_type_class()
|
|
816
822
|
|
|
817
823
|
for field, targets in assoc_fields.items():
|
|
818
|
-
targets = targets if isinstance(targets, list) else [targets]
|
|
819
824
|
setattr(
|
|
820
825
|
association,
|
|
821
826
|
field,
|
|
@@ -832,11 +837,15 @@ class Model():
|
|
|
832
837
|
for attacker_id in attackers_info:
|
|
833
838
|
attacker = AttackerAttachment(name = attackers_info[attacker_id]['name'])
|
|
834
839
|
attacker.entry_points = []
|
|
835
|
-
for
|
|
840
|
+
for asset_name, entry_points_dict in \
|
|
841
|
+
attackers_info[attacker_id]['entry_points'].items():
|
|
836
842
|
attacker.entry_points.append(
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
843
|
+
(
|
|
844
|
+
model.get_asset_by_id(
|
|
845
|
+
entry_points_dict['asset_id']),
|
|
846
|
+
entry_points_dict['attack_steps']
|
|
847
|
+
)
|
|
848
|
+
)
|
|
840
849
|
model.add_attacker(attacker, attacker_id = int(attacker_id))
|
|
841
850
|
return model
|
|
842
851
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|