@@ -185,21 +185,26 @@ def fetch_all_compliance_info(config_rules)
185185 #
186186 # Returns: The same config_rules array with `results` key added to each rule.
187187 def add_results_to_config_rules ( config_rules )
188+ resource_name_map = { }
188189 config_rules . each do |rule |
189190 response = @client . get_compliance_details_by_config_rule ( config_rule_name : rule [ :config_rule_name ] , limit : 100 )
190191 rule_results = response . to_h [ :evaluation_results ]
191192 while response . next_token
192- response = @client . get_compliance_details_by_config_rule ( next_token : response . next_token , limit : 100 )
193+ response = @client . get_compliance_details_by_config_rule ( config_rule_name : rule [ :config_rule_name ] , next_token : response . next_token , limit : 100 )
193194 rule_results += response . to_h [ :evaluation_results ]
194195 end
195196
197+ resource_name_map = get_resource_name_map ( rule_results , resource_name_map )
198+
196199 rule [ :results ] = [ ]
197200 rule_results . each do |result |
198201 hdf_result = { }
199202 # code_desc
200- hdf_result [ 'code_desc' ] = result . dig ( :evaluation_result_identifier , :evaluation_result_qualifier ) &.map do |k , v |
201- "#{ k } : #{ v } "
202- end &.join ( ', ' )
203+ code_desc = result . dig ( :evaluation_result_identifier , :evaluation_result_qualifier ) &.map do |k , v |
204+ "#{ k } : #{ v } "
205+ end &.join ( ', ' ) || ''
206+ code_desc += ", resource_name: #{ resource_name_map [ result . dig ( :evaluation_result_identifier , :evaluation_result_qualifier , :resource_id ) ] || 'unknown' } "
207+ hdf_result [ 'code_desc' ] = code_desc
203208 # start_time
204209 hdf_result [ 'start_time' ] = if result . key? ( :config_rule_invoked_time )
205210 DateTime . parse ( result [ :config_rule_invoked_time ] . to_s ) . strftime ( '%Y-%m-%dT%H:%M:%S%:z' )
@@ -246,6 +251,48 @@ def add_results_to_config_rules(config_rules)
246251 config_rules
247252 end
248253
254+ ##
255+ # Takes in `rule_results` from a `get_compliance_details_by_config_rule` API call,
256+ # then makes `list_discovered_resources` API calls to get the `resource_name` for
257+ # each resouce ID.
258+ #
259+ # Resource ID alone without resource name commonly makes it inconvenient to figure out
260+ # what AWS resource that the rule is referencing in its results.
261+ def get_resource_name_map ( rule_results , current_resource_name_map )
262+ # Should be in the format: { resource_id: resource_name }
263+ resource_map = { }
264+
265+ # Group by resource Type because the API call requires a type to be specified
266+ groups = rule_results . group_by { |e | e . dig ( :evaluation_result_identifier , :evaluation_result_qualifier , :resource_type ) }
267+ # Trim down values to just the ids
268+ groups = groups . map do |resource_type , rule_results_arr |
269+ [
270+ resource_type ,
271+ rule_results_arr . map { |result | result . dig ( :evaluation_result_identifier , :evaluation_result_qualifier , :resource_id ) } . uniq ,
272+ ]
273+ end
274+ # Reject any ids that are already in `current_resource_name_map`
275+ groups = groups . map do |resource_type , resource_ids |
276+ [
277+ resource_type ,
278+ resource_ids . reject { |id | current_resource_name_map . include? id } ,
279+ ]
280+ end
281+
282+ groups . each do |resource_type , resource_ids |
283+ # API endpoint reports a max size of 20
284+ resource_ids . each_slice ( 20 ) do |resource_ids_slice |
285+ # Don't send an API call for an empty array
286+ next if resource_ids_slice . empty?
287+
288+ response = @client . list_discovered_resources ( resource_type : resource_type , resource_ids : resource_ids_slice , limit : 100 )
289+ resource_map = resource_map . merge ( response . resource_identifiers . map { |resource | [ resource . resource_id , resource . resource_name ] } . to_h )
290+ end
291+ end
292+
293+ current_resource_name_map . merge resource_map
294+ end
295+
249296 ##
250297 # Takes in a config rule and pulls out tags that are useful for HDF.
251298 #
0 commit comments