cfn-nag 0.0.44 → 0.1.0
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/bin/cfn_nag +27 -11
- data/bin/cfn_nag_rules +5 -4
- data/bin/cfn_nag_scan +29 -0
- data/lib/cfn-nag.rb +3 -0
- data/lib/cfn-nag/cfn_nag.rb +115 -0
- data/lib/cfn-nag/custom_rule_loader.rb +72 -0
- data/lib/cfn-nag/custom_rules/CloudFormationAuthenticationRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/CloudFrontDistributionAccessLoggingRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/EbsVolumeHasSseRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/ElasticLoadBalancerAccessLoggingRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyNotResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyWildcardActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyWildcardResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyNotResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyWildcardActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyWildcardResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotActionOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotActionOnTrustPolicyRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotPrincipalOnTrustPolicyRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotResourceOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/IamRoleWildcardActionOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/IamRoleWildcardActionOnTrustPolicyRule.rb +27 -0
- data/lib/cfn-nag/custom_rules/IamRoleWildcardResourceOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/LambdaPermissionInvokeFunctionActionRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/LambdaPermissionWildcardPrincipalRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/ManagedPolicyOnUserRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/PolicyOnUserRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyNotPrincipalRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyWildcardActionRule.rb +30 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyWildcardPrincipalRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/S3BucketPublicReadAclRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/S3BucketPublicReadWriteAclRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupEgressOpenToWorldRule.rb +39 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupEgressPortRangeRule.rb +38 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb +40 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupIngressOpenToWorldRule.rb +39 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupIngressPortRangeRule.rb +38 -0
- data/lib/{custom_rules/security_group_missing_egress.rb → cfn-nag/custom_rules/SecurityGroupMissingEgressRule.rb} +6 -12
- data/lib/cfn-nag/custom_rules/SnsTopicPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/SnsTopicPolicyNotPrincipalRule.rb +26 -0
- data/lib/cfn-nag/custom_rules/SnsTopicPolicyWildcardPrincipalRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyNotPrincipalRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardActionRule.rb +30 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardPrincipalRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/UserHasInlinePolicyRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/UserMissingGroupRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/WafWebAclDefaultActionRule.rb +34 -0
- data/lib/cfn-nag/custom_rules/base.rb +28 -0
- data/lib/cfn-nag/custom_rules/unencrypted_s3_put_allowed.rb +58 -0
- data/lib/{profile.rb → cfn-nag/profile.rb} +0 -1
- data/lib/{profile_loader.rb → cfn-nag/profile_loader.rb} +2 -2
- data/lib/{result_view → cfn-nag/result_view}/json_results.rb +0 -0
- data/lib/{result_view → cfn-nag/result_view}/rules_view.rb +0 -0
- data/lib/{result_view → cfn-nag/result_view}/simple_stdout_results.rb +5 -12
- data/lib/cfn-nag/rule_definition.rb +36 -0
- data/lib/cfn-nag/rule_dumper.rb +23 -0
- data/lib/cfn-nag/rule_registry.rb +43 -0
- data/lib/cfn-nag/template_discovery.rb +24 -0
- data/lib/cfn-nag/violation.rb +58 -0
- metadata +79 -36
- data/lib/cfn_nag.rb +0 -219
- data/lib/custom_rule_loader.rb +0 -64
- data/lib/custom_rules/unencrypted_s3_put_allowed.rb +0 -58
- data/lib/custom_rules/user_missing_group.rb +0 -34
- data/lib/json_rules/basic_rules.rb +0 -49
- data/lib/json_rules/cfn_rules.rb +0 -4
- data/lib/json_rules/cidr_rules.rb +0 -77
- data/lib/json_rules/cloudfront_rules.rb +0 -4
- data/lib/json_rules/ebs_rules.rb +0 -4
- data/lib/json_rules/iam_policy_rules.rb +0 -153
- data/lib/json_rules/iam_user_rules.rb +0 -15
- data/lib/json_rules/lambda_rules.rb +0 -9
- data/lib/json_rules/loadbalancer_rules.rb +0 -9
- data/lib/json_rules/port_rules.rb +0 -33
- data/lib/json_rules/s3_bucket_rules.rb +0 -51
- data/lib/json_rules/sns_rules.rb +0 -29
- data/lib/json_rules/sqs_rules.rb +0 -25
- data/lib/model/action_parser.rb +0 -27
- data/lib/model/cfn_model.rb +0 -182
- data/lib/model/iam_user_parser.rb +0 -34
- data/lib/model/parser_registry.rb +0 -31
- data/lib/model/s3_bucket_policy.rb +0 -25
- data/lib/model/s3_bucket_policy_parser.rb +0 -28
- data/lib/model/security_group_parser.rb +0 -59
- data/lib/rule.rb +0 -208
- data/lib/rule_registry.rb +0 -45
- data/lib/violation.rb +0 -41
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'custom_rule_loader'
|
2
|
+
require_relative 'profile_loader'
|
3
|
+
require_relative 'result_view/rules_view'
|
4
|
+
|
5
|
+
class CfnNagRuleDumper
|
6
|
+
def initialize(profile_definition: nil,
|
7
|
+
rule_directory: nil)
|
8
|
+
@rule_directory = rule_directory
|
9
|
+
@profile_definition = profile_definition
|
10
|
+
end
|
11
|
+
|
12
|
+
def dump_rules
|
13
|
+
custom_rule_loader = CustomRuleLoader.new(rule_directory: @rule_directory)
|
14
|
+
rule_registry = custom_rule_loader.rule_definitions
|
15
|
+
|
16
|
+
profile = nil
|
17
|
+
unless @profile_definition.nil?
|
18
|
+
profile = ProfileLoader.new(rule_registry).load(profile_definition: @profile_definition)
|
19
|
+
end
|
20
|
+
|
21
|
+
RulesView.new.emit(rule_registry, profile)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'rule_definition'
|
2
|
+
|
3
|
+
class RuleRegistry
|
4
|
+
attr_reader :rules
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@rules = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def definition(id:,
|
11
|
+
type:,
|
12
|
+
message:)
|
13
|
+
rule_definition = RuleDefinition.new(id: id,
|
14
|
+
type: type,
|
15
|
+
message: message)
|
16
|
+
existing_def = by_id id
|
17
|
+
|
18
|
+
if existing_def.nil?
|
19
|
+
add_rule rule_definition
|
20
|
+
else
|
21
|
+
existing_def
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def by_id(id)
|
26
|
+
@rules.find { |rule| rule.id == id }
|
27
|
+
end
|
28
|
+
|
29
|
+
def warnings
|
30
|
+
@rules.select { |rule| rule.type == RuleDefinition::WARNING }
|
31
|
+
end
|
32
|
+
|
33
|
+
def failings
|
34
|
+
@rules.select { |rule| rule.type == RuleDefinition::FAILING_VIOLATION }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def add_rule(violation_def)
|
40
|
+
@rules << violation_def
|
41
|
+
violation_def
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class TemplateDiscovery
|
2
|
+
def discover_templates(input_json_path)
|
3
|
+
if ::File.directory? input_json_path
|
4
|
+
templates = find_templates_in_directory(directory: input_json_path)
|
5
|
+
elsif ::File.file? input_json_path
|
6
|
+
templates = [input_json_path]
|
7
|
+
else
|
8
|
+
fail "#{input_json_path} is not a proper path"
|
9
|
+
end
|
10
|
+
templates
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def find_templates_in_directory(directory:,
|
16
|
+
cfn_extensions: %w(json yaml yml template))
|
17
|
+
|
18
|
+
templates = []
|
19
|
+
cfn_extensions.each do |cfn_extension|
|
20
|
+
templates += Dir[File.join(directory, "**/*.#{cfn_extension}")]
|
21
|
+
end
|
22
|
+
templates
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative 'rule_definition'
|
2
|
+
|
3
|
+
class Violation < RuleDefinition
|
4
|
+
attr_reader :logical_resource_ids
|
5
|
+
|
6
|
+
def initialize(id:,
|
7
|
+
type:,
|
8
|
+
message:,
|
9
|
+
logical_resource_ids: nil)
|
10
|
+
super id: id,
|
11
|
+
type: type,
|
12
|
+
message: message
|
13
|
+
|
14
|
+
@logical_resource_ids = logical_resource_ids
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
"#{super.to_s} #{@logical_resource_ids}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_h
|
22
|
+
super.to_h.merge({
|
23
|
+
logical_resource_ids: @logical_resource_ids
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.count_warnings(violations)
|
28
|
+
violations.inject(0) do |count, violation|
|
29
|
+
if violation.type == Violation::WARNING
|
30
|
+
if empty?(violation.logical_resource_ids)
|
31
|
+
count += 1
|
32
|
+
else
|
33
|
+
count += violation.logical_resource_ids.size
|
34
|
+
end
|
35
|
+
end
|
36
|
+
count
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.count_failures(violations)
|
41
|
+
violations.inject(0) do |count, violation|
|
42
|
+
if violation.type == Violation::FAILING_VIOLATION
|
43
|
+
if empty?(violation.logical_resource_ids)
|
44
|
+
count += 1
|
45
|
+
else
|
46
|
+
count += violation.logical_resource_ids.size
|
47
|
+
end
|
48
|
+
end
|
49
|
+
count
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def self.empty?(array)
|
56
|
+
array.nil? || array.size ==0
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfn-nag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Eric Kascic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logging
|
@@ -38,49 +38,92 @@ dependencies:
|
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.1.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: cfn-model
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.0.5
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.5
|
41
55
|
description: Auditing tool for CloudFormation templates
|
42
56
|
email:
|
43
57
|
executables:
|
44
58
|
- cfn_nag
|
45
59
|
- cfn_nag_rules
|
60
|
+
- cfn_nag_scan
|
46
61
|
extensions: []
|
47
62
|
extra_rdoc_files: []
|
48
63
|
files:
|
49
64
|
- bin/cfn_nag
|
50
65
|
- bin/cfn_nag_rules
|
51
|
-
-
|
52
|
-
- lib/
|
53
|
-
- lib/
|
54
|
-
- lib/
|
55
|
-
- lib/custom_rules/
|
56
|
-
- lib/
|
57
|
-
- lib/
|
58
|
-
- lib/
|
59
|
-
- lib/
|
60
|
-
- lib/
|
61
|
-
- lib/
|
62
|
-
- lib/
|
63
|
-
- lib/
|
64
|
-
- lib/
|
65
|
-
- lib/
|
66
|
-
- lib/
|
67
|
-
- lib/
|
68
|
-
- lib/
|
69
|
-
- lib/
|
70
|
-
- lib/
|
71
|
-
- lib/
|
72
|
-
- lib/
|
73
|
-
- lib/
|
74
|
-
- lib/
|
75
|
-
- lib/
|
76
|
-
- lib/
|
77
|
-
- lib/
|
78
|
-
- lib/
|
79
|
-
- lib/
|
80
|
-
- lib/
|
81
|
-
- lib/
|
82
|
-
- lib/
|
83
|
-
- lib/
|
66
|
+
- bin/cfn_nag_scan
|
67
|
+
- lib/cfn-nag.rb
|
68
|
+
- lib/cfn-nag/cfn_nag.rb
|
69
|
+
- lib/cfn-nag/custom_rule_loader.rb
|
70
|
+
- lib/cfn-nag/custom_rules/CloudFormationAuthenticationRule.rb
|
71
|
+
- lib/cfn-nag/custom_rules/CloudFrontDistributionAccessLoggingRule.rb
|
72
|
+
- lib/cfn-nag/custom_rules/EbsVolumeHasSseRule.rb
|
73
|
+
- lib/cfn-nag/custom_rules/ElasticLoadBalancerAccessLoggingRule.rb
|
74
|
+
- lib/cfn-nag/custom_rules/IamManagedPolicyNotActionRule.rb
|
75
|
+
- lib/cfn-nag/custom_rules/IamManagedPolicyNotResourceRule.rb
|
76
|
+
- lib/cfn-nag/custom_rules/IamManagedPolicyWildcardActionRule.rb
|
77
|
+
- lib/cfn-nag/custom_rules/IamManagedPolicyWildcardResourceRule.rb
|
78
|
+
- lib/cfn-nag/custom_rules/IamPolicyNotActionRule.rb
|
79
|
+
- lib/cfn-nag/custom_rules/IamPolicyNotResourceRule.rb
|
80
|
+
- lib/cfn-nag/custom_rules/IamPolicyWildcardActionRule.rb
|
81
|
+
- lib/cfn-nag/custom_rules/IamPolicyWildcardResourceRule.rb
|
82
|
+
- lib/cfn-nag/custom_rules/IamRoleNotActionOnPermissionsPolicyRule.rb
|
83
|
+
- lib/cfn-nag/custom_rules/IamRoleNotActionOnTrustPolicyRule.rb
|
84
|
+
- lib/cfn-nag/custom_rules/IamRoleNotPrincipalOnTrustPolicyRule.rb
|
85
|
+
- lib/cfn-nag/custom_rules/IamRoleNotResourceOnPermissionsPolicyRule.rb
|
86
|
+
- lib/cfn-nag/custom_rules/IamRoleWildcardActionOnPermissionsPolicyRule.rb
|
87
|
+
- lib/cfn-nag/custom_rules/IamRoleWildcardActionOnTrustPolicyRule.rb
|
88
|
+
- lib/cfn-nag/custom_rules/IamRoleWildcardResourceOnPermissionsPolicyRule.rb
|
89
|
+
- lib/cfn-nag/custom_rules/LambdaPermissionInvokeFunctionActionRule.rb
|
90
|
+
- lib/cfn-nag/custom_rules/LambdaPermissionWildcardPrincipalRule.rb
|
91
|
+
- lib/cfn-nag/custom_rules/ManagedPolicyOnUserRule.rb
|
92
|
+
- lib/cfn-nag/custom_rules/PolicyOnUserRule.rb
|
93
|
+
- lib/cfn-nag/custom_rules/S3BucketPolicyNotActionRule.rb
|
94
|
+
- lib/cfn-nag/custom_rules/S3BucketPolicyNotPrincipalRule.rb
|
95
|
+
- lib/cfn-nag/custom_rules/S3BucketPolicyWildcardActionRule.rb
|
96
|
+
- lib/cfn-nag/custom_rules/S3BucketPolicyWildcardPrincipalRule.rb
|
97
|
+
- lib/cfn-nag/custom_rules/S3BucketPublicReadAclRule.rb
|
98
|
+
- lib/cfn-nag/custom_rules/S3BucketPublicReadWriteAclRule.rb
|
99
|
+
- lib/cfn-nag/custom_rules/SecurityGroupEgressOpenToWorldRule.rb
|
100
|
+
- lib/cfn-nag/custom_rules/SecurityGroupEgressPortRangeRule.rb
|
101
|
+
- lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb
|
102
|
+
- lib/cfn-nag/custom_rules/SecurityGroupIngressOpenToWorldRule.rb
|
103
|
+
- lib/cfn-nag/custom_rules/SecurityGroupIngressPortRangeRule.rb
|
104
|
+
- lib/cfn-nag/custom_rules/SecurityGroupMissingEgressRule.rb
|
105
|
+
- lib/cfn-nag/custom_rules/SnsTopicPolicyNotActionRule.rb
|
106
|
+
- lib/cfn-nag/custom_rules/SnsTopicPolicyNotPrincipalRule.rb
|
107
|
+
- lib/cfn-nag/custom_rules/SnsTopicPolicyWildcardPrincipalRule.rb
|
108
|
+
- lib/cfn-nag/custom_rules/SqsQueuePolicyNotActionRule.rb
|
109
|
+
- lib/cfn-nag/custom_rules/SqsQueuePolicyNotPrincipalRule.rb
|
110
|
+
- lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardActionRule.rb
|
111
|
+
- lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardPrincipalRule.rb
|
112
|
+
- lib/cfn-nag/custom_rules/UserHasInlinePolicyRule.rb
|
113
|
+
- lib/cfn-nag/custom_rules/UserMissingGroupRule.rb
|
114
|
+
- lib/cfn-nag/custom_rules/WafWebAclDefaultActionRule.rb
|
115
|
+
- lib/cfn-nag/custom_rules/base.rb
|
116
|
+
- lib/cfn-nag/custom_rules/unencrypted_s3_put_allowed.rb
|
117
|
+
- lib/cfn-nag/profile.rb
|
118
|
+
- lib/cfn-nag/profile_loader.rb
|
119
|
+
- lib/cfn-nag/result_view/json_results.rb
|
120
|
+
- lib/cfn-nag/result_view/rules_view.rb
|
121
|
+
- lib/cfn-nag/result_view/simple_stdout_results.rb
|
122
|
+
- lib/cfn-nag/rule_definition.rb
|
123
|
+
- lib/cfn-nag/rule_dumper.rb
|
124
|
+
- lib/cfn-nag/rule_registry.rb
|
125
|
+
- lib/cfn-nag/template_discovery.rb
|
126
|
+
- lib/cfn-nag/violation.rb
|
84
127
|
homepage: https://github.com/stelligent/cfn_nag
|
85
128
|
licenses:
|
86
129
|
- MIT
|
data/lib/cfn_nag.rb
DELETED
@@ -1,219 +0,0 @@
|
|
1
|
-
require_relative 'rule'
|
2
|
-
require_relative 'custom_rule_loader'
|
3
|
-
require_relative 'rule_registry'
|
4
|
-
require_relative 'profile_loader'
|
5
|
-
require_relative 'model/cfn_model'
|
6
|
-
require_relative 'result_view/simple_stdout_results'
|
7
|
-
require_relative 'result_view/json_results'
|
8
|
-
require_relative 'result_view/rules_view'
|
9
|
-
require 'tempfile'
|
10
|
-
|
11
|
-
class CfnNag
|
12
|
-
include Rule
|
13
|
-
|
14
|
-
def initialize(profile_definition: nil)
|
15
|
-
@warning_registry = []
|
16
|
-
@violation_registry = []
|
17
|
-
@rule_registry = RuleRegistry.new
|
18
|
-
@custom_rule_loader = CustomRuleLoader.new(@rule_registry)
|
19
|
-
@profile_definition = profile_definition
|
20
|
-
end
|
21
|
-
|
22
|
-
def dump_rules(rule_directories: [])
|
23
|
-
validate_extra_rule_directories(rule_directories)
|
24
|
-
|
25
|
-
dummy_cfn = <<-END
|
26
|
-
{
|
27
|
-
"Resources": {
|
28
|
-
"resource1": {
|
29
|
-
"Type" : "AWS::EC2::DHCPOptions",
|
30
|
-
"Properties": {
|
31
|
-
"DomainNameServers" : [ "10.0.0.1" ]
|
32
|
-
}
|
33
|
-
}
|
34
|
-
}
|
35
|
-
}
|
36
|
-
END
|
37
|
-
|
38
|
-
Tempfile.open('tempfile') do |dummy_cfn_template|
|
39
|
-
dummy_cfn_template.write dummy_cfn
|
40
|
-
dummy_cfn_template.rewind
|
41
|
-
audit_file(input_json_path: dummy_cfn_template.path,
|
42
|
-
rule_directories: rule_directories)
|
43
|
-
end
|
44
|
-
|
45
|
-
profile = nil
|
46
|
-
unless @profile_definition.nil?
|
47
|
-
profile = ProfileLoader.new(@rule_registry).load(profile_definition: @profile_definition)
|
48
|
-
end
|
49
|
-
|
50
|
-
RulesView.new.emit(@rule_registry, profile)
|
51
|
-
end
|
52
|
-
|
53
|
-
def audit(input_json_path:,
|
54
|
-
rule_directories: [],
|
55
|
-
output_format:'txt')
|
56
|
-
validate_extra_rule_directories(rule_directories)
|
57
|
-
|
58
|
-
aggregate_results = audit_results input_json_path: input_json_path,
|
59
|
-
output_format: output_format,
|
60
|
-
rule_directories: rule_directories.flatten
|
61
|
-
|
62
|
-
aggregate_results.inject(0) { |total_failure_count, results| total_failure_count + results[:file_results][:failure_count] }
|
63
|
-
end
|
64
|
-
|
65
|
-
def audit_results(input_json_path:,
|
66
|
-
output_format:'txt',
|
67
|
-
rule_directories: [])
|
68
|
-
|
69
|
-
templates = discover_templates(input_json_path)
|
70
|
-
|
71
|
-
aggregate_results = []
|
72
|
-
templates.each do |template|
|
73
|
-
aggregate_results << {
|
74
|
-
filename: template,
|
75
|
-
file_results: audit_file(input_json_path: template,
|
76
|
-
rule_directories: rule_directories)
|
77
|
-
}
|
78
|
-
end
|
79
|
-
|
80
|
-
render_results(aggregate_results: aggregate_results,
|
81
|
-
output_format: output_format)
|
82
|
-
|
83
|
-
aggregate_results
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.configure_logging(opts)
|
87
|
-
logger = Logging.logger['log']
|
88
|
-
if opts[:debug]
|
89
|
-
logger.level = :debug
|
90
|
-
else
|
91
|
-
logger.level = :info
|
92
|
-
end
|
93
|
-
|
94
|
-
logger.add_appenders Logging.appenders.stdout
|
95
|
-
end
|
96
|
-
|
97
|
-
def audit_template(input_json:,
|
98
|
-
rule_directories: [])
|
99
|
-
@stop_processing = false
|
100
|
-
@violations = []
|
101
|
-
|
102
|
-
unless legal_json?(input_json)
|
103
|
-
@violations << Violation.new(id: 'FATAL',
|
104
|
-
type: Violation::FAILING_VIOLATION,
|
105
|
-
message: 'not even legit JSON',
|
106
|
-
violating_code: input_json)
|
107
|
-
@stop_processing = true
|
108
|
-
end
|
109
|
-
|
110
|
-
generic_json_rules(input_json, rule_directories) unless @stop_processing == true
|
111
|
-
|
112
|
-
@violations += custom_rules input_json unless @stop_processing == true
|
113
|
-
|
114
|
-
@violations = filter_violations_by_profile @violations unless @stop_processing == true
|
115
|
-
|
116
|
-
{
|
117
|
-
failure_count: Rule::count_failures(@violations),
|
118
|
-
violations: @violations
|
119
|
-
}
|
120
|
-
end
|
121
|
-
|
122
|
-
private
|
123
|
-
|
124
|
-
def filter_violations_by_profile(violations)
|
125
|
-
profile = nil
|
126
|
-
unless @profile_definition.nil?
|
127
|
-
profile = ProfileLoader.new(@rule_registry).load(profile_definition: @profile_definition)
|
128
|
-
end
|
129
|
-
|
130
|
-
violations.reject do |violation|
|
131
|
-
not profile.nil? and not profile.execute_rule?(violation.id)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def validate_extra_rule_directories(rule_directories)
|
136
|
-
rule_directories.flatten.each do |rule_directory|
|
137
|
-
fail "Not a real directory #{rule_directory}" unless File.directory? rule_directory
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
|
142
|
-
def render_results(aggregate_results:,
|
143
|
-
output_format:)
|
144
|
-
results_renderer(output_format).new.render(aggregate_results)
|
145
|
-
end
|
146
|
-
|
147
|
-
def audit_file(input_json_path:,
|
148
|
-
rule_directories:)
|
149
|
-
audit_template(input_json: IO.read(input_json_path),
|
150
|
-
rule_directories: rule_directories)
|
151
|
-
end
|
152
|
-
|
153
|
-
def discover_templates(input_json_path)
|
154
|
-
if ::File.directory? input_json_path
|
155
|
-
templates = find_templates_in_directory(directory: input_json_path)
|
156
|
-
elsif ::File.file? input_json_path
|
157
|
-
templates = [input_json_path.path]
|
158
|
-
else
|
159
|
-
fail "#{input_json_path} is not a proper path"
|
160
|
-
end
|
161
|
-
templates
|
162
|
-
end
|
163
|
-
|
164
|
-
def find_templates_in_directory(directory:,
|
165
|
-
cfn_extensions: %w(json template))
|
166
|
-
|
167
|
-
templates = []
|
168
|
-
cfn_extensions.each do |cfn_extension|
|
169
|
-
templates += Dir[File.join(directory, "**/*.#{cfn_extension}")]
|
170
|
-
end
|
171
|
-
templates
|
172
|
-
end
|
173
|
-
|
174
|
-
def results_renderer(output_format)
|
175
|
-
registry = {
|
176
|
-
'txt' => SimpleStdoutResults,
|
177
|
-
'json' => JsonResults
|
178
|
-
}
|
179
|
-
registry[output_format]
|
180
|
-
end
|
181
|
-
|
182
|
-
def legal_json?(input_json)
|
183
|
-
begin
|
184
|
-
JSON.parse(input_json)
|
185
|
-
true
|
186
|
-
rescue JSON::ParserError
|
187
|
-
return false
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def command?(command)
|
192
|
-
not system("#{command} > /dev/null 2>&1").nil?
|
193
|
-
end
|
194
|
-
|
195
|
-
def generic_json_rules(input_json, rule_directories)
|
196
|
-
unless command? 'jq'
|
197
|
-
fail 'jq executable must be available in PATH'
|
198
|
-
end
|
199
|
-
rules = Dir[File.join(__dir__, 'json_rules', '*.rb')].sort
|
200
|
-
|
201
|
-
rules.each do |rule_file|
|
202
|
-
@input_json = input_json
|
203
|
-
eval IO.read(rule_file)
|
204
|
-
end
|
205
|
-
|
206
|
-
rule_directories.each do |rule_directory|
|
207
|
-
rules = Dir[File.join(rule_directory, '*.rb')].sort
|
208
|
-
|
209
|
-
rules.each do |rule_file|
|
210
|
-
@input_json = input_json
|
211
|
-
eval IO.read(rule_file)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def custom_rules(input_json)
|
217
|
-
@custom_rule_loader.custom_rules(input_json)
|
218
|
-
end
|
219
|
-
end
|