Skip to content

Commit 2aaad38

Browse files
author
Justin Kufro
committed
Include AWS resource name in code description in AWS Config Mapper
1 parent 5da2c79 commit 2aaad38

File tree

1 file changed

+50
-3
lines changed

1 file changed

+50
-3
lines changed

lib/heimdall_tools/aws_config_mapper.rb

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ 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]
@@ -193,13 +194,17 @@ def add_results_to_config_rules(config_rules)
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

Comments
 (0)