cfn-nag 0.0.44 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 905bc16ca0d4964c17e4a532a444b174541c61a6
|
4
|
+
data.tar.gz: 5b76a420e36c46f4adeff8506cae88ff76462b83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da46ac982d9a672b38b8161dbb7b123763fb88f34a0a196c6059cee52157076796c18973a385525cc9f00c50b4bf6ab8abcf992b6ddf6cd08e201c6482efce9d
|
7
|
+
data.tar.gz: da78b9bf29944292f4221ab5dd0dd4cca0c03d0398f164f03b391cf29164b29fc1fbb437851b822411e24297ca31473f6feebf7e175ff83a582d5b191badf4a2
|
data/bin/cfn_nag
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'trollop'
|
3
|
-
require '
|
3
|
+
require 'cfn-nag'
|
4
4
|
require 'logging'
|
5
|
+
require 'json'
|
5
6
|
|
6
7
|
opts = Trollop::options do
|
7
|
-
|
8
|
-
|
8
|
+
usage '[options] <cloudformation template path ...>|<cloudformation template in STDIN>'
|
9
|
+
|
9
10
|
opt :debug, 'Enable debug output', type: :boolean, required: false, default: false
|
10
|
-
opt :rule_directory, 'Extra rule
|
11
|
+
opt :rule_directory, 'Extra rule directory', type: :io, required: false, default: nil
|
11
12
|
opt :profile_path, 'Path to a profile file', type: :io, required: false, default: nil
|
12
13
|
end
|
13
14
|
|
14
|
-
Trollop::die(:output_format,
|
15
|
-
'Must be txt or json') unless %w(txt json).include?(opts[:output_format])
|
16
|
-
|
17
15
|
CfnNag::configure_logging(opts)
|
18
16
|
|
19
17
|
profile_definition = nil
|
@@ -21,8 +19,26 @@ unless opts[:profile_path].nil?
|
|
21
19
|
profile_definition = IO.read(opts[:profile_path])
|
22
20
|
end
|
23
21
|
|
24
|
-
cfn_nag = CfnNag.new(profile_definition: profile_definition
|
22
|
+
cfn_nag = CfnNag.new(profile_definition: profile_definition,
|
23
|
+
rule_directory: opts[:rule_directory])
|
24
|
+
|
25
|
+
# trollop appears to pop args off of ARGV
|
26
|
+
# ARGF concatenates which we don't want
|
27
|
+
if ARGV.size == 0
|
28
|
+
results = cfn_nag.audit(cloudformation_string: STDIN.read)
|
29
|
+
|
30
|
+
results[:violations] = results[:violations].map { |violation| violation.to_h }
|
31
|
+
puts JSON.pretty_generate(results)
|
32
|
+
exit results[:failure_count]
|
33
|
+
else
|
34
|
+
total_failure_count = 0
|
35
|
+
ARGV.each do |file_name|
|
36
|
+
results = cfn_nag.audit(cloudformation_string: IO.read(file_name))
|
37
|
+
|
38
|
+
total_failure_count += results[:failure_count]
|
39
|
+
results[:violations] = results[:violations].map { |violation| violation.to_h }
|
40
|
+
puts JSON.pretty_generate(results)
|
41
|
+
end
|
42
|
+
exit total_failure_count
|
43
|
+
end
|
25
44
|
|
26
|
-
exit cfn_nag.audit(input_json_path: opts[:input_json_path],
|
27
|
-
output_format: opts[:output_format],
|
28
|
-
rule_directories: opts[:rule_directory])
|
data/bin/cfn_nag_rules
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'trollop'
|
3
|
-
require '
|
3
|
+
require 'cfn-nag'
|
4
4
|
|
5
5
|
opts = Trollop::options do
|
6
|
-
opt :rule_directory, 'Extra rule directories', type: :
|
6
|
+
opt :rule_directory, 'Extra rule directories', type: :io, required: false, default: nil
|
7
7
|
opt :profile_path, 'Path to a profile file', type: :io, required: false, default: nil
|
8
8
|
end
|
9
9
|
|
@@ -12,6 +12,7 @@ unless opts[:profile_path].nil?
|
|
12
12
|
profile_definition = IO.read(opts[:profile_path])
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
rule_dumper = CfnNagRuleDumper.new(profile_definition: profile_definition,
|
16
|
+
rule_directory: opts[:rule_directory])
|
16
17
|
|
17
|
-
|
18
|
+
rule_dumper.dump_rules
|
data/bin/cfn_nag_scan
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'trollop'
|
3
|
+
require 'cfn-nag'
|
4
|
+
require 'logging'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
opts = Trollop::options do
|
8
|
+
opt :input_path, 'CloudFormation template to nag on or directory of templates - all *.json, *.yaml, *.yml and *.template recursively', type: :io, required: true
|
9
|
+
opt :output_format, 'Format of results: [txt, json]', type: :string, default: 'txt'
|
10
|
+
opt :debug, 'Enable debug output', type: :boolean, required: false, default: false
|
11
|
+
opt :rule_directory, 'Extra rule directory', type: :io, required: false, default: nil
|
12
|
+
opt :profile_path, 'Path to a profile file', type: :io, required: false, default: nil
|
13
|
+
end
|
14
|
+
|
15
|
+
Trollop::die(:output_format,
|
16
|
+
'Must be txt or json') unless %w(txt json).include?(opts[:output_format])
|
17
|
+
|
18
|
+
CfnNag::configure_logging(opts)
|
19
|
+
|
20
|
+
profile_definition = nil
|
21
|
+
unless opts[:profile_path].nil?
|
22
|
+
profile_definition = IO.read(opts[:profile_path])
|
23
|
+
end
|
24
|
+
|
25
|
+
cfn_nag = CfnNag.new(profile_definition: profile_definition,
|
26
|
+
rule_directory: opts[:rule_directory])
|
27
|
+
|
28
|
+
exit cfn_nag.audit_aggregate_across_files_and_render_results(input_path: opts[:input_path],
|
29
|
+
output_format: opts[:output_format])
|
data/lib/cfn-nag.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'custom_rule_loader'
|
2
|
+
require_relative 'rule_registry'
|
3
|
+
require_relative 'profile_loader'
|
4
|
+
require_relative 'template_discovery'
|
5
|
+
require_relative 'result_view/simple_stdout_results'
|
6
|
+
require_relative 'result_view/json_results'
|
7
|
+
require 'cfn-model'
|
8
|
+
require 'logging'
|
9
|
+
|
10
|
+
class CfnNag
|
11
|
+
def initialize(profile_definition: nil,
|
12
|
+
rule_directory: nil)
|
13
|
+
@rule_directory = rule_directory
|
14
|
+
@custom_rule_loader = CustomRuleLoader.new(rule_directory: rule_directory)
|
15
|
+
@profile_definition = profile_definition
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Given a file or directory path, emit aggregate results to stdout
|
20
|
+
#
|
21
|
+
# Return an aggregate failure count (for exit code usage)
|
22
|
+
#
|
23
|
+
def audit_aggregate_across_files_and_render_results(input_path:,
|
24
|
+
output_format:'txt')
|
25
|
+
aggregate_results = audit_aggregate_across_files input_path: input_path
|
26
|
+
|
27
|
+
render_results(aggregate_results: aggregate_results,
|
28
|
+
output_format: output_format)
|
29
|
+
|
30
|
+
aggregate_results.inject(0) do |total_failure_count, results|
|
31
|
+
total_failure_count + results[:file_results][:failure_count]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Given a file or directory path, return aggregate results
|
37
|
+
#
|
38
|
+
def audit_aggregate_across_files(input_path:)
|
39
|
+
templates = TemplateDiscovery.new.discover_templates(input_path)
|
40
|
+
|
41
|
+
aggregate_results = []
|
42
|
+
templates.each do |template|
|
43
|
+
aggregate_results << {
|
44
|
+
filename: template,
|
45
|
+
file_results: audit(cloudformation_string: IO.read(template))
|
46
|
+
}
|
47
|
+
end
|
48
|
+
aggregate_results
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Given cloudformation json/yml, run all the rules against it
|
53
|
+
#
|
54
|
+
# Return a hash with failure count
|
55
|
+
#
|
56
|
+
def audit(cloudformation_string:)
|
57
|
+
stop_processing = false
|
58
|
+
violations = []
|
59
|
+
|
60
|
+
begin
|
61
|
+
cfn_model = CfnParser.new.parse cloudformation_string
|
62
|
+
rescue ParserError => parser_error
|
63
|
+
violations << Violation.new(id: 'FATAL',
|
64
|
+
type: Violation::FAILING_VIOLATION,
|
65
|
+
message: parser_error.to_s)
|
66
|
+
stop_processing = true
|
67
|
+
end
|
68
|
+
|
69
|
+
violations += @custom_rule_loader.execute_custom_rules(cfn_model) unless stop_processing == true
|
70
|
+
|
71
|
+
violations = filter_violations_by_profile violations unless stop_processing == true
|
72
|
+
|
73
|
+
{
|
74
|
+
failure_count: Violation.count_failures(violations),
|
75
|
+
violations: violations
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.configure_logging(opts)
|
80
|
+
logger = Logging.logger['log']
|
81
|
+
if opts[:debug]
|
82
|
+
logger.level = :debug
|
83
|
+
else
|
84
|
+
logger.level = :info
|
85
|
+
end
|
86
|
+
|
87
|
+
logger.add_appenders Logging.appenders.stdout
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def filter_violations_by_profile(violations)
|
93
|
+
profile = nil
|
94
|
+
unless @profile_definition.nil?
|
95
|
+
profile = ProfileLoader.new(@custom_rule_loader.rule_definitions).load(profile_definition: @profile_definition)
|
96
|
+
end
|
97
|
+
|
98
|
+
violations.reject do |violation|
|
99
|
+
not profile.nil? and not profile.execute_rule?(violation.id)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def render_results(aggregate_results:,
|
104
|
+
output_format:)
|
105
|
+
results_renderer(output_format).new.render(aggregate_results)
|
106
|
+
end
|
107
|
+
|
108
|
+
def results_renderer(output_format)
|
109
|
+
registry = {
|
110
|
+
'txt' => SimpleStdoutResults,
|
111
|
+
'json' => JsonResults
|
112
|
+
}
|
113
|
+
registry[output_format]
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'cfn-model'
|
2
|
+
require 'logging'
|
3
|
+
require_relative 'rule_registry'
|
4
|
+
|
5
|
+
##
|
6
|
+
# This object can discover the internal and custom user-provided rules and
|
7
|
+
# apply these rules to a CfnModel object
|
8
|
+
#
|
9
|
+
class CustomRuleLoader
|
10
|
+
def initialize(rule_directory: nil)
|
11
|
+
@rule_directory = rule_directory
|
12
|
+
validate_extra_rule_directory rule_directory
|
13
|
+
end
|
14
|
+
|
15
|
+
def rule_definitions
|
16
|
+
rule_registry = RuleRegistry.new
|
17
|
+
|
18
|
+
discover_rule_classes(@rule_directory).each do |rule_class|
|
19
|
+
rule = rule_class.new
|
20
|
+
rule_registry.definition(id: rule.rule_id,
|
21
|
+
type: rule.rule_type,
|
22
|
+
message: rule.rule_text)
|
23
|
+
end
|
24
|
+
rule_registry
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute_custom_rules(cfn_model)
|
28
|
+
Logging.logger['log'].debug "cfn_model: #{cfn_model}"
|
29
|
+
|
30
|
+
violations = []
|
31
|
+
|
32
|
+
discover_rule_classes(@rule_directory).each do |rule_class|
|
33
|
+
audit_result = rule_class.new.audit(cfn_model)
|
34
|
+
violations << audit_result unless audit_result.nil?
|
35
|
+
end
|
36
|
+
violations
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def validate_extra_rule_directory(rule_directory)
|
42
|
+
unless rule_directory.nil?
|
43
|
+
fail "Not a real directory #{rule_directory}" unless File.directory? rule_directory
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def discover_rule_filenames(rule_directory)
|
48
|
+
rule_filenames = []
|
49
|
+
unless rule_directory.nil?
|
50
|
+
rule_filenames += Dir[File.join(rule_directory, '*Rule.rb')].sort
|
51
|
+
end
|
52
|
+
rule_filenames += Dir[File.join(__dir__, 'custom_rules', '*Rule.rb')].sort
|
53
|
+
Logging.logger['log'].debug "rule_filenames: #{rule_filenames}"
|
54
|
+
rule_filenames
|
55
|
+
end
|
56
|
+
|
57
|
+
def discover_rule_classes(rule_directory)
|
58
|
+
rule_classes = []
|
59
|
+
|
60
|
+
rule_filenames = discover_rule_filenames(rule_directory)
|
61
|
+
|
62
|
+
rule_filenames.each do |rule_filename|
|
63
|
+
require(rule_filename)
|
64
|
+
rule_classname = File.basename(rule_filename, '.rb')
|
65
|
+
|
66
|
+
rule_classes << Object.const_get(rule_classname)
|
67
|
+
end
|
68
|
+
Logging.logger['log'].debug "rule_classes: #{rule_classes}"
|
69
|
+
|
70
|
+
rule_classes
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class CloudFormationAuthenticationRule < BaseRule
|
5
|
+
def rule_text
|
6
|
+
'Specifying credentials in the template itself is probably not the safest thing'
|
7
|
+
end
|
8
|
+
|
9
|
+
def rule_type
|
10
|
+
Violation::WARNING
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_id
|
14
|
+
'W1'
|
15
|
+
end
|
16
|
+
|
17
|
+
def audit_impl(cfn_model)
|
18
|
+
logical_resource_ids = []
|
19
|
+
cfn_model.raw_model['Resources'].each do |resource_name, resource|
|
20
|
+
unless resource['Metadata'].nil?
|
21
|
+
if !resource['Metadata']['AWS::CloudFormation::Authentication'].nil?
|
22
|
+
logical_resource_ids << resource_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
logical_resource_ids
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class CloudFrontDistributionAccessLoggingRule < BaseRule
|
5
|
+
def rule_text
|
6
|
+
'CloudFront Distribution should enable access logging'
|
7
|
+
end
|
8
|
+
|
9
|
+
def rule_type
|
10
|
+
Violation::WARNING
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_id
|
14
|
+
'W10'
|
15
|
+
end
|
16
|
+
|
17
|
+
def audit_impl(cfn_model)
|
18
|
+
violating_distributions = cfn_model.resources_by_type('AWS::CloudFront::Distribution').select do |distribution|
|
19
|
+
distribution.distributionConfig['Logging'].nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
violating_distributions.map { |distribution| distribution.logical_resource_id }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class EbsVolumeHasSseRule < BaseRule
|
5
|
+
def rule_text
|
6
|
+
'EBS volume should have server-side encryption enabled'
|
7
|
+
end
|
8
|
+
|
9
|
+
def rule_type
|
10
|
+
Violation::FAILING_VIOLATION
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_id
|
14
|
+
'F1'
|
15
|
+
end
|
16
|
+
|
17
|
+
def audit_impl(cfn_model)
|
18
|
+
violating_volumes = cfn_model.resources_by_type('AWS::EC2::Volume').select do |volume|
|
19
|
+
volume.encrypted.nil? || volume.encrypted == false
|
20
|
+
end
|
21
|
+
|
22
|
+
violating_volumes.map { |violating_user| violating_user.logical_resource_id }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class ElasticLoadBalancerAccessLoggingRule < BaseRule
|
5
|
+
def rule_text
|
6
|
+
'Elastic Load Balancer should have access logging enabled'
|
7
|
+
end
|
8
|
+
|
9
|
+
def rule_type
|
10
|
+
Violation::WARNING
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_id
|
14
|
+
'W26'
|
15
|
+
end
|
16
|
+
|
17
|
+
def audit_impl(cfn_model)
|
18
|
+
violating_elbs = cfn_model.resources_by_type('AWS::ElasticLoadBalancing::LoadBalancer').select do |elb|
|
19
|
+
elb.accessLoggingPolicy.nil? || elb.accessLoggingPolicy['Enabled'] != true
|
20
|
+
end
|
21
|
+
|
22
|
+
violating_elbs.map { |violating_user| violating_user.logical_resource_id }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class IamManagedPolicyNotActionRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'IAM managed policy should not allow Allow+NotAction'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::WARNING
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'W17'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
violating_policies = cfn_model.resources_by_type('AWS::IAM::ManagedPolicy').select do |policy|
|
20
|
+
!policy.policyDocument.allows_not_action.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
violating_policies.map { |policy| policy.logical_resource_id }
|
24
|
+
end
|
25
|
+
end
|