cfn-nag 0.3.36 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3bbfbd7db2b9426d31da6b33f1c57ef3206fd577
4
- data.tar.gz: 7467677da594cc69cb29499937341f174e1a96f9
3
+ metadata.gz: 679f328149572244f9d7716508fb21ec61d51b82
4
+ data.tar.gz: 5fe1047c08e2b48a6e7370ffb65ac7aa877a0503
5
5
  SHA512:
6
- metadata.gz: 3f78c54ce0cd89a94668916325489a8e1f5438323cccba1d914163cc821550c3dca33f2fb15c73b74181f68d3710bba329c20d7f8aee192e58da7087fde25b6a
7
- data.tar.gz: f9e9162205017eaedd6699781fd50d135082b42f03af1ea3682100c29378a9e27e90115a6efbcc67091f7a181e5dfec1697378caacb1425602fcf71d09c0326d
6
+ metadata.gz: 5cf850041ccbb24904d252e21153c84a843bdfd05eec85fd87f2752ac1707b731b06ba81ffa1b5b81fea4bf77c71c209d4898f1ef6fb4d4b192dc92cd29a0ae6
7
+ data.tar.gz: 2d2ed30c52bdd934748b423982daba740ed52b427ee186d9c95ab7cda8996be33ff2d1410e81f8e2bc8cdf786dc630bff9bb43c572d7e49e2a089cf8147f0a59
@@ -14,10 +14,11 @@ class CfnNag
14
14
  print_suppression: false,
15
15
  isolate_custom_rule_exceptions: false)
16
16
  @rule_directory = rule_directory
17
- @custom_rule_loader = CustomRuleLoader.new(rule_directory: rule_directory,
18
- allow_suppression: allow_suppression,
19
- print_suppression: print_suppression,
20
- isolate_custom_rule_exceptions: isolate_custom_rule_exceptions)
17
+ @custom_rule_loader = CustomRuleLoader.new(
18
+ rule_directory: rule_directory, allow_suppression: allow_suppression,
19
+ print_suppression: print_suppression,
20
+ isolate_custom_rule_exceptions: isolate_custom_rule_exceptions
21
+ )
21
22
  @profile_definition = profile_definition
22
23
  end
23
24
 
@@ -26,10 +27,12 @@ class CfnNag
26
27
  #
27
28
  # Return an aggregate failure count (for exit code usage)
28
29
  #
29
- def audit_aggregate_across_files_and_render_results(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
30
+ def audit_aggregate_across_files_and_render_results(
31
+ input_path:, output_format: 'txt', parameter_values_path: nil
32
+ )
33
+ aggregate_results = \
34
+ audit_aggregate_across_files input_path: input_path,
35
+ parameter_values_path: parameter_values_path
33
36
 
34
37
  render_results(aggregate_results: aggregate_results,
35
38
  output_format: output_format)
@@ -43,7 +46,8 @@ class CfnNag
43
46
  # Given a file or directory path, return aggregate results
44
47
  #
45
48
  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)
49
+ parameter_values_string = \
50
+ parameter_values_path.nil? ? nil : IO.read(parameter_values_path)
47
51
  templates = TemplateDiscovery.new.discover_templates(input_path)
48
52
  aggregate_results = []
49
53
  templates.each do |template|
@@ -59,7 +63,8 @@ class CfnNag
59
63
  ##
60
64
  # Given cloudformation json/yml, run all the rules against it
61
65
  #
62
- # Optionally include JSON with Parameters key to substitute into cfn_model.parameters
66
+ # Optionally include JSON with Parameters key to substitute into
67
+ # cfn_model.parameters
63
68
  #
64
69
  # Return a hash with failure count
65
70
  #
@@ -68,7 +73,8 @@ class CfnNag
68
73
  violations = []
69
74
 
70
75
  begin
71
- cfn_model = CfnParser.new.parse cloudformation_string, parameter_values_string
76
+ cfn_model = CfnParser.new.parse cloudformation_string,
77
+ parameter_values_string
72
78
  rescue Psych::SyntaxError, ParserError => parser_error
73
79
  violations << Violation.new(id: 'FATAL',
74
80
  type: Violation::FAILING_VIOLATION,
@@ -76,9 +82,10 @@ class CfnNag
76
82
  stop_processing = true
77
83
  end
78
84
 
79
- violations += @custom_rule_loader.execute_custom_rules(cfn_model) unless stop_processing == true
80
-
81
- violations = filter_violations_by_profile violations unless stop_processing == true
85
+ unless stop_processing == true
86
+ violations += @custom_rule_loader.execute_custom_rules(cfn_model)
87
+ violations = filter_violations_by_profile violations
88
+ end
82
89
 
83
90
  {
84
91
  failure_count: Violation.count_failures(violations),
@@ -102,7 +109,8 @@ class CfnNag
102
109
  def filter_violations_by_profile(violations)
103
110
  profile = nil
104
111
  unless @profile_definition.nil?
105
- profile = ProfileLoader.new(@custom_rule_loader.rule_definitions).load(profile_definition: @profile_definition)
112
+ profile = ProfileLoader.new(@custom_rule_loader.rule_definitions)
113
+ .load(profile_definition: @profile_definition)
106
114
  end
107
115
 
108
116
  violations.reject do |violation|
@@ -49,9 +49,9 @@ class CustomRuleLoader
49
49
 
50
50
  discover_rule_classes(@rule_directory).each do |rule_class|
51
51
  begin
52
- filtered_cfn_model = cfn_model_with_suppressed_resources_removed cfn_model: cfn_model,
53
- rule_id: rule_class.new.rule_id,
54
- allow_suppression: @allow_suppression
52
+ filtered_cfn_model = cfn_model_with_suppressed_resources_removed \
53
+ cfn_model: cfn_model, rule_id: rule_class.new.rule_id,
54
+ allow_suppression: @allow_suppression
55
55
  audit_result = rule_class.new.audit(filtered_cfn_model)
56
56
  violations << audit_result unless audit_result.nil?
57
57
  rescue Exception => exception
@@ -76,7 +76,10 @@ class CustomRuleLoader
76
76
  private
77
77
 
78
78
  def rules_to_suppress(resource)
79
- if resource.metadata && resource.metadata['cfn_nag'] && resource.metadata['cfn_nag']['rules_to_suppress']
79
+ if resource.metadata &&
80
+ resource.metadata['cfn_nag'] &&
81
+ resource.metadata['cfn_nag']['rules_to_suppress']
82
+
80
83
  resource.metadata['cfn_nag']['rules_to_suppress']
81
84
  else
82
85
  nil
@@ -102,7 +105,8 @@ class CustomRuleLoader
102
105
  logical_resource_id = mangled_metadata.first
103
106
  mangled_rules = mangled_metadata[1]
104
107
 
105
- STDERR.puts "#{logical_resource_id} has missing cfn_nag suppression rule id: #{mangled_rules}"
108
+ STDERR.puts "#{logical_resource_id} has missing cfn_nag " \
109
+ "suppression rule id: #{mangled_rules}"
106
110
  end
107
111
  end
108
112
 
@@ -112,7 +116,8 @@ class CustomRuleLoader
112
116
  rule_to_suppress['id'] == rule_id
113
117
  end
114
118
  if found_suppression_rule && @print_suppression
115
- STDERR.puts "Suppressing #{rule_id} on #{logical_resource_id} for reason: #{found_suppression_rule['reason']}"
119
+ STDERR.puts "Suppressing #{rule_id} on #{logical_resource_id} " \
120
+ "for reason: #{found_suppression_rule['reason']}"
116
121
  end
117
122
  !found_suppression_rule.nil?
118
123
  end
@@ -136,9 +141,8 @@ class CustomRuleLoader
136
141
  end
137
142
 
138
143
  def validate_extra_rule_directory(rule_directory)
139
- unless rule_directory.nil?
140
- raise "Not a real directory #{rule_directory}" unless File.directory? rule_directory
141
- end
144
+ return true if rule_directory.nil? || File.directory?(rule_directory)
145
+ raise "Not a real directory #{rule_directory}"
142
146
  end
143
147
 
144
148
  def discover_rule_filenames(rule_directory)
@@ -172,7 +176,9 @@ class CustomRuleLoader
172
176
  unless rule_directory.nil?
173
177
  rule_filenames += Dir[File.join(rule_directory, '*jmespath.rb')].sort
174
178
  end
175
- rule_filenames += Dir[File.join(__dir__, 'custom_rules', '*jmespath.rb')].sort
179
+ rule_filenames += Dir[File.join(__dir__,
180
+ 'custom_rules',
181
+ '*jmespath.rb')].sort
176
182
  Logging.logger['log'].debug "jmespath_filenames: #{rule_filenames}"
177
183
  rule_filenames
178
184
  end
@@ -3,7 +3,8 @@ require_relative 'base'
3
3
 
4
4
  class CloudFormationAuthenticationRule < BaseRule
5
5
  def rule_text
6
- 'Specifying credentials in the template itself is probably not the safest thing'
6
+ 'Specifying credentials in the template itself ' \
7
+ 'is probably not the safest thing'
7
8
  end
8
9
 
9
10
  def rule_type
@@ -15,9 +15,11 @@ class CloudFrontDistributionAccessLoggingRule < BaseRule
15
15
  end
16
16
 
17
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
18
+ violating_distributions = \
19
+ cfn_model.resources_by_type('AWS::CloudFront::Distribution')
20
+ .select do |distribution|
21
+ distribution.distributionConfig['Logging'].nil?
22
+ end
21
23
 
22
24
  violating_distributions.map(&:logical_resource_id)
23
25
  end
@@ -15,9 +15,10 @@ class EbsVolumeHasSseRule < BaseRule
15
15
  end
16
16
 
17
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.to_s.downcase == 'false'
20
- end
18
+ violating_volumes = \
19
+ cfn_model.resources_by_type('AWS::EC2::Volume').select do |volume|
20
+ volume.encrypted.nil? || volume.encrypted.to_s.downcase == 'false'
21
+ end
21
22
 
22
23
  violating_volumes.map(&:logical_resource_id)
23
24
  end
@@ -15,9 +15,12 @@ class ElasticLoadBalancerAccessLoggingRule < BaseRule
15
15
  end
16
16
 
17
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
18
+ violating_elbs = \
19
+ cfn_model.resources_by_type('AWS::ElasticLoadBalancing::LoadBalancer')
20
+ .select do |elb|
21
+ elb.accessLoggingPolicy.nil? ||
22
+ elb.accessLoggingPolicy['Enabled'] != true
23
+ end
21
24
 
22
25
  violating_elbs.map(&:logical_resource_id)
23
26
  end
@@ -15,9 +15,11 @@ class IamManagedPolicyNotActionRule < BaseRule
15
15
  end
16
16
 
17
17
  def audit_impl(cfn_model)
18
- violating_policies = cfn_model.resources_by_type('AWS::IAM::ManagedPolicy').select do |policy|
19
- !policy.policy_document.allows_not_action.empty?
20
- end
18
+ violating_policies = \
19
+ cfn_model.resources_by_type('AWS::IAM::ManagedPolicy')
20
+ .select do |policy|
21
+ !policy.policy_document.allows_not_action.empty?
22
+ end
21
23
 
22
24
  violating_policies.map(&:logical_resource_id)
23
25
  end
@@ -15,9 +15,11 @@ class IamManagedPolicyNotResourceRule < BaseRule
15
15
  end
16
16
 
17
17
  def audit_impl(cfn_model)
18
- violating_policies = cfn_model.resources_by_type('AWS::IAM::ManagedPolicy').select do |policy|
19
- !policy.policy_document.allows_not_resource.empty?
20
- end
18
+ violating_policies = \
19
+ cfn_model.resources_by_type('AWS::IAM::ManagedPolicy')
20
+ .select do |policy|
21
+ !policy.policy_document.allows_not_resource.empty?
22
+ end
21
23
 
22
24
  violating_policies.map(&:logical_resource_id)
23
25
  end
@@ -15,9 +15,11 @@ class IamManagedPolicyWildcardActionRule < BaseRule
15
15
  end
16
16
 
17
17
  def audit_impl(cfn_model)
18
- violating_policies = cfn_model.resources_by_type('AWS::IAM::ManagedPolicy').select do |policy|
19
- !policy.policy_document.wildcard_allowed_actions.empty?
20
- end
18
+ violating_policies = \
19
+ cfn_model.resources_by_type('AWS::IAM::ManagedPolicy')
20
+ .select do |policy|
21
+ !policy.policy_document.wildcard_allowed_actions.empty?
22
+ end
21
23
 
22
24
  violating_policies.map(&:logical_resource_id)
23
25
  end
@@ -15,9 +15,11 @@ class IamManagedPolicyWildcardResourceRule < BaseRule
15
15
  end
16
16
 
17
17
  def audit_impl(cfn_model)
18
- violating_policies = cfn_model.resources_by_type('AWS::IAM::ManagedPolicy').select do |policy|
19
- !policy.policy_document.wildcard_allowed_resources.empty?
20
- end
18
+ violating_policies = \
19
+ cfn_model.resources_by_type('AWS::IAM::ManagedPolicy')
20
+ .select do |policy|
21
+ !policy.policy_document.wildcard_allowed_resources.empty?
22
+ end
21
23
 
22
24
  violating_policies.map(&:logical_resource_id)
23
25
  end
@@ -15,9 +15,11 @@ class IamPolicyNotActionRule < BaseRule
15
15
  end
16
16
 
17
17
  def audit_impl(cfn_model)
18
- violating_policies = cfn_model.resources_by_type('AWS::IAM::Policy').select do |policy|
19
- !policy.policy_document.allows_not_action.empty?
20
- end
18
+ violating_policies = \
19
+ cfn_model.resources_by_type('AWS::IAM::Policy')
20
+ .select do |policy|
21
+ !policy.policy_document.allows_not_action.empty?
22
+ end
21
23
 
22
24
  violating_policies.map(&:logical_resource_id)
23
25
  end
@@ -15,9 +15,11 @@ class IamPolicyNotResourceRule < BaseRule
15
15
  end
16
16
 
17
17
  def audit_impl(cfn_model)
18
- violating_policies = cfn_model.resources_by_type('AWS::IAM::Policy').select do |policy|
19
- !policy.policy_document.allows_not_resource.empty?
20
- end
18
+ violating_policies = \
19
+ cfn_model.resources_by_type('AWS::IAM::Policy')
20
+ .select do |policy|
21
+ !policy.policy_document.allows_not_resource.empty?
22
+ end
21
23
 
22
24
  violating_policies.map(&:logical_resource_id)
23
25
  end
@@ -6,7 +6,8 @@ class SecurityGroupIngressOpenToWorldRule < BaseRule
6
6
  include IpAddr
7
7
 
8
8
  def rule_text
9
- 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB'
9
+ 'Security Groups found with cidr open to world on ingress. ' \
10
+ 'This should never be true on instance. Permissible on ELB'
10
11
  end
11
12
 
12
13
  def rule_type
@@ -18,7 +19,8 @@ class SecurityGroupIngressOpenToWorldRule < BaseRule
18
19
  end
19
20
 
20
21
  ##
21
- # This will behave slightly different than the legacy jq based rule which was targeted against inline ingress only
22
+ # This will behave slightly different than the legacy jq based rule
23
+ # which was targeted against inline ingress only
22
24
  def audit_impl(cfn_model)
23
25
  logical_resource_ids = []
24
26
  cfn_model.security_groups.each do |security_group|
@@ -1,4 +1,7 @@
1
1
 
2
2
  # failure(id: 'F8888',
3
- # jmespath: "Resources.*|[?Type == 'AWS::EC2::Volume' && (Properties.Encrypted == `false` || Properties.Encrypted == `null`)].id",
3
+ # jmespath:
4
+ # "Resources.*|[?Type == 'AWS::EC2::Volume' && " \
5
+ # "(Properties.Encrypted == `false` || " \
6
+ # "Properties.Encrypted == `null`)].id",
4
7
  # message: 'Found a naughty EBS volume')
@@ -2,7 +2,8 @@ require 'netaddr'
2
2
 
3
3
  module IpAddr
4
4
  def ip4_open?(ingress)
5
- # only care about literals. if a Hash/Ref not going to chase it down given likely a Parameter with external val
5
+ # only care about literals. if a Hash/Ref not going to chase it down
6
+ # given likely a Parameter with external val
6
7
  ingress.cidrIp.is_a?(String) && ingress.cidrIp == '0.0.0.0/0'
7
8
  end
8
9
 
@@ -10,8 +11,10 @@ module IpAddr
10
11
  normalized_cidr_ip6 = normalize_cidr_ip6(ingress)
11
12
  return false if normalized_cidr_ip6.nil?
12
13
 
13
- # only care about literals. if a Hash/Ref not going to chase it down given likely a Parameter with external val
14
- (NetAddr::CIDRv6.create(normalized_cidr_ip6) == NetAddr::CIDRv6.create('::/0'))
14
+ # only care about literals. if a Hash/Ref not going to chase it down
15
+ # given likely a Parameter with external val
16
+ (NetAddr::CIDRv6.create(normalized_cidr_ip6) ==
17
+ NetAddr::CIDRv6.create('::/0'))
15
18
  end
16
19
 
17
20
  def ip4_cidr_range?(ingress)
@@ -22,14 +25,17 @@ module IpAddr
22
25
  normalized_cidr_ip6 = normalize_cidr_ip6(ingress)
23
26
  return false if normalized_cidr_ip6.nil?
24
27
 
25
- # only care about literals. if a Hash/Ref not going to chase it down given likely a Parameter with external val
28
+ # only care about literals. if a Hash/Ref not going to chase it down
29
+ # given likely a Parameter with external val
26
30
  !NetAddr::CIDRv6.create(normalized_cidr_ip6).to_s.end_with?('/128')
27
31
  end
28
32
 
29
33
  ##
30
34
  # If it's a string, just pass through
31
- # If it's a symbol - probably because the YAML.load call treats an unquoted ::/0 as a the symbol :':/0'
32
- # Otherwise it's probably a Ref or whatever and we aren't going to do anything with it
35
+ # If it's a symbol - probably because the YAML.load call treats an unquoted
36
+ # ::/0 as a the symbol :':/0'
37
+ # Otherwise it's probably a Ref or whatever and we aren't going to do
38
+ # anything with it
33
39
  #
34
40
  def normalize_cidr_ip6(ingress)
35
41
  if ingress.cidrIpv6.is_a?(Symbol)
@@ -18,7 +18,8 @@ class ProfileLoader
18
18
  if !rule_line_match.nil?
19
19
  rule_id = rule_line_match.captures.first
20
20
  if @rules_registry.by_id(rule_id) == nil
21
- raise "#{rule_id} is not a legal rule identifier from: #{@rules_registry.rules.map { |rule| rule.id }}"
21
+ raise "#{rule_id} is not a legal rule identifier from: " \
22
+ "#{@rules_registry.rules.map { |rule| rule.id }}"
22
23
  else
23
24
  new_profile.add_rule rule_id
24
25
  end
@@ -3,7 +3,8 @@ require 'json'
3
3
  class JsonResults
4
4
  def render(results)
5
5
  hashified_results = results.each do |result|
6
- result[:file_results][:violations] = result[:file_results][:violations].map(&:to_h)
6
+ result[:file_results][:violations] = \
7
+ result[:file_results][:violations].map(&:to_h)
7
8
  end
8
9
 
9
10
  puts JSON.pretty_generate(hashified_results)
@@ -15,7 +15,8 @@ class CfnNagRuleDumper
15
15
 
16
16
  profile = nil
17
17
  unless @profile_definition.nil?
18
- profile = ProfileLoader.new(rule_registry).load(profile_definition: @profile_definition)
18
+ profile = ProfileLoader.new(rule_registry)
19
+ .load(profile_definition: @profile_definition)
19
20
  end
20
21
 
21
22
  RulesView.new.emit(rule_registry, profile)
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.36
4
+ version: 0.3.37
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-27 00:00:00.000000000 Z
11
+ date: 2018-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec