cfn-nag 0.3.36 → 0.3.37

Sign up to get free protection for your applications and to get access to all the features.
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