Skip to content

Commit

Permalink
Include AWS resource name in code description in AWS Config Mapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Kufro committed Sep 20, 2021
1 parent 5da2c79 commit 2aaad38
Showing 1 changed file with 50 additions and 3 deletions.
53 changes: 50 additions & 3 deletions lib/heimdall_tools/aws_config_mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ def fetch_all_compliance_info(config_rules)
#
# Returns: The same config_rules array with `results` key added to each rule.
def add_results_to_config_rules(config_rules)
resource_name_map = {}
config_rules.each do |rule|
response = @client.get_compliance_details_by_config_rule(config_rule_name: rule[:config_rule_name], limit: 100)
rule_results = response.to_h[:evaluation_results]
Expand All @@ -193,13 +194,17 @@ def add_results_to_config_rules(config_rules)
rule_results += response.to_h[:evaluation_results]
end

resource_name_map = get_resource_name_map(rule_results, resource_name_map)

rule[:results] = []
rule_results.each do |result|
hdf_result = {}
# code_desc
hdf_result['code_desc'] = result.dig(:evaluation_result_identifier, :evaluation_result_qualifier)&.map do |k, v|
"#{k}: #{v}"
end&.join(', ')
code_desc = result.dig(:evaluation_result_identifier, :evaluation_result_qualifier)&.map do |k, v|
"#{k}: #{v}"
end&.join(', ') || ''
code_desc += ", resource_name: #{resource_name_map[result.dig(:evaluation_result_identifier, :evaluation_result_qualifier, :resource_id)] || 'unknown'}"
hdf_result['code_desc'] = code_desc
# start_time
hdf_result['start_time'] = if result.key?(:config_rule_invoked_time)
DateTime.parse(result[:config_rule_invoked_time].to_s).strftime('%Y-%m-%dT%H:%M:%S%:z')
Expand Down Expand Up @@ -246,6 +251,48 @@ def add_results_to_config_rules(config_rules)
config_rules
end

##
# Takes in `rule_results` from a `get_compliance_details_by_config_rule` API call,
# then makes `list_discovered_resources` API calls to get the `resource_name` for
# each resouce ID.
#
# Resource ID alone without resource name commonly makes it inconvenient to figure out
# what AWS resource that the rule is referencing in its results.
def get_resource_name_map(rule_results, current_resource_name_map)
# Should be in the format: { resource_id: resource_name }
resource_map = {}

# Group by resource Type because the API call requires a type to be specified
groups = rule_results.group_by { |e| e.dig(:evaluation_result_identifier, :evaluation_result_qualifier, :resource_type) }
# Trim down values to just the ids
groups = groups.map do |resource_type, rule_results_arr|
[
resource_type,
rule_results_arr.map { |result| result.dig(:evaluation_result_identifier, :evaluation_result_qualifier, :resource_id) }.uniq,
]
end
# Reject any ids that are already in `current_resource_name_map`
groups = groups.map do |resource_type, resource_ids|
[
resource_type,
resource_ids.reject { |id| current_resource_name_map.include? id },
]
end

groups.each do |resource_type, resource_ids|
# API endpoint reports a max size of 20
resource_ids.each_slice(20) do |resource_ids_slice|
# Don't send an API call for an empty array
next if resource_ids_slice.empty?

response = @client.list_discovered_resources(resource_type: resource_type, resource_ids: resource_ids_slice, limit: 100)
resource_map = resource_map.merge(response.resource_identifiers.map { |resource| [resource.resource_id, resource.resource_name] }.to_h)
end
end

current_resource_name_map.merge resource_map
end

##
# Takes in a config rule and pulls out tags that are useful for HDF.
#
Expand Down

0 comments on commit 2aaad38

Please sign in to comment.