heimdall_tools 1.3.36 → 1.3.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +21 -0
- data/lib/data/aws-config-mapping.csv +107 -0
- data/lib/heimdall_tools.rb +1 -0
- data/lib/heimdall_tools/aws_config_mapper.rb +284 -0
- data/lib/heimdall_tools/cli.rb +13 -1
- data/lib/heimdall_tools/hdf.rb +3 -1
- data/lib/heimdall_tools/help/aws_config_mapper.md +30 -0
- metadata +18 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6e9d50bdf3b2f06cdd02be70517a574ca2a4f979abdb80d705682f02fe7dd45
|
|
4
|
+
data.tar.gz: a695c5f4f843802da69e4e150befbbbc9914a87d4aa20319a8156fbf376e9805
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2295f30b0e973d2e59f2860d7ed7fcfa2dd75367a5731f250d1c6b5842326d9df984db383ee8a03b9aedc741a73729c8a0b6d6fb5ef13bc463cfe3b750238801
|
|
7
|
+
data.tar.gz: 56a80ca04c456e1aff7769ce3f0f554a5a7c533a801cfff800812898d9a888d96264e5da0c08c86576432e7e690fbfe7aad4bc3f21f59c9107bfc1c12bb425ed
|
data/README.md
CHANGED
|
@@ -14,6 +14,7 @@ HeimdallTools supplies several methods to convert output from various tools to "
|
|
|
14
14
|
- **nikto_mapper** - open-source web server scanner
|
|
15
15
|
- **jfrog_xray_mapper** - package vulnerability scanner
|
|
16
16
|
- **dbprotect_mapper** - database vulnerability scanner
|
|
17
|
+
- **aws_config_mapper** - assess, audit, and evaluate AWS resources
|
|
17
18
|
|
|
18
19
|
Ruby 2.4 or higher (check using "ruby -v")
|
|
19
20
|
|
|
@@ -213,6 +214,26 @@ FLAGS:
|
|
|
213
214
|
example: heimdall_tools dbprotect_mapper -x check_results_details_report.xml -o db_protect_hdf.json
|
|
214
215
|
```
|
|
215
216
|
|
|
217
|
+
## aws_config_mapper
|
|
218
|
+
|
|
219
|
+
aws_config_mapper pulls Ruby AWS SDK data to translate AWS Config Rule results into HDF format json to be viewable in Heimdall
|
|
220
|
+
|
|
221
|
+
### AWS Config Rule Mapping:
|
|
222
|
+
The mapping of AWS Config Rules to 800-53 Controls was sourced from [this link](https://docs.aws.amazon.com/config/latest/developerguide/operational-best-practices-for-nist-800-53_rev_4.html).
|
|
223
|
+
|
|
224
|
+
### Authentication with AWS:
|
|
225
|
+
[Developer Guide for configuring Ruby AWS SDK for authentication](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html)
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
USAGE: heimdall_tools aws_config_mapper [OPTIONS] -o <hdf-scan-results.json>
|
|
229
|
+
|
|
230
|
+
FLAGS:
|
|
231
|
+
-o --output <scan-results> : path to output scan-results json.
|
|
232
|
+
-V --verbose : verbose run [optional].
|
|
233
|
+
|
|
234
|
+
example: heimdall_tools aws_config_mapper -o aws_config_results_hdf.json
|
|
235
|
+
```
|
|
236
|
+
|
|
216
237
|
## version
|
|
217
238
|
|
|
218
239
|
Prints out the gem version
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
AwsConfigRuleName,NIST-ID,Rev
|
|
2
|
+
secretsmanager-scheduled-rotation-success-check,AC-2(1)|AC-2(j),4
|
|
3
|
+
iam-user-group-membership-check,AC-2(1)|AC-2(j)|AC-3|AC-6,4
|
|
4
|
+
iam-password-policy,AC-2(1)|AC-2(f)|AC-2(j)|IA-2|IA-5(1)(a)(d)(e)|IA-5(4),4
|
|
5
|
+
access-keys-rotated,AC-2(1)|AC-2(j),4
|
|
6
|
+
iam-user-unused-credentials-check,AC-2(1)|AC-2(3)|AC-2(f)|AC-3|AC-6,4
|
|
7
|
+
securityhub-enabled,AC-2(1)|AC-2(4)|AC-2(12)(a)|AC-2(g)|AC-17(1)|AU-6(1)(3)|CA-7(a)(b)|SA-10|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(16)|SI-4(a)(b)(c),4
|
|
8
|
+
guardduty-enabled-centralized,AC-2(1)|AC-2(4)|AC-2(12)(a)|AC-2(g)|AC-17(1)|AU-6(1)(3)|CA-7(a)(b)|RA-5|SA-10|SI-4(1)|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(16)|SI-4(a)(b)(c),4
|
|
9
|
+
cloud-trail-cloud-watch-logs-enabled,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-6(1)(3)|AU-7(1)|AU-12(a)(c)|CA-7(a)(b)|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(a)(b)(c),4
|
|
10
|
+
cloudtrail-enabled,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
11
|
+
multi-region-cloudtrail-enabled,AC-2(4)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
12
|
+
rds-logging-enabled,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
13
|
+
cloudwatch-alarm-action-check,AC-2(4)|AU-6(1)(3)|AU-7(1)|CA-7(a)(b)|IR-4(1)|SI-4(2)|SI-4(4)|SI-4(5)|SI-4(a)(b)(c),4
|
|
14
|
+
redshift-cluster-configuration-check,AC-2(4)|AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c)|SC-13|SC-28,4
|
|
15
|
+
iam-root-access-key-check,AC-2(f)|AC-2(j)|AC-3|AC-6|AC-6(10),4
|
|
16
|
+
s3-bucket-logging-enabled,AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
17
|
+
cloudtrail-s3-dataevents-enabled,AC-2(g)|AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
18
|
+
root-account-mfa-enabled,AC-2(j)|IA-2(1)(11),4
|
|
19
|
+
emr-kerberos-enabled,AC-2(j)|AC-3|AC-5(c)|AC-6,4
|
|
20
|
+
iam-group-has-users-check,AC-2(j)|AC-3|AC-5(c)|AC-6|SC-2,4
|
|
21
|
+
iam-policy-no-statements-with-admin-access,AC-2(j)|AC-3|AC-5(c)|AC-6|SC-2,4
|
|
22
|
+
iam-user-no-policies-check,AC-2(j)|AC-3|AC-5(c)|AC-6,4
|
|
23
|
+
s3-bucket-public-write-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
24
|
+
lambda-function-public-access-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
25
|
+
rds-snapshots-public-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
26
|
+
redshift-cluster-public-access-check,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
27
|
+
s3-bucket-policy-grantee-check,AC-3|AC-6|SC-7|SC-7(3),4
|
|
28
|
+
s3-bucket-public-read-prohibited,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
29
|
+
s3-account-level-public-access-blocks,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
30
|
+
dms-replication-not-public,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
31
|
+
ebs-snapshot-public-restorable-check,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
32
|
+
sagemaker-notebook-no-direct-internet-access,AC-3|AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
33
|
+
rds-instance-public-access-check,AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
34
|
+
lambda-inside-vpc,AC-4|SC-7|SC-7(3),4
|
|
35
|
+
ec2-instances-in-vpc,AC-4|SC-7|SC-7(3),4
|
|
36
|
+
restricted-common-ports,AC-4|CM-2|SC-7|SC-7(3),4
|
|
37
|
+
restricted-ssh,AC-4|SC-7|SC-7(3),4
|
|
38
|
+
vpc-default-security-group-closed,AC-4|SC-7|SC-7(3),4
|
|
39
|
+
vpc-sg-open-only-to-authorized-ports,AC-4|SC-7|SC-7(3),4
|
|
40
|
+
acm-certificate-expiration-check,AC-4|AC-17(2)|SC-12,4
|
|
41
|
+
ec2-instance-no-public-ip,AC-4|AC-6|AC-21(b)|SC-7|SC-7(3),4
|
|
42
|
+
elasticsearch-in-vpc-only,AC-4|SC-7|SC-7(3),4
|
|
43
|
+
emr-master-no-public-ip,AC-4|AC-21(b)|SC-7|SC-7(3),4
|
|
44
|
+
internet-gateway-authorized-vpc-only,AC-4|AC-17(3)|SC-7|SC-7(3),4
|
|
45
|
+
codebuild-project-envvar-awscred-check,AC-6|IA-5(7)|SA-3(a),4
|
|
46
|
+
ec2-imdsv2-check,AC-6,4
|
|
47
|
+
iam-no-inline-policy-check,AC-6,4
|
|
48
|
+
alb-http-to-https-redirection-check,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13|SC-23,4
|
|
49
|
+
redshift-require-tls-ssl,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13,4
|
|
50
|
+
s3-bucket-ssl-requests-only,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13,4
|
|
51
|
+
elb-acm-certificate-required,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-13,4
|
|
52
|
+
alb-http-drop-invalid-header-enabled,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-23,4
|
|
53
|
+
elb-tls-https-listeners-only,AC-17(2)|SC-7|SC-8|SC-8(1)|SC-23,4
|
|
54
|
+
api-gw-execution-logging-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
55
|
+
elb-logging-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
56
|
+
vpc-flow-logs-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c),4
|
|
57
|
+
wafv2-logging-enabled,AU-2(a)(d)|AU-3|AU-12(a)(c)|SC-7|SI-4(a)(b)(c),4
|
|
58
|
+
cloud-trail-encryption-enabled,AU-9|SC-13|SC-28,4
|
|
59
|
+
cloudwatch-log-group-encrypted,AU-9|SC-13|SC-28,4
|
|
60
|
+
s3-bucket-replication-enabled,AU-9(2)|CP-9(b)|CP-10|SC-5|SC-36,4
|
|
61
|
+
cw-loggroup-retention-period-check,AU-11|SI-12,4
|
|
62
|
+
ec2-instance-detailed-monitoring-enabled,CA-7(a)(b)|SI-4(2)|SI-4(a)(b)(c),4
|
|
63
|
+
rds-enhanced-monitoring-enabled,CA-7(a)(b),4
|
|
64
|
+
ec2-instance-managed-by-systems-manager,CM-2|CM-7(a)|CM-8(1)|CM-8(3)(a)|SA-3(a)|SA-10|SI-2(2)|SI-7(1),4
|
|
65
|
+
ec2-managedinstance-association-compliance-status-check,CM-2|CM-7(a)|CM-8(3)(a)|SI-2(2),4
|
|
66
|
+
ec2-stopped-instance,CM-2,4
|
|
67
|
+
ec2-volume-inuse-check,CM-2|SC-4,4
|
|
68
|
+
elb-deletion-protection-enabled,CM-2|CP-10,4
|
|
69
|
+
cloudtrail-security-trail-enabled,CM-2,4
|
|
70
|
+
ec2-managedinstance-patch-compliance-status-check,CM-8(3)(a)|SI-2(2)|SI-7(1),4
|
|
71
|
+
db-instance-backup-enabled,CP-9(b)|CP-10|SI-12,4
|
|
72
|
+
dynamodb-pitr-enabled,CP-9(b)|CP-10|SI-12,4
|
|
73
|
+
elasticache-redis-cluster-automatic-backup-check,CP-9(b)|CP-10|SI-12,4
|
|
74
|
+
dynamodb-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
|
75
|
+
ebs-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
|
76
|
+
efs-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
|
77
|
+
rds-in-backup-plan,CP-9(b)|CP-10|SI-12,4
|
|
78
|
+
dynamodb-autoscaling-enabled,CP-10|SC-5,4
|
|
79
|
+
rds-multi-az-support,CP-10|SC-5|SC-36,4
|
|
80
|
+
s3-bucket-versioning-enabled,CP-10|SI-12,4
|
|
81
|
+
vpc-vpn-2-tunnels-up,CP-10,4
|
|
82
|
+
elb-cross-zone-load-balancing-enabled,CP-10|SC-5,4
|
|
83
|
+
root-account-hardware-mfa-enabled,IA-2(1)(11),4
|
|
84
|
+
mfa-enabled-for-iam-console-access,IA-2(1)(2)(11),4
|
|
85
|
+
iam-user-mfa-enabled,IA-2(1)(2)(11),4
|
|
86
|
+
guardduty-non-archived-findings,IR-4(1)|IR-6(1)|IR-7(1)|RA-5|SA-10|SI-4(a)(b)(c),4
|
|
87
|
+
codebuild-project-source-repo-url-check,SA-3(a),4
|
|
88
|
+
autoscaling-group-elb-healthcheck-required,SC-5,4
|
|
89
|
+
rds-instance-deletion-protection-enabled,SC-5,4
|
|
90
|
+
alb-waf-enabled,SC-7|SI-4(a)(b)(c),4
|
|
91
|
+
elasticsearch-node-to-node-encryption-check,SC-7|SC-8|SC-8(1),4
|
|
92
|
+
cmk-backing-key-rotation-enabled,SC-12,4
|
|
93
|
+
kms-cmk-not-scheduled-for-deletion,SC-12|SC-28,4
|
|
94
|
+
api-gw-cache-enabled-and-encrypted,SC-13|SC-28,4
|
|
95
|
+
efs-encrypted-check,SC-13|SC-28,4
|
|
96
|
+
elasticsearch-encrypted-at-rest,SC-13|SC-28,4
|
|
97
|
+
encrypted-volumes,SC-13|SC-28,4
|
|
98
|
+
rds-storage-encrypted,SC-13|SC-28,4
|
|
99
|
+
s3-bucket-server-side-encryption-enabled,SC-13|SC-28,4
|
|
100
|
+
sagemaker-endpoint-configuration-kms-key-configured,SC-13|SC-28,4
|
|
101
|
+
sagemaker-notebook-instance-kms-key-configured,SC-13|SC-28,4
|
|
102
|
+
sns-encrypted-kms,SC-13|SC-28,4
|
|
103
|
+
dynamodb-table-encrypted-kms,SC-13,4
|
|
104
|
+
s3-bucket-default-lock-enabled,SC-28,4
|
|
105
|
+
ec2-ebs-encryption-by-default,SC-28,4
|
|
106
|
+
rds-snapshot-encrypted,SC-28,4
|
|
107
|
+
cloud-trail-log-file-validation-enabled,SI-7|SI-7(1),4
|
data/lib/heimdall_tools.rb
CHANGED
|
@@ -14,4 +14,5 @@ module HeimdallTools
|
|
|
14
14
|
autoload :NiktoMapper, 'heimdall_tools/nikto_mapper'
|
|
15
15
|
autoload :JfrogXrayMapper, 'heimdall_tools/jfrog_xray_mapper'
|
|
16
16
|
autoload :DBProtectMapper, 'heimdall_tools/dbprotect_mapper'
|
|
17
|
+
autoload :AwsConfigMapper, 'heimdall_tools/aws_config_mapper'
|
|
17
18
|
end
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
require 'aws-sdk-configservice'
|
|
2
|
+
require 'heimdall_tools/hdf'
|
|
3
|
+
require 'csv'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
RESOURCE_DIR = Pathname.new(__FILE__).join('../../data')
|
|
7
|
+
|
|
8
|
+
AWS_CONFIG_MAPPING_FILE = File.join(RESOURCE_DIR, 'aws-config-mapping.csv')
|
|
9
|
+
|
|
10
|
+
NOT_APPLICABLE_MSG = 'No AWS resources found to evaluate complaince for this rule'.freeze
|
|
11
|
+
INSUFFICIENT_DATA_MSG = 'Not enough data has been collectd to determine compliance yet.'.freeze
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# HDF mapper for use with AWS Config rules.
|
|
15
|
+
#
|
|
16
|
+
# Ruby AWS Ruby SDK for ConfigService:
|
|
17
|
+
# - https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html
|
|
18
|
+
#
|
|
19
|
+
# rubocop:disable Metrics/AbcSize, Metrics/ClassLength
|
|
20
|
+
module HeimdallTools
|
|
21
|
+
class AwsConfigMapper
|
|
22
|
+
def initialize(custom_mapping, verbose = false)
|
|
23
|
+
@verbose = verbose
|
|
24
|
+
@default_mapping = get_rule_mapping(AWS_CONFIG_MAPPING_FILE)
|
|
25
|
+
@custom_mapping = custom_mapping.nil? ? {} : get_rule_mapping(custom_mapping)
|
|
26
|
+
@client = Aws::ConfigService::Client.new
|
|
27
|
+
@issues = get_all_config_rules
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Convert to HDF
|
|
32
|
+
#
|
|
33
|
+
# If there is overlap in rule names from @default_mapping and @custom_mapping,
|
|
34
|
+
# then the tags from both will be added to the rule.
|
|
35
|
+
def to_hdf
|
|
36
|
+
controls = @issues.map do |issue|
|
|
37
|
+
@item = {}
|
|
38
|
+
@item['id'] = issue[:config_rule_name]
|
|
39
|
+
@item['title'] = issue[:config_rule_name]
|
|
40
|
+
@item['desc'] = issue[:description]
|
|
41
|
+
@item['impact'] = 0.5
|
|
42
|
+
@item['tags'] = hdf_tags(issue)
|
|
43
|
+
@item['descriptions'] = hdf_descriptions(issue)
|
|
44
|
+
@item['refs'] = NA_ARRAY
|
|
45
|
+
@item['source_location'] = { ref: issue[:config_rule_arn], line: 1 }
|
|
46
|
+
@item['code'] = ''
|
|
47
|
+
@item['results'] = issue[:results]
|
|
48
|
+
# Avoid duplicating rules that exist in the custom mapping as 'unmapped' in this loop
|
|
49
|
+
if @custom_mapping.include?(issue[:config_rule_name]) && !@default_mapping.include?(issue[:config_rule_name])
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
@item
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
results = HeimdallDataFormat.new(
|
|
56
|
+
profile_name: 'AWS Config',
|
|
57
|
+
title: 'AWS Config',
|
|
58
|
+
summary: 'AWS Config',
|
|
59
|
+
controls: controls,
|
|
60
|
+
statistics: { aws_config_sdk_version: Aws::ConfigService::GEM_VERSION }
|
|
61
|
+
)
|
|
62
|
+
results.to_hdf
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
##
|
|
68
|
+
# Read in a config rule -> 800-53 control mapping CSV.
|
|
69
|
+
#
|
|
70
|
+
# Params:
|
|
71
|
+
# - path: The file path to the CSV file
|
|
72
|
+
#
|
|
73
|
+
# Returns: A mapped version of the csv in the format { rule_name: row, ... }
|
|
74
|
+
def get_rule_mapping(path)
|
|
75
|
+
Hash[CSV.read(path, headers: true).map { |row| [row[0], row] }]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Fetches information on all of the config rules available to the
|
|
80
|
+
# AWS account.
|
|
81
|
+
#
|
|
82
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html#describe_config_rules-instance_method
|
|
83
|
+
#
|
|
84
|
+
# Returns: list of hash for all config rules available
|
|
85
|
+
def get_all_config_rules
|
|
86
|
+
config_rules = []
|
|
87
|
+
|
|
88
|
+
# Fetch all rules with pagination
|
|
89
|
+
response = @client.describe_config_rules
|
|
90
|
+
config_rules += response.config_rules
|
|
91
|
+
while response.next_token
|
|
92
|
+
response = @client.describe_config_rules(next_token: response.next_token)
|
|
93
|
+
config_rules += response.config_rules
|
|
94
|
+
end
|
|
95
|
+
config_rules = config_rules.map(&:to_h)
|
|
96
|
+
|
|
97
|
+
# Add necessary data to rules using helpers
|
|
98
|
+
add_compliance_to_config_rules(config_rules)
|
|
99
|
+
add_results_to_config_rules(config_rules)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Adds compliance information for config rules to the config rule hash
|
|
104
|
+
# from AwsConfigMapper::get_all_config_rules.
|
|
105
|
+
#
|
|
106
|
+
# `complaince_type` may be any of the following:
|
|
107
|
+
# ["COMPLIANT", "NON_COMPLIANT", "NOT_APPLICABLE", "INSUFFICIENT_DATA"]
|
|
108
|
+
#
|
|
109
|
+
# Params:
|
|
110
|
+
# - config_rules: The list of hash from AwsConfigMapper::get_all_config_rules
|
|
111
|
+
#
|
|
112
|
+
# Returns: The same config_rules array with `compliance` key added to each rule
|
|
113
|
+
def add_compliance_to_config_rules(config_rules)
|
|
114
|
+
mapped_compliance_results = fetch_all_compliance_info(config_rules)
|
|
115
|
+
|
|
116
|
+
# Add compliance to config_rules
|
|
117
|
+
config_rules.each do |rule|
|
|
118
|
+
rule[:compliance] = mapped_compliance_results[rule[:config_rule_name]]&.dig(:compliance, :compliance_type)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
config_rules
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
##
|
|
125
|
+
# Fetch and combine all compliance information for the config rules.
|
|
126
|
+
#
|
|
127
|
+
# AWS allows passing up to 25 rules at a time to this endpoint.
|
|
128
|
+
#
|
|
129
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html#describe_compliance_by_config_rule-instance_method
|
|
130
|
+
#
|
|
131
|
+
# Params:
|
|
132
|
+
# - config_rules: The list of hash from AwsConfigMapper::get_all_config_rules
|
|
133
|
+
#
|
|
134
|
+
# Returns: Results mapped by config rule in the format { name: {<response>}, ... }
|
|
135
|
+
def fetch_all_compliance_info(config_rules)
|
|
136
|
+
compliance_results = []
|
|
137
|
+
|
|
138
|
+
config_rules.each_slice(25).each do |slice|
|
|
139
|
+
config_rule_names = slice.map { |r| r[:config_rule_name] }
|
|
140
|
+
response = @client.describe_compliance_by_config_rule(config_rule_names: config_rule_names)
|
|
141
|
+
compliance_results += response.compliance_by_config_rules
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Map based on name for easy lookup
|
|
145
|
+
Hash[compliance_results.collect { |r| [r.config_rule_name, r.to_h] }]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
##
|
|
149
|
+
# Takes in config rules and formats the results for hdf format.
|
|
150
|
+
#
|
|
151
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ConfigService/Client.html#get_compliance_details_by_config_rule-instance_method
|
|
152
|
+
#
|
|
153
|
+
# Example hdf results:
|
|
154
|
+
# [
|
|
155
|
+
# {
|
|
156
|
+
# "code_desc": "This rule...",
|
|
157
|
+
# "run_time": 0.314016,
|
|
158
|
+
# "start_time": "2018-11-18T20:21:40-05:00",
|
|
159
|
+
# "status": "passed"
|
|
160
|
+
# },
|
|
161
|
+
# ...
|
|
162
|
+
# ]
|
|
163
|
+
#
|
|
164
|
+
# Status may be any of the following: ['passed', 'failed', 'skipped', 'loaded']
|
|
165
|
+
#
|
|
166
|
+
# Params:
|
|
167
|
+
# - rule: Rules from AwsConfigMapper::get_all_config_rules
|
|
168
|
+
#
|
|
169
|
+
# Returns: The same config_rules array with `results` key added to each rule.
|
|
170
|
+
def add_results_to_config_rules(config_rules)
|
|
171
|
+
config_rules.each do |rule|
|
|
172
|
+
response = @client.get_compliance_details_by_config_rule(config_rule_name: rule[:config_rule_name], limit: 100)
|
|
173
|
+
rule_results = response.to_h[:evaluation_results]
|
|
174
|
+
while response.next_token
|
|
175
|
+
response = @client.get_compliance_details_by_config_rule(next_token: response.next_token, limit: 100)
|
|
176
|
+
rule_results += response.to_h[:evaluation_results]
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
rule[:results] = []
|
|
180
|
+
rule_results.each do |result|
|
|
181
|
+
hdf_result = {}
|
|
182
|
+
# code_desc
|
|
183
|
+
hdf_result['code_desc'] = result.dig(:evaluation_result_identifier, :evaluation_result_qualifier)&.map do |k, v|
|
|
184
|
+
"#{k}: #{v}"
|
|
185
|
+
end&.join(', ')
|
|
186
|
+
# start_time
|
|
187
|
+
hdf_result['start_time'] = if result.key?(:config_rule_invoked_time)
|
|
188
|
+
DateTime.parse(result[:config_rule_invoked_time].to_s).strftime('%Y-%m-%dT%H:%M:%S%:z')
|
|
189
|
+
end
|
|
190
|
+
# run_time
|
|
191
|
+
hdf_result['run_time'] = if result.key?(:result_recorded_time) && result.key?(:config_rule_invoked_time)
|
|
192
|
+
(result[:result_recorded_time] - result[:config_rule_invoked_time]).round(6)
|
|
193
|
+
end
|
|
194
|
+
# status
|
|
195
|
+
hdf_result['status'] = case result.dig(:compliance_type)
|
|
196
|
+
when 'COMPLIANT'
|
|
197
|
+
'passed'
|
|
198
|
+
when 'NON_COMPLIANT'
|
|
199
|
+
'failed'
|
|
200
|
+
else
|
|
201
|
+
'skipped'
|
|
202
|
+
end
|
|
203
|
+
hdf_result['message'] = "(#{hdf_result['code_desc']}): #{result[:annotation] || 'Rule does not pass rule compliance'}" if hdf_result['status'] == 'failed'
|
|
204
|
+
rule[:results] << hdf_result
|
|
205
|
+
end
|
|
206
|
+
next unless rule[:results].empty?
|
|
207
|
+
|
|
208
|
+
case rule[:compliance]
|
|
209
|
+
when 'NOT_APPLICABLE'
|
|
210
|
+
rule[:impact] = 0
|
|
211
|
+
rule[:results] << {
|
|
212
|
+
'run_time': 0,
|
|
213
|
+
'code_desc': NOT_APPLICABLE_MSG,
|
|
214
|
+
'skip_message': NOT_APPLICABLE_MSG,
|
|
215
|
+
'start_time': DateTime.now.strftime('%Y-%m-%dT%H:%M:%S%:z'),
|
|
216
|
+
'status': 'skipped'
|
|
217
|
+
}
|
|
218
|
+
when 'INSUFFICIENT_DATA'
|
|
219
|
+
rule[:results] << {
|
|
220
|
+
'run_time': 0,
|
|
221
|
+
'code_desc': INSUFFICIENT_DATA_MSG,
|
|
222
|
+
'skip_message': INSUFFICIENT_DATA_MSG,
|
|
223
|
+
'start_time': DateTime.now.strftime('%Y-%m-%dT%H:%M:%S%:z'),
|
|
224
|
+
'status': 'skipped'
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
config_rules
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
##
|
|
233
|
+
# Takes in a config rule and pulls out tags that are useful for HDF.
|
|
234
|
+
#
|
|
235
|
+
# Params:
|
|
236
|
+
# - config_rule: A single config rule from AwsConfigMapper::get_all_config_rules
|
|
237
|
+
#
|
|
238
|
+
# Returns: Hash containing all relevant HDF tags
|
|
239
|
+
def hdf_tags(config_rule)
|
|
240
|
+
result = {}
|
|
241
|
+
|
|
242
|
+
@default_mapping
|
|
243
|
+
@custom_mapping
|
|
244
|
+
|
|
245
|
+
# NIST tag
|
|
246
|
+
result['nist'] = []
|
|
247
|
+
default_mapping_match = @default_mapping[config_rule[:config_rule_name]]
|
|
248
|
+
|
|
249
|
+
result['nist'] += default_mapping_match[1].split('|') unless default_mapping_match.nil?
|
|
250
|
+
|
|
251
|
+
custom_mapping_match = @custom_mapping[config_rule[:config_rule_name]]
|
|
252
|
+
|
|
253
|
+
result['nist'] += custom_mapping_match[1].split('|').map { |name| "#{name} (user provided)" } unless custom_mapping_match.nil?
|
|
254
|
+
|
|
255
|
+
result['nist'] = ['unmapped'] if result['nist'].empty?
|
|
256
|
+
|
|
257
|
+
result
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def check_text(config_rule)
|
|
261
|
+
params = (JSON.parse(config_rule[:input_parameters]).map { |key, value| "#{key}: #{value}" }).join('<br/>')
|
|
262
|
+
check_text = config_rule[:config_rule_arn]
|
|
263
|
+
check_text += "<br/>#{params}" unless params.empty?
|
|
264
|
+
check_text
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
##
|
|
268
|
+
# Takes in a config rule and pulls out information for the descriptions array
|
|
269
|
+
#
|
|
270
|
+
# Params:
|
|
271
|
+
# - config_rule: A single config rule from AwsConfigMapper::get_all_config_rules
|
|
272
|
+
#
|
|
273
|
+
# Returns: Array containing all relevant descriptions information
|
|
274
|
+
def hdf_descriptions(config_rule)
|
|
275
|
+
[
|
|
276
|
+
{
|
|
277
|
+
'label': 'check',
|
|
278
|
+
'data': check_text(config_rule)
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
# rubocop:enable Metrics/AbcSize, Metrics/ClassLength
|
data/lib/heimdall_tools/cli.rb
CHANGED
|
@@ -98,7 +98,7 @@ module HeimdallTools
|
|
|
98
98
|
puts "\r\HDF Generated:\n"
|
|
99
99
|
puts "#{options[:output]}"
|
|
100
100
|
end
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
desc 'dbprotect_mapper', 'dbprotect_mapper translates dbprotect results xml to HDF format Json be viewed on Heimdall'
|
|
103
103
|
long_desc Help.text(:dbprotect_mapper)
|
|
104
104
|
option :xml, required: true, aliases: '-x'
|
|
@@ -111,6 +111,18 @@ module HeimdallTools
|
|
|
111
111
|
puts "#{options[:output]}"
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
+
desc 'aws_config_mapper', 'aws_config_mapper pulls Ruby AWS SDK data to translate AWS Config Rule results into HDF format Json to be viewable in Heimdall'
|
|
115
|
+
long_desc Help.text(:aws_config_mapper)
|
|
116
|
+
# option :custom_mapping, required: false, aliases: '-m'
|
|
117
|
+
option :output, required: true, aliases: '-o'
|
|
118
|
+
option :verbose, type: :boolean, aliases: '-V'
|
|
119
|
+
def aws_config_mapper
|
|
120
|
+
hdf = HeimdallTools::AwsConfigMapper.new(options[:custom_mapping]).to_hdf
|
|
121
|
+
File.write(options[:output], hdf)
|
|
122
|
+
puts "\r\HDF Generated:\n"
|
|
123
|
+
puts "#{options[:output]}"
|
|
124
|
+
end
|
|
125
|
+
|
|
114
126
|
desc 'version', 'prints version'
|
|
115
127
|
def version
|
|
116
128
|
puts VERSION
|
data/lib/heimdall_tools/hdf.rb
CHANGED
|
@@ -29,7 +29,8 @@ module HeimdallTools
|
|
|
29
29
|
groups: NA_ARRAY,
|
|
30
30
|
status: 'loaded',
|
|
31
31
|
controls: NA_TAG,
|
|
32
|
-
target_id: NA_TAG
|
|
32
|
+
target_id: NA_TAG,
|
|
33
|
+
statistics: NA_HASH)
|
|
33
34
|
|
|
34
35
|
@results_json = {}
|
|
35
36
|
@results_json['platform'] = {}
|
|
@@ -40,6 +41,7 @@ module HeimdallTools
|
|
|
40
41
|
|
|
41
42
|
@results_json['statistics'] = {}
|
|
42
43
|
@results_json['statistics']['duration'] = duration || NA_TAG
|
|
44
|
+
@results_json['statistics'].merge! statistics
|
|
43
45
|
|
|
44
46
|
@results_json['profiles'] = []
|
|
45
47
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
aws_config_mapper pulls Ruby AWS SDK data to translate AWS Config Rule results into HDF format json to be viewable in Heimdall
|
|
2
|
+
|
|
3
|
+
AWS Config Rule Mapping:
|
|
4
|
+
The mapping of AWS Config Rules to 800-53 Controls was sourced from [this link](https://docs.aws.amazon.com/config/latest/developerguide/operational-best-practices-for-nist-800-53_rev_4.html).
|
|
5
|
+
|
|
6
|
+
Authentication with AWS:
|
|
7
|
+
[Developer Guide for configuring Ruby AWS SDK for authentication](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html)
|
|
8
|
+
|
|
9
|
+
Authentication Example:
|
|
10
|
+
|
|
11
|
+
- Create `~/.aws/credentials`
|
|
12
|
+
- Add contents to file, replacing with your access ID and key
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
[default]
|
|
16
|
+
aws_access_key_id = your_access_key_id
|
|
17
|
+
aws_secret_access_key = your_secret_access_key
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- (optional) set AWS region through `~/.aws/config` file with contents
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
[default]
|
|
24
|
+
output = json
|
|
25
|
+
region = us-gov-west-1
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
|
|
30
|
+
heimdall_tools aws_config_mapper -o aws_config_results.json
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: heimdall_tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.37
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Thew
|
|
@@ -12,6 +12,20 @@ bindir: exe
|
|
|
12
12
|
cert_chain: []
|
|
13
13
|
date: 2021-03-01 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: aws-sdk-configservice
|
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
|
+
requirements:
|
|
19
|
+
- - "~>"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '1'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - "~>"
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '1'
|
|
15
29
|
- !ruby/object:Gem::Dependency
|
|
16
30
|
name: nokogiri
|
|
17
31
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -181,11 +195,13 @@ files:
|
|
|
181
195
|
- Rakefile
|
|
182
196
|
- exe/heimdall_tools
|
|
183
197
|
- lib/data/U_CCI_List.xml
|
|
198
|
+
- lib/data/aws-config-mapping.csv
|
|
184
199
|
- lib/data/cwe-nist-mapping.csv
|
|
185
200
|
- lib/data/nessus-plugins-nist-mapping.csv
|
|
186
201
|
- lib/data/nikto-nist-mapping.csv
|
|
187
202
|
- lib/data/owasp-nist-mapping.csv
|
|
188
203
|
- lib/heimdall_tools.rb
|
|
204
|
+
- lib/heimdall_tools/aws_config_mapper.rb
|
|
189
205
|
- lib/heimdall_tools/burpsuite_mapper.rb
|
|
190
206
|
- lib/heimdall_tools/cli.rb
|
|
191
207
|
- lib/heimdall_tools/command.rb
|
|
@@ -193,6 +209,7 @@ files:
|
|
|
193
209
|
- lib/heimdall_tools/fortify_mapper.rb
|
|
194
210
|
- lib/heimdall_tools/hdf.rb
|
|
195
211
|
- lib/heimdall_tools/help.rb
|
|
212
|
+
- lib/heimdall_tools/help/aws_config_mapper.md
|
|
196
213
|
- lib/heimdall_tools/help/burpsuite_mapper.md
|
|
197
214
|
- lib/heimdall_tools/help/dbprotect_mapper.md
|
|
198
215
|
- lib/heimdall_tools/help/fortify_mapper.md
|