cfn-nag 0.3.22 → 0.3.23
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 +8 -2
- data/bin/cfn_nag_scan +3 -1
- data/lib/cfn-nag/cfn_nag.rb +11 -6
- data/lib/cfn-nag/custom_rules/RDSInstanceMasterUserPasswordRule.rb +61 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dbc83f4e332ec0dc78d062c7cb61de979a9ab0a
|
4
|
+
data.tar.gz: a7b949b88a2d4d89ae1fb89de204cfb04ba56a27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 264209cc00d7fac44802652981ed5815643c67a46da322a7617a45a03be6dc079e44ba87515bf95f1544abf07eb4c366b4755ffeb2859e519d643caeee231065
|
7
|
+
data.tar.gz: b33e31569da12196a3be074b83c83744e0a0527ed050580532ca83fb6f74882ed0ad240f7630965c3aeace8b52a4cb1d378d9ae385566395d44d67a05d581dde
|
data/bin/cfn_nag
CHANGED
@@ -14,6 +14,7 @@ opts = Trollop::options do
|
|
14
14
|
opt :print_suppression, 'Emit suppressions to stderr', type: :boolean, required: false, default: false
|
15
15
|
opt :rule_directory, 'Extra rule directory', type: :io, required: false, default: nil
|
16
16
|
opt :profile_path, 'Path to a profile file', type: :io, required: false, default: nil
|
17
|
+
opt :parameter_values_path, 'Path to a JSON file to pull Parameter values from', type: :io, required: false, default: nil
|
17
18
|
opt :isolate_custom_rule_exceptions, 'Isolate custom rule exceptions - just emit the exception without stack trace and keep chugging', type: :boolean, required: false, default: false
|
18
19
|
end
|
19
20
|
|
@@ -24,6 +25,11 @@ unless opts[:profile_path].nil?
|
|
24
25
|
profile_definition = IO.read(opts[:profile_path])
|
25
26
|
end
|
26
27
|
|
28
|
+
parameter_values_string = nil
|
29
|
+
unless opts[:parameter_values_path].nil?
|
30
|
+
parameter_values_string = IO.read(opts[:parameter_values_path])
|
31
|
+
end
|
32
|
+
|
27
33
|
cfn_nag = CfnNag.new(profile_definition: profile_definition,
|
28
34
|
rule_directory: opts[:rule_directory],
|
29
35
|
allow_suppression: opts[:allow_suppression],
|
@@ -33,7 +39,7 @@ cfn_nag = CfnNag.new(profile_definition: profile_definition,
|
|
33
39
|
# trollop appears to pop args off of ARGV
|
34
40
|
# ARGF concatenates which we don't want
|
35
41
|
if ARGV.size == 0
|
36
|
-
results = cfn_nag.audit(cloudformation_string: STDIN.read)
|
42
|
+
results = cfn_nag.audit(cloudformation_string: STDIN.read, parameter_values_string: parameter_values_string)
|
37
43
|
|
38
44
|
results[:violations] = results[:violations].map { |violation| violation.to_h }
|
39
45
|
puts JSON.pretty_generate(results)
|
@@ -41,7 +47,7 @@ if ARGV.size == 0
|
|
41
47
|
else
|
42
48
|
total_failure_count = 0
|
43
49
|
ARGV.each do |file_name|
|
44
|
-
results = cfn_nag.audit(cloudformation_string: IO.read(file_name))
|
50
|
+
results = cfn_nag.audit(cloudformation_string: IO.read(file_name), parameter_values_string: parameter_values_string)
|
45
51
|
|
46
52
|
total_failure_count += results[:failure_count]
|
47
53
|
results[:violations] = results[:violations].map { |violation| violation.to_h }
|
data/bin/cfn_nag_scan
CHANGED
@@ -13,6 +13,7 @@ opts = Trollop::options do
|
|
13
13
|
opt :debug, 'Enable debug output', type: :boolean, required: false, default: false
|
14
14
|
opt :rule_directory, 'Extra rule directory', type: :io, required: false, default: nil
|
15
15
|
opt :profile_path, 'Path to a profile file', type: :io, required: false, default: nil
|
16
|
+
opt :parameter_values_path, 'Path to a JSON file to pull Parameter values from', type: :io, required: false, default: nil
|
16
17
|
opt :allow_suppression, 'Allow using Metadata to suppress violations', type: :boolean, required: false, default: true
|
17
18
|
opt :print_suppression, 'Emit suppressions to stderr', type: :boolean, required: false, default: false
|
18
19
|
opt :isolate_custom_rule_exceptions, 'Isolate custom rule exceptions - just emit the exception without stack trace and keep chugging', type: :boolean, required: false, default: false
|
@@ -35,4 +36,5 @@ cfn_nag = CfnNag.new(profile_definition: profile_definition,
|
|
35
36
|
isolate_custom_rule_exceptions: opts[:isolate_custom_rule_exceptions])
|
36
37
|
|
37
38
|
exit cfn_nag.audit_aggregate_across_files_and_render_results(input_path: opts[:input_path],
|
38
|
-
output_format: opts[:output_format]
|
39
|
+
output_format: opts[:output_format],
|
40
|
+
parameter_values_path: opts[:parameter_values_path])
|
data/lib/cfn-nag/cfn_nag.rb
CHANGED
@@ -27,8 +27,9 @@ class CfnNag
|
|
27
27
|
# Return an aggregate failure count (for exit code usage)
|
28
28
|
#
|
29
29
|
def audit_aggregate_across_files_and_render_results(input_path:,
|
30
|
-
output_format:'txt'
|
31
|
-
|
30
|
+
output_format:'txt',
|
31
|
+
parameter_values_path: nil)
|
32
|
+
aggregate_results = audit_aggregate_across_files input_path: input_path, parameter_values_path: parameter_values_path
|
32
33
|
|
33
34
|
render_results(aggregate_results: aggregate_results,
|
34
35
|
output_format: output_format)
|
@@ -41,13 +42,15 @@ class CfnNag
|
|
41
42
|
##
|
42
43
|
# Given a file or directory path, return aggregate results
|
43
44
|
#
|
44
|
-
def audit_aggregate_across_files(input_path:)
|
45
|
+
def audit_aggregate_across_files(input_path:, parameter_values_path: nil)
|
46
|
+
parameter_values_string = parameter_values_path.nil? ? nil : IO.read(parameter_values_path)
|
45
47
|
templates = TemplateDiscovery.new.discover_templates(input_path)
|
46
48
|
aggregate_results = []
|
47
49
|
templates.each do |template|
|
48
50
|
aggregate_results << {
|
49
51
|
filename: template,
|
50
|
-
file_results: audit(cloudformation_string: IO.read(template)
|
52
|
+
file_results: audit(cloudformation_string: IO.read(template),
|
53
|
+
parameter_values_string: parameter_values_string)
|
51
54
|
}
|
52
55
|
end
|
53
56
|
aggregate_results
|
@@ -56,14 +59,16 @@ class CfnNag
|
|
56
59
|
##
|
57
60
|
# Given cloudformation json/yml, run all the rules against it
|
58
61
|
#
|
62
|
+
# Optionally include JSON with Parameters key to substitute into cfn_model.parameters
|
63
|
+
#
|
59
64
|
# Return a hash with failure count
|
60
65
|
#
|
61
|
-
def audit(cloudformation_string:)
|
66
|
+
def audit(cloudformation_string:, parameter_values_string: nil)
|
62
67
|
stop_processing = false
|
63
68
|
violations = []
|
64
69
|
|
65
70
|
begin
|
66
|
-
cfn_model = CfnParser.new.parse cloudformation_string
|
71
|
+
cfn_model = CfnParser.new.parse cloudformation_string, parameter_values_string
|
67
72
|
rescue Psych::SyntaxError, ParserError => parser_error
|
68
73
|
violations << Violation.new(id: 'FATAL',
|
69
74
|
type: Violation::FAILING_VIOLATION,
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class RDSInstanceMasterUserPasswordRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'RDS instance master user password must be Ref to NoEcho Parameter'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F23'
|
16
|
+
end
|
17
|
+
|
18
|
+
# one word of warning... if somebody applies parameter values via JSON.... this will compare that....
|
19
|
+
# probably shouldn't be doing that though - if it's NoEcho there's a good reason
|
20
|
+
# bother checking synthesized_value? that would be the indicator.....
|
21
|
+
def audit_impl(cfn_model)
|
22
|
+
violating_rdsinstances = cfn_model.resources_by_type('AWS::RDS::DBInstance').select do |instance|
|
23
|
+
if instance.masterUserPassword.nil?
|
24
|
+
false
|
25
|
+
else
|
26
|
+
!references_no_echo_parameter_without_default?(cfn_model, instance.masterUserPassword)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
violating_rdsinstances.map { |instance| instance.logical_resource_id }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def to_boolean(string)
|
36
|
+
if string.to_s.downcase == 'true'
|
37
|
+
true
|
38
|
+
else
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def references_no_echo_parameter_without_default?(cfn_model, master_user_password)
|
44
|
+
# i feel like i've written this mess somewhere before
|
45
|
+
if master_user_password.is_a? Hash
|
46
|
+
if master_user_password.has_key? 'Ref'
|
47
|
+
if cfn_model.parameters.has_key? master_user_password['Ref']
|
48
|
+
parameter = cfn_model.parameters[master_user_password['Ref']]
|
49
|
+
|
50
|
+
return to_boolean(parameter.noEcho) && parameter.default.nil?
|
51
|
+
else
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
else
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
# String or anything weird will fall through here
|
59
|
+
false
|
60
|
+
end
|
61
|
+
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.3.
|
4
|
+
version: 0.3.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Kascic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logging
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.
|
47
|
+
version: 0.1.20
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1.
|
54
|
+
version: 0.1.20
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: jmespath
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/cfn-nag/custom_rules/LambdaPermissionWildcardPrincipalRule.rb
|
119
119
|
- lib/cfn-nag/custom_rules/ManagedPolicyOnUserRule.rb
|
120
120
|
- lib/cfn-nag/custom_rules/PolicyOnUserRule.rb
|
121
|
+
- lib/cfn-nag/custom_rules/RDSInstanceMasterUserPasswordRule.rb
|
121
122
|
- lib/cfn-nag/custom_rules/RDSInstancePubliclyAccessibleRule.rb
|
122
123
|
- lib/cfn-nag/custom_rules/S3BucketPolicyNotActionRule.rb
|
123
124
|
- lib/cfn-nag/custom_rules/S3BucketPolicyNotPrincipalRule.rb
|