1
1
import re
2
2
3
- from typing import List , Dict
3
+ from typing import List , Dict , Set
4
4
5
- from assemblyline .common .dict_utils import flatten
5
+ from assemblyline .common .forge import CachedObject , get_datastore
6
6
from assemblyline .odm .models .tagging import Tagging
7
7
8
8
@@ -16,22 +16,33 @@ def tag_list_to_dict(tag_list: List[Dict]) -> Dict:
16
16
return tag_dict
17
17
18
18
19
- def tag_dict_to_list (tag_dict : Dict ) -> List [Dict ]:
19
+ def tag_dict_to_list (tag_dict : Dict , safelisted : bool = False ) -> List [Dict ]:
20
20
return [
21
- {'type' : k , 'value' : t , 'short_type' : k .rsplit ("." , 1 )[- 1 ]}
22
- for k , v in flatten ( tag_dict ) .items ()
21
+ {'safelisted' : safelisted , ' type' : k , 'value' : t , 'short_type' : k .rsplit ("." , 1 )[- 1 ]}
22
+ for k , v in tag_dict .items ()
23
23
if v is not None
24
24
for t in v
25
25
]
26
26
27
27
28
- class InvalidWhitelist (Exception ):
28
+ def get_safelist_key (t_type : str , t_value : str ) -> str :
29
+ return f"{ t_type } __{ t_value } "
30
+
31
+
32
+ def get_safelist (ds ) -> Set :
33
+ return {get_safelist_key (sl ['tag' ]['type' ], sl ['tag' ]['value' ]): True
34
+ for sl in ds .safelist .stream_search ("type:tag AND enabled:true" , as_obj = False )}
35
+
36
+
37
+ class InvalidSafelist (Exception ):
29
38
pass
30
39
31
40
32
- class TagWhitelister (object ):
41
+ class TagSafelister (object ):
33
42
def __init__ (self , data , log = None ):
34
43
valid_tags = set (Tagging .flat_fields ().keys ())
44
+ self .datastore = get_datastore ()
45
+ self .safelist = CachedObject (get_safelist , kwargs = {'ds' : self .datastore }, refresh = 300 )
35
46
36
47
self .match = data .get ('match' , {})
37
48
self .regex = data .get ('regex' , {})
@@ -40,38 +51,62 @@ def __init__(self, data, log=None):
40
51
# Validate matches and regex
41
52
for section , item in {'match' : self .match , 'regex' : self .regex }.items ():
42
53
if not isinstance (item , dict ):
43
- raise InvalidWhitelist (f"Section { section } should be of type: DICT" )
54
+ raise InvalidSafelist (f"Section { section } should be of type: DICT" )
44
55
45
56
for k , v in item .items ():
46
57
if not isinstance (v , list ):
47
- raise InvalidWhitelist (f"Values in the { section } section should all be of type: LIST" )
58
+ raise InvalidSafelist (f"Values in the { section } section should all be of type: LIST" )
48
59
49
60
if k not in valid_tags :
50
- raise InvalidWhitelist (f"Key ({ k } ) in the { section } section is not a valid tag." )
61
+ raise InvalidSafelist (f"Key ({ k } ) in the { section } section is not a valid tag." )
51
62
52
63
if section == 'regex' :
53
64
self .regex [k ] = [re .compile (x ) for x in v ]
54
65
55
- def is_whitelisted (self , t_type , t_value ):
66
+ def is_safelisted (self , t_type , t_value ):
67
+ if self .safelist .get (get_safelist_key (t_type , t_value ), False ):
68
+ if self .log :
69
+ self .log .info (f"Tag '{ t_type } ' with value '{ t_value } ' was safelisted." )
70
+ return True
71
+
56
72
for match in self .match .get (t_type , []):
57
73
if t_value == match :
58
74
if self .log :
59
- self .log .info (f"Tag '{ t_type } ' with value '{ t_value } ' was whitelisted by match rule." )
75
+ self .log .info (f"Tag '{ t_type } ' with value '{ t_value } ' was safelisted by match rule." )
60
76
return True
61
77
62
78
for regex in self .regex .get (t_type , []):
63
79
if regex .match (t_value ):
64
80
if self .log :
65
81
self .log .info (f"Tag '{ t_type } ' with value '{ t_value } ' "
66
- f"was whitelisted by regex '{ regex .pattern } '." )
82
+ f"was safelisted by regex '{ regex .pattern } '." )
67
83
return True
68
84
69
85
return False
70
86
71
- def whitelist_many (self , t_type , t_values ):
87
+ def safelist_many (self , t_type , t_values ):
72
88
if not isinstance (t_values , list ):
73
89
t_values = [t_values ]
74
- return [x for x in t_values if not self .is_whitelisted (t_type , x )]
90
+
91
+ tags = []
92
+ safelisted_tags = []
93
+ for x in t_values :
94
+ if self .is_safelisted (t_type , x ):
95
+ safelisted_tags .append (x )
96
+ else :
97
+ tags .append (x )
98
+
99
+ return tags , safelisted_tags
75
100
76
101
def get_validated_tag_map (self , tag_map ):
77
- return {k : self .whitelist_many (k , v ) for k , v in tag_map .items () if v is not None }
102
+ tags = {}
103
+ safelisted_tags = {}
104
+ for k , v in tag_map .items ():
105
+ if v is not None and v != []:
106
+ c_tags , c_safelisted_tags = self .safelist_many (k , v )
107
+ if c_tags :
108
+ tags [k ] = c_tags
109
+ if c_safelisted_tags :
110
+ safelisted_tags [k ] = c_safelisted_tags
111
+
112
+ return tags , safelisted_tags
0 commit comments