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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 268084f6ab092c47a31679530e79f8f45edcf18f
4
- data.tar.gz: 38d0c66ec02ff5c990a5dddeda13ab7a87af9bb0
3
+ metadata.gz: 6dbc83f4e332ec0dc78d062c7cb61de979a9ab0a
4
+ data.tar.gz: a7b949b88a2d4d89ae1fb89de204cfb04ba56a27
5
5
  SHA512:
6
- metadata.gz: f24b0b3a8bd1b8b0f6116ddf5cdb1764ec5655f81111ff76858bd0fe2512e32f68221ab651f6e4082d0daf15940f297bac8f47f1f615cdd6719175d55e8543e5
7
- data.tar.gz: 71716b9f5be85c99a8c24e50006ccc115e278da43c246709258ce646bfc06eb616ae64e17e9a6d59aa8ff7aed322b782501084e73dce6773881bb597a1a0cc8f
6
+ metadata.gz: 264209cc00d7fac44802652981ed5815643c67a46da322a7617a45a03be6dc079e44ba87515bf95f1544abf07eb4c366b4755ffeb2859e519d643caeee231065
7
+ data.tar.gz: b33e31569da12196a3be074b83c83744e0a0527ed050580532ca83fb6f74882ed0ad240f7630965c3aeace8b52a4cb1d378d9ae385566395d44d67a05d581dde
@@ -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 }
@@ -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])
@@ -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
- aggregate_results = audit_aggregate_across_files input_path: input_path
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.22
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-15 00:00:00.000000000 Z
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.19
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.19
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