11import copy
22from spaceone .inventory .plugin .collector .lib import *
33from ..base import ResourceManager
4- from ...conf .cloud_service_conf import ASSET_URL , INSTANCE_FILTERS , DEFAULT_VULNERABLE_PORTS
4+ from ...conf .cloud_service_conf import (
5+ ASSET_URL ,
6+ INSTANCE_FILTERS ,
7+ DEFAULT_VULNERABLE_PORTS ,
8+ )
59from plugin .error .custom import ERROR_VULNERABLE_PORTS
610
711
@@ -16,6 +20,7 @@ def __init__(self, *args, **kwargs):
1620 self .cloud_service_type = "SecurityGroup"
1721 self .metadata_path = "metadata/ec2/sg.yaml"
1822 self .include_vpc_default = False
23+ self .sg_rules_for_this_group = []
1924
2025 def create_cloud_service_type (self ):
2126 result = []
@@ -50,9 +55,23 @@ def create_cloud_service(self, region, options, secret_data, schema):
5055 account_id = options .get ("account_id" , "" )
5156 self .connector .load_account_id (account_id )
5257
58+ # Get Security Group Rules Detail
59+ sg_rules_detail = self .connector .get_security_group_rules ()
60+
61+ sg_rules_map = {}
62+ for data in sg_rules_detail :
63+ for rule in data .get ("SecurityGroupRules" , []):
64+ group_id = rule .get ("GroupId" )
65+ if group_id not in sg_rules_map :
66+ sg_rules_map [group_id ] = []
67+ sg_rules_map [group_id ].append (rule )
68+
5369 for data in results :
5470 for raw in data .get ("SecurityGroups" , []):
5571 try :
72+ group_id = raw .get ("GroupId" , "" )
73+ self .sg_rules_for_this_group = sg_rules_map .get (group_id , [])
74+
5675 if (
5776 self .include_vpc_default is False
5877 and raw .get ("VpcId" ) in default_vpcs
@@ -62,75 +81,94 @@ def create_cloud_service(self, region, options, secret_data, schema):
6281 # Inbound Rules
6382 inbound_rules = []
6483 for in_rule in raw .get ("IpPermissions" , []):
84+ in_rule_copy = copy .deepcopy (in_rule )
85+
6586 for _ip_range in in_rule .get ("IpRanges" , []):
66- in_rule_copy = copy .deepcopy (in_rule )
6787 inbound_rules .append (
68- self .custom_security_group_inbound_rule_info (
69- in_rule_copy , _ip_range , "ip_ranges" ,vulnerable_ports
88+ self ._custom_security_group_inbound_rule_info (
89+ raw_rule = in_rule_copy ,
90+ remote = _ip_range ,
91+ remote_type = "ip_ranges" ,
92+ is_egress = False ,
93+ vulnerable_ports = vulnerable_ports ,
7094 )
7195 )
7296
7397 for _user_group_pair in in_rule .get ("UserIdGroupPairs" , []):
74- in_rule_copy = copy .deepcopy (in_rule )
7598 inbound_rules .append (
76- self .custom_security_group_inbound_rule_info (
77- in_rule_copy ,
78- _user_group_pair ,
79- "user_id_group_pairs" ,
80- vulnerable_ports ,
99+ self ._custom_security_group_inbound_rule_info (
100+ raw_rule = in_rule_copy ,
101+ remote = _user_group_pair ,
102+ remote_type = "user_id_group_pairs" ,
103+ is_egress = False ,
104+ vulnerable_ports = vulnerable_ports ,
81105 )
82106 )
83107
84108 for _ip_v6_range in in_rule .get ("Ipv6Ranges" , []):
85- in_rule_copy = copy .deepcopy (in_rule )
86109 inbound_rules .append (
87- self .custom_security_group_inbound_rule_info (
88- in_rule_copy , _ip_v6_range , "ipv6_ranges" ,vulnerable_ports
110+ self ._custom_security_group_inbound_rule_info (
111+ raw_rule = in_rule_copy ,
112+ remote = _ip_v6_range ,
113+ remote_type = "ipv6_ranges" ,
114+ is_egress = False ,
115+ vulnerable_ports = vulnerable_ports ,
89116 )
90117 )
91118
92119 for prefix_list_id in in_rule .get ("PrefixListIds" , []):
93- in_rule_copy = copy .deepcopy (in_rule )
94120 inbound_rules .append (
95- self .custom_security_group_inbound_rule_info (
96- in_rule_copy , prefix_list_id , "prefix_list_ids" ,vulnerable_ports
121+ self ._custom_security_group_inbound_rule_info (
122+ raw_rule = in_rule_copy ,
123+ remote = prefix_list_id ,
124+ remote_type = "prefix_list_ids" ,
125+ is_egress = False ,
126+ vulnerable_ports = vulnerable_ports ,
97127 )
98128 )
99129
100130 # Outbound Rules
101131 outbound_rules = []
102132 for out_rule in raw .get ("IpPermissionsEgress" , []):
133+ out_rule_copy = copy .deepcopy (out_rule )
134+
103135 for _ip_range in out_rule .get ("IpRanges" , []):
104- out_rule_copy = copy .deepcopy (out_rule )
105136 outbound_rules .append (
106- self .custom_security_group_rule_info (
107- out_rule_copy , _ip_range , "ip_ranges"
137+ self ._custom_security_group_inbound_rule_info (
138+ raw_rule = out_rule_copy ,
139+ remote = _ip_range ,
140+ remote_type = "ip_ranges" ,
141+ is_egress = True ,
108142 )
109143 )
110144
111145 for _user_group_pairs in out_rule .get ("UserIdGroupPairs" , []):
112- out_rule_copy = copy .deepcopy (out_rule )
113146 outbound_rules .append (
114- self .custom_security_group_rule_info (
115- out_rule_copy ,
116- _user_group_pairs ,
117- "user_id_group_pairs" ,
147+ self ._custom_security_group_inbound_rule_info (
148+ raw_rule = out_rule_copy ,
149+ remote = _user_group_pairs ,
150+ remote_type = "user_id_group_pairs" ,
151+ is_egress = True ,
118152 )
119153 )
120154
121155 for _ip_v6_range in out_rule .get ("Ipv6Ranges" , []):
122- out_rule_copy = copy .deepcopy (out_rule )
123156 outbound_rules .append (
124- self .custom_security_group_rule_info (
125- out_rule_copy , _ip_v6_range , "ipv6_ranges"
157+ self ._custom_security_group_inbound_rule_info (
158+ raw_rule = out_rule_copy ,
159+ remote = _ip_v6_range ,
160+ remote_type = "ipv6_ranges" ,
161+ is_egress = True ,
126162 )
127163 )
128164
129165 for prefix_list_id in out_rule .get ("PrefixListIds" , []):
130- out_rule_copy = copy .deepcopy (out_rule )
131166 outbound_rules .append (
132- self .custom_security_group_rule_info (
133- out_rule_copy , prefix_list_id , "prefix_list_ids"
167+ self ._custom_security_group_inbound_rule_info (
168+ raw_rule = out_rule_copy ,
169+ remote = prefix_list_id ,
170+ remote_type = "prefix_list_ids" ,
171+ is_egress = True ,
134172 )
135173 )
136174
@@ -151,7 +189,6 @@ def create_cloud_service(self, region, options, secret_data, schema):
151189 )
152190 sg_vo = raw
153191
154- group_id = sg_vo .get ("GroupId" , "" )
155192 link = f"https://console.aws.amazon.com/ec2/v2/home?region={ region } #SecurityGroups:group-id={ group_id } "
156193 reference = self .get_reference (group_id , link )
157194
@@ -167,15 +204,7 @@ def create_cloud_service(self, region, options, secret_data, schema):
167204 reference = reference ,
168205 )
169206 yield cloud_service
170- # yield {
171- # "data": sg_vo,
172- # "name": sg_vo.group_name,
173- # "account": self.account_id,
174- # "tags": self.convert_tags_to_dict_type(raw.get("Tags", [])),
175- # }
176-
177207 except Exception as e :
178- # resource_id = raw.get("GroupId", "")
179208 yield make_error_response (
180209 error = e ,
181210 provider = self .provider ,
@@ -184,24 +213,82 @@ def create_cloud_service(self, region, options, secret_data, schema):
184213 region_name = region ,
185214 )
186215
187- def custom_security_group_inbound_rule_info (self , raw_rule , remote , remote_type , vulnerable_ports ):
188- raw_rule = self .custom_security_group_rule_info (raw_rule , remote , remote_type )
216+ @staticmethod
217+ def _get_matched_security_group_rule_id (
218+ raw_rule , sg_rules_detail , remote , remote_type , is_egress
219+ ):
220+ raw_protocol = raw_rule .get ("IpProtocol" )
221+ raw_from_port = raw_rule .get ("FromPort" )
222+ raw_to_port = raw_rule .get ("ToPort" )
223+
224+ for sg_rule in sg_rules_detail :
225+ if sg_rule .get ("IsEgress" ) != is_egress :
226+ continue
227+
228+ if sg_rule .get ("IpProtocol" ) != raw_protocol :
229+ continue
230+
231+ if raw_from_port :
232+ sg_from_port = sg_rule .get ("FromPort" )
233+ if raw_from_port is not None and sg_from_port is not None :
234+ if raw_from_port != sg_from_port :
235+ continue
236+
237+ if raw_to_port :
238+ sg_to_port = sg_rule .get ("ToPort" )
239+ if raw_to_port is not None and sg_to_port is not None :
240+ if raw_to_port != sg_to_port :
241+ continue
242+
243+ if remote_type == "ip_ranges" :
244+ if sg_rule .get ("CidrIpv4" ) != remote .get ("CidrIp" ):
245+ continue
246+ elif remote_type == "ipv6_ranges" :
247+ if sg_rule .get ("CidrIpv6" ) != remote .get ("CidrIpv6" ):
248+ continue
249+ elif remote_type == "prefix_list_ids" :
250+ if sg_rule .get ("PrefixListId" ) != remote .get ("PrefixListId" ):
251+ continue
252+ elif remote_type == "user_id_group_pairs" :
253+ referenced_group = sg_rule .get ("ReferencedGroupInfo" , {})
254+ if referenced_group .get ("GroupId" ) != remote .get ("GroupId" ):
255+ continue
256+
257+ return sg_rule .get ("SecurityGroupRuleId" )
258+
259+ return None
260+
261+ def _custom_security_group_inbound_rule_info (
262+ self , raw_rule , remote , remote_type , is_egress , vulnerable_ports = None
263+ ):
264+ rule_id = self ._get_matched_security_group_rule_id (
265+ raw_rule = raw_rule ,
266+ sg_rules_detail = self .sg_rules_for_this_group ,
267+ remote = remote ,
268+ remote_type = remote_type ,
269+ is_egress = is_egress ,
270+ )
271+
272+ raw_rule = self ._custom_security_group_rule_info (raw_rule , remote , remote_type )
189273
190274 protocol_display = raw_rule .get ("protocol_display" )
191275
192276 if vulnerable_ports :
193- ports = self ._get_vulnerable_ports (protocol_display , raw_rule , vulnerable_ports )
277+ ports = self ._get_vulnerable_ports (
278+ protocol_display , raw_rule , vulnerable_ports
279+ )
194280
195281 raw_rule .update (
196282 {
283+ "rule_id" : rule_id ,
197284 "vulnerable_ports" : ports ,
198- "detected_vulnerable_ports" : True if ports else False
285+ "detected_vulnerable_ports" : True if ports else False ,
199286 }
200287 )
201288
202289 return raw_rule
203290
204- def custom_security_group_rule_info (self , raw_rule , remote , remote_type ):
291+ def _custom_security_group_rule_info (self , raw_rule , remote , remote_type ):
205292 protocol_display = self ._get_protocol_display (raw_rule .get ("IpProtocol" ))
206293 raw_rule .update (
207294 {
@@ -331,7 +418,9 @@ def get_instance_name_from_tags(instance):
331418 return ""
332419
333420 @staticmethod
334- def _get_vulnerable_ports (protocol_display : str , raw_rule : dict , vulnerable_ports : str ):
421+ def _get_vulnerable_ports (
422+ protocol_display : str , raw_rule : dict , vulnerable_ports : str
423+ ):
335424 try :
336425 ports = []
337426
0 commit comments