cfn-nag 0.7.16 → 0.8.3
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_rules +1 -1
- data/lib/cfn-nag/base_rule.rb +7 -1
- data/lib/cfn-nag/cfn_nag.rb +13 -17
- data/lib/cfn-nag/cfn_nag_config.rb +3 -3
- data/lib/cfn-nag/cfn_nag_executor.rb +5 -5
- data/lib/cfn-nag/cli_options.rb +16 -5
- data/lib/cfn-nag/custom_rules/GameLiftFleetInboundPortRangeRule.rb +2 -0
- data/lib/cfn-nag/custom_rules/base.rb +7 -1
- data/lib/cfn-nag/deny_list_loader.rb +43 -0
- data/lib/cfn-nag/result_view/json_results.rb +1 -1
- data/lib/cfn-nag/result_view/sarif_results.rb +103 -0
- data/lib/cfn-nag/result_view/stdout_results.rb +1 -1
- data/lib/cfn-nag/rule_definition.rb +6 -3
- data/lib/cfn-nag/rule_registry.rb +1 -0
- data/lib/cfn-nag/version.rb +6 -0
- data/lib/cfn-nag/violation.rb +11 -0
- data/lib/cfn-nag/violation_filtering.rb +9 -9
- metadata +7 -5
- data/lib/cfn-nag/blacklist_loader.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e016d95eb663b1bd6a4c7d8d968ea35de3396da8521f03dc33afb69fef6d0adc
|
4
|
+
data.tar.gz: 2e29005bceb483b4b14d6f35b32857775d89b81025d5eb2a9e2032730b36def6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ed62f5cc0fa8b820c226b760ca9ac68fb942245c83511dbab69dece8dac99a389b210f5f832d5d73ca935fdc36ca1037ce953b648267c1035e8767b43a46850
|
7
|
+
data.tar.gz: d54be264eb1f5418df550667b78d6860e76dcd27f6319d01706569e66bff682c2ccf7157df0757887725467c00219ee0519056c40ef227365bee79204312f855
|
data/bin/cfn_nag_rules
CHANGED
data/lib/cfn-nag/base_rule.rb
CHANGED
@@ -20,10 +20,16 @@ class CfnNag
|
|
20
20
|
logical_resource_ids = audit_impl(cfn_model)
|
21
21
|
return if logical_resource_ids.empty?
|
22
22
|
|
23
|
+
violation(logical_resource_ids)
|
24
|
+
end
|
25
|
+
|
26
|
+
def violation(logical_resource_ids, line_numbers = nil)
|
23
27
|
Violation.new(id: rule_id,
|
28
|
+
name: self.class.name,
|
24
29
|
type: rule_type,
|
25
30
|
message: rule_text,
|
26
|
-
logical_resource_ids: logical_resource_ids
|
31
|
+
logical_resource_ids: logical_resource_ids,
|
32
|
+
line_numbers: line_numbers)
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
data/lib/cfn-nag/cfn_nag.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative 'result_view/stdout_results'
|
|
8
8
|
require_relative 'result_view/simple_stdout_results'
|
9
9
|
require_relative 'result_view/colored_stdout_results'
|
10
10
|
require_relative 'result_view/json_results'
|
11
|
+
require_relative 'result_view/sarif_results'
|
11
12
|
require 'cfn-model'
|
12
13
|
|
13
14
|
# Top-level CfnNag class for running profiles
|
@@ -93,13 +94,13 @@ class CfnNag
|
|
93
94
|
@config.custom_rule_loader.rule_definitions
|
94
95
|
)
|
95
96
|
|
96
|
-
violations =
|
97
|
+
violations = filter_violations_by_deny_list_and_profile(violations)
|
97
98
|
violations = mark_line_numbers(violations, cfn_model)
|
98
99
|
rescue RuleRepoException, Psych::SyntaxError, ParserError => fatal_error
|
99
|
-
violations << fatal_violation(fatal_error.to_s)
|
100
|
+
violations << Violation.fatal_violation(fatal_error.to_s)
|
100
101
|
rescue JSON::ParserError => json_parameters_error
|
101
102
|
error = "JSON Parameter values parse error: #{json_parameters_error}"
|
102
|
-
violations << fatal_violation(error)
|
103
|
+
violations << Violation.fatal_violation(error)
|
103
104
|
end
|
104
105
|
|
105
106
|
violations = prune_fatal_violations(violations) if @config.ignore_fatal
|
@@ -112,7 +113,7 @@ class CfnNag
|
|
112
113
|
|
113
114
|
def render_results(aggregate_results:,
|
114
115
|
output_format:)
|
115
|
-
results_renderer(output_format).new.render(aggregate_results)
|
116
|
+
results_renderer(output_format).new.render(aggregate_results, @config.custom_rule_loader.rule_definitions)
|
116
117
|
end
|
117
118
|
|
118
119
|
private
|
@@ -127,21 +128,21 @@ class CfnNag
|
|
127
128
|
violations
|
128
129
|
end
|
129
130
|
|
130
|
-
def
|
131
|
+
def filter_violations_by_deny_list_and_profile(violations)
|
131
132
|
violations = filter_violations_by_profile(
|
132
133
|
profile_definition: @config.profile_definition,
|
133
134
|
rule_definitions: @config.custom_rule_loader.rule_definitions,
|
134
135
|
violations: violations
|
135
136
|
)
|
136
137
|
|
137
|
-
# this must come after -
|
138
|
-
|
139
|
-
|
138
|
+
# this must come after - deny list should always win
|
139
|
+
filter_violations_by_deny_list(
|
140
|
+
deny_list_definition: @config.deny_list_definition,
|
140
141
|
rule_definitions: @config.custom_rule_loader.rule_definitions,
|
141
142
|
violations: violations
|
142
143
|
)
|
143
|
-
rescue StandardError =>
|
144
|
-
violations << fatal_violation(
|
144
|
+
rescue StandardError => deny_list_or_profile_parse_error
|
145
|
+
violations << Violation.fatal_violation(deny_list_or_profile_parse_error.to_s)
|
145
146
|
violations
|
146
147
|
end
|
147
148
|
|
@@ -152,17 +153,12 @@ class CfnNag
|
|
152
153
|
}
|
153
154
|
end
|
154
155
|
|
155
|
-
def fatal_violation(message)
|
156
|
-
Violation.new(id: 'FATAL',
|
157
|
-
type: Violation::FAILING_VIOLATION,
|
158
|
-
message: message)
|
159
|
-
end
|
160
|
-
|
161
156
|
def results_renderer(output_format)
|
162
157
|
registry = {
|
163
158
|
'colortxt' => ColoredStdoutResults,
|
164
159
|
'txt' => SimpleStdoutResults,
|
165
|
-
'json' => JsonResults
|
160
|
+
'json' => JsonResults,
|
161
|
+
'sarif' => SarifResults
|
166
162
|
}
|
167
163
|
registry[output_format]
|
168
164
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class CfnNagConfig
|
4
4
|
# rubocop:disable Metrics/ParameterLists
|
5
5
|
def initialize(profile_definition: nil,
|
6
|
-
|
6
|
+
deny_list_definition: nil,
|
7
7
|
rule_directory: nil,
|
8
8
|
allow_suppression: true,
|
9
9
|
print_suppression: false,
|
@@ -21,7 +21,7 @@ class CfnNagConfig
|
|
21
21
|
rule_repository_definitions: rule_repository_definitions
|
22
22
|
)
|
23
23
|
@profile_definition = profile_definition
|
24
|
-
@
|
24
|
+
@deny_list_definition = deny_list_definition
|
25
25
|
@fail_on_warnings = fail_on_warnings
|
26
26
|
@rule_repositories = rule_repositories
|
27
27
|
@rule_arguments = rule_arguments
|
@@ -29,6 +29,6 @@ class CfnNagConfig
|
|
29
29
|
end
|
30
30
|
# rubocop:enable Metrics/ParameterLists
|
31
31
|
|
32
|
-
attr_reader :rule_arguments, :rule_directory, :custom_rule_loader, :profile_definition, :
|
32
|
+
attr_reader :rule_arguments, :rule_directory, :custom_rule_loader, :profile_definition, :deny_list_definition, \
|
33
33
|
:fail_on_warnings, :rule_repositories, :ignore_fatal
|
34
34
|
end
|
@@ -7,7 +7,7 @@ require 'cfn-nag/cfn_nag_config'
|
|
7
7
|
class CfnNagExecutor
|
8
8
|
def initialize
|
9
9
|
@profile_definition = nil
|
10
|
-
@
|
10
|
+
@deny_list_definition = nil
|
11
11
|
@parameter_values_string = nil
|
12
12
|
@condition_values_string = nil
|
13
13
|
@rule_repository_definitions = []
|
@@ -74,9 +74,9 @@ class CfnNagExecutor
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def validate_options(opts)
|
77
|
-
unless opts[:output_format].nil? || %w[colortxt txt json].include?(opts[:output_format])
|
77
|
+
unless opts[:output_format].nil? || %w[colortxt txt json sarif].include?(opts[:output_format])
|
78
78
|
Optimist.die(:output_format,
|
79
|
-
'Must be colortxt, txt, or
|
79
|
+
'Must be colortxt, txt, json or sarif')
|
80
80
|
end
|
81
81
|
|
82
82
|
opts[:rule_arguments]&.each do |rule_argument|
|
@@ -89,7 +89,7 @@ class CfnNagExecutor
|
|
89
89
|
def execute_io_options(opts)
|
90
90
|
@profile_definition = read_conditionally(opts[:profile_path])
|
91
91
|
|
92
|
-
@
|
92
|
+
@deny_list_definition = read_conditionally(opts[:deny_list_path]) || read_conditionally(opts[:blacklist_path])
|
93
93
|
|
94
94
|
@parameter_values_string = read_conditionally(opts[:parameter_values_path])
|
95
95
|
|
@@ -122,7 +122,7 @@ class CfnNagExecutor
|
|
122
122
|
def cfn_nag_config(opts)
|
123
123
|
CfnNagConfig.new(
|
124
124
|
profile_definition: @profile_definition,
|
125
|
-
|
125
|
+
deny_list_definition: @deny_list_definition,
|
126
126
|
rule_directory: opts[:rule_directory],
|
127
127
|
allow_suppression: opts[:allow_suppression],
|
128
128
|
print_suppression: opts[:print_suppression],
|
data/lib/cfn-nag/cli_options.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'optimist'
|
4
|
+
require_relative 'version'
|
4
5
|
|
5
6
|
# rubocop:disable Metrics/ClassLength
|
6
7
|
class Options
|
@@ -8,7 +9,7 @@ class Options
|
|
8
9
|
'emit the exception without stack trace ' \
|
9
10
|
'and keep chugging'
|
10
11
|
|
11
|
-
@version =
|
12
|
+
@version = CfnNagVersion::VERSION
|
12
13
|
|
13
14
|
def self.for(type)
|
14
15
|
case type
|
@@ -58,8 +59,13 @@ class Options
|
|
58
59
|
type: :string,
|
59
60
|
required: false,
|
60
61
|
default: nil
|
62
|
+
opt :deny_list_path,
|
63
|
+
'Path to a deny list file',
|
64
|
+
type: :string,
|
65
|
+
required: false,
|
66
|
+
default: nil
|
61
67
|
opt :blacklist_path,
|
62
|
-
'Path to a
|
68
|
+
'(Deprecated) Path to a deny list file',
|
63
69
|
type: :string,
|
64
70
|
required: false,
|
65
71
|
default: nil
|
@@ -84,7 +90,7 @@ class Options
|
|
84
90
|
required: false,
|
85
91
|
default: false
|
86
92
|
opt :output_format,
|
87
|
-
'Format of results: [txt, json, colortxt]',
|
93
|
+
'Format of results: [txt, json, colortxt, sarif]',
|
88
94
|
type: :string,
|
89
95
|
default: 'colortxt'
|
90
96
|
opt :rule_repository,
|
@@ -127,7 +133,7 @@ class Options
|
|
127
133
|
type: :string,
|
128
134
|
required: true
|
129
135
|
opt :output_format,
|
130
|
-
'Format of results: [txt, json, colortxt]',
|
136
|
+
'Format of results: [txt, json, colortxt, sarif]',
|
131
137
|
type: :string,
|
132
138
|
default: 'colortxt'
|
133
139
|
opt :debug,
|
@@ -145,8 +151,13 @@ class Options
|
|
145
151
|
type: :string,
|
146
152
|
required: false,
|
147
153
|
default: nil
|
154
|
+
opt :deny_list_path,
|
155
|
+
'Path to a deny list file',
|
156
|
+
type: :string,
|
157
|
+
required: false,
|
158
|
+
default: nil
|
148
159
|
opt :blacklist_path,
|
149
|
-
'Path to a
|
160
|
+
'(Deprecated) Path to a deny list file',
|
150
161
|
type: :string,
|
151
162
|
required: false,
|
152
163
|
default: nil
|
@@ -18,6 +18,8 @@ class GameLiftFleetInboundPortRangeRule < BaseRule
|
|
18
18
|
|
19
19
|
def audit_impl(cfn_model)
|
20
20
|
violating_gamelift_fleets = cfn_model.resources_by_type('AWS::GameLift::Fleet').select do |gamelift_fleet|
|
21
|
+
next false if gamelift_fleet.eC2InboundPermissions.nil?
|
22
|
+
|
21
23
|
violating_permissions = gamelift_fleet.eC2InboundPermissions.select do |permission|
|
22
24
|
# Cast to strings incase template provided mixed types
|
23
25
|
permission['FromPort'].to_s != permission['ToPort'].to_s
|
@@ -19,9 +19,15 @@ class BaseRule
|
|
19
19
|
logical_resource_ids = audit_impl(cfn_model)
|
20
20
|
return if logical_resource_ids.empty?
|
21
21
|
|
22
|
+
violation(logical_resource_ids)
|
23
|
+
end
|
24
|
+
|
25
|
+
def violation(logical_resource_ids, line_numbers = [])
|
22
26
|
Violation.new(id: rule_id,
|
27
|
+
name: self.class.name,
|
23
28
|
type: rule_type,
|
24
29
|
message: rule_text,
|
25
|
-
logical_resource_ids: logical_resource_ids
|
30
|
+
logical_resource_ids: logical_resource_ids,
|
31
|
+
line_numbers: line_numbers)
|
26
32
|
end
|
27
33
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
class DenyListLoader
|
6
|
+
def initialize(rules_registry)
|
7
|
+
@rules_registry = rules_registry
|
8
|
+
end
|
9
|
+
|
10
|
+
def load(deny_list_definition:)
|
11
|
+
raise 'Empty profile' if deny_list_definition.strip == ''
|
12
|
+
|
13
|
+
deny_list_ruleset = RuleIdSet.new
|
14
|
+
|
15
|
+
deny_list_hash = load_deny_list_yaml(deny_list_definition)
|
16
|
+
raise 'Deny list is malformed' unless deny_list_hash.is_a? Hash
|
17
|
+
|
18
|
+
rules_to_suppress = deny_list_hash.fetch('RulesToSuppress', {})
|
19
|
+
raise 'Missing RulesToSuppress key in deny list' if rules_to_suppress.empty?
|
20
|
+
|
21
|
+
rule_ids_to_suppress = rules_to_suppress.map { |rule| rule['id'] }
|
22
|
+
rule_ids_to_suppress.each do |rule_id|
|
23
|
+
check_valid_rule_id rule_id
|
24
|
+
deny_list_ruleset.add_rule rule_id
|
25
|
+
end
|
26
|
+
|
27
|
+
deny_list_ruleset
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def load_deny_list_yaml(deny_list_definition)
|
33
|
+
YAML.safe_load(deny_list_definition)
|
34
|
+
rescue StandardError => yaml_parse_error
|
35
|
+
raise "YAML parse of deny list failed: #{yaml_parse_error}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_valid_rule_id(rule_id)
|
39
|
+
return true unless @rules_registry.by_id(rule_id).nil?
|
40
|
+
|
41
|
+
raise "#{rule_id} is not a legal rule identifier from: #{@rules_registry.ids}"
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class SarifResults
|
7
|
+
def render(results, rule_registry)
|
8
|
+
sarif_results = []
|
9
|
+
results.each do |file|
|
10
|
+
# For each file in the results, review the violations
|
11
|
+
file[:file_results][:violations].each do |violation|
|
12
|
+
# For each violation, generate a sarif result for each logical resource id in the violation
|
13
|
+
violation.logical_resource_ids.each_with_index do |_logical_resource_id, index|
|
14
|
+
sarif_results << sarif_result(file_name: file[:filename], violation: violation, index: index)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
sarif_report = {
|
20
|
+
version: '2.1.0',
|
21
|
+
'$schema': 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
|
22
|
+
runs: [
|
23
|
+
tool: {
|
24
|
+
driver: driver(rule_registry.rules)
|
25
|
+
},
|
26
|
+
results: sarif_results
|
27
|
+
]
|
28
|
+
}
|
29
|
+
|
30
|
+
puts JSON.pretty_generate(sarif_report)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Generates a SARIF driver object, which describes the tool and the rules used
|
34
|
+
def driver(rules)
|
35
|
+
{
|
36
|
+
name: 'cfn_nag',
|
37
|
+
informationUri: 'https://github.com/stelligent/cfn_nag',
|
38
|
+
semanticVersion: CfnNagVersion::VERSION,
|
39
|
+
rules: rules.map do |rule_definition|
|
40
|
+
{
|
41
|
+
id: "CFN_NAG_#{rule_definition.id}",
|
42
|
+
name: rule_definition.name,
|
43
|
+
fullDescription: {
|
44
|
+
text: rule_definition.message
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Given a cfn_nag Violation object, and index, generates a SARIF result object for the finding
|
52
|
+
def sarif_result(file_name:, violation:, index:)
|
53
|
+
{
|
54
|
+
ruleId: "CFN_NAG_#{violation.id}",
|
55
|
+
level: sarif_level(violation.type),
|
56
|
+
message: {
|
57
|
+
text: violation.message
|
58
|
+
},
|
59
|
+
locations: [
|
60
|
+
{
|
61
|
+
physicalLocation: {
|
62
|
+
artifactLocation: {
|
63
|
+
uri: relative_path(file_name),
|
64
|
+
uriBaseId: '%SRCROOT%'
|
65
|
+
},
|
66
|
+
region: {
|
67
|
+
startLine: sarif_line_number(violation.line_numbers[index])
|
68
|
+
}
|
69
|
+
},
|
70
|
+
logicalLocations: [
|
71
|
+
{
|
72
|
+
name: violation.logical_resource_ids[index]
|
73
|
+
}
|
74
|
+
]
|
75
|
+
}
|
76
|
+
]
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
# Line number defaults to 1 unless provided with valid number
|
81
|
+
def sarif_line_number(line_number)
|
82
|
+
line_number.nil? || line_number.to_i < 1 ? 1 : line_number.to_i
|
83
|
+
end
|
84
|
+
|
85
|
+
def sarif_level(violation_type)
|
86
|
+
case violation_type
|
87
|
+
when RuleDefinition::WARNING
|
88
|
+
'warning'
|
89
|
+
else
|
90
|
+
'error'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def relative_path(file_name)
|
95
|
+
file_pathname = Pathname.new(file_name)
|
96
|
+
|
97
|
+
if file_pathname.relative?
|
98
|
+
file_pathname.to_s
|
99
|
+
else
|
100
|
+
file_pathname.relative_path_from(Pathname.pwd).to_s
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -4,27 +4,30 @@ class RuleDefinition
|
|
4
4
|
WARNING = 'WARN'
|
5
5
|
FAILING_VIOLATION = 'FAIL'
|
6
6
|
|
7
|
-
attr_reader :id, :type, :message
|
7
|
+
attr_reader :id, :name, :type, :message
|
8
8
|
|
9
9
|
def initialize(id:,
|
10
|
+
name:,
|
10
11
|
type:,
|
11
12
|
message:)
|
12
13
|
@id = id
|
14
|
+
@name = name
|
13
15
|
@type = type
|
14
16
|
@message = message
|
15
17
|
|
16
|
-
[@id, @type, @message].each do |required|
|
18
|
+
[@id, @type, @name, @message].each do |required|
|
17
19
|
raise 'No parameters to Violation constructor can be nil' if required.nil?
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
23
|
def to_s
|
22
|
-
"#{@id} #{@type} #{@message}"
|
24
|
+
"#{@id} #{name} #{@type} #{@message}"
|
23
25
|
end
|
24
26
|
|
25
27
|
def to_h
|
26
28
|
{
|
27
29
|
id: @id,
|
30
|
+
name: @name,
|
28
31
|
type: @type,
|
29
32
|
message: @message
|
30
33
|
}
|
data/lib/cfn-nag/violation.rb
CHANGED
@@ -6,18 +6,22 @@ require_relative 'rule_definition'
|
|
6
6
|
class Violation < RuleDefinition
|
7
7
|
attr_reader :logical_resource_ids, :line_numbers
|
8
8
|
|
9
|
+
# rubocop:disable Metrics/ParameterLists
|
9
10
|
def initialize(id:,
|
11
|
+
name:,
|
10
12
|
type:,
|
11
13
|
message:,
|
12
14
|
logical_resource_ids: [],
|
13
15
|
line_numbers: [])
|
14
16
|
super id: id,
|
17
|
+
name: name,
|
15
18
|
type: type,
|
16
19
|
message: message
|
17
20
|
|
18
21
|
@logical_resource_ids = logical_resource_ids
|
19
22
|
@line_numbers = line_numbers
|
20
23
|
end
|
24
|
+
# rubocop:enable Metrics/ParameterLists
|
21
25
|
|
22
26
|
def to_s
|
23
27
|
"#{super} #{@logical_resource_ids}"
|
@@ -57,6 +61,13 @@ class Violation < RuleDefinition
|
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
64
|
+
def fatal_violation(message)
|
65
|
+
Violation.new(id: 'FATAL',
|
66
|
+
name: 'system',
|
67
|
+
type: Violation::FAILING_VIOLATION,
|
68
|
+
message: message)
|
69
|
+
end
|
70
|
+
|
60
71
|
private
|
61
72
|
|
62
73
|
def empty?(array)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'cfn-nag/profile_loader'
|
4
|
-
require 'cfn-nag/
|
4
|
+
require 'cfn-nag/deny_list_loader'
|
5
5
|
|
6
6
|
module ViolationFiltering
|
7
7
|
def filter_violations_by_profile(profile_definition:, rule_definitions:, violations:)
|
@@ -20,19 +20,19 @@ module ViolationFiltering
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
unless
|
23
|
+
def filter_violations_by_deny_list(deny_list_definition:, rule_definitions:, violations:)
|
24
|
+
deny_list = nil
|
25
|
+
unless deny_list_definition.nil?
|
26
26
|
begin
|
27
|
-
|
28
|
-
|
29
|
-
rescue StandardError =>
|
30
|
-
raise "
|
27
|
+
deny_list = DenyListLoader.new(rule_definitions)
|
28
|
+
.load(deny_list_definition: deny_list_definition)
|
29
|
+
rescue StandardError => deny_list_load_error
|
30
|
+
raise "Deny list loading error: #{deny_list_load_error}"
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
violations.reject do |violation|
|
35
|
-
!
|
35
|
+
!deny_list.nil? && deny_list.contains_rule?(violation.id)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
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.
|
4
|
+
version: 0.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Kascic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.6.
|
75
|
+
version: 0.6.5
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.6.
|
82
|
+
version: 0.6.5
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: logging
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -180,7 +180,6 @@ files:
|
|
180
180
|
- bin/spcm_scan
|
181
181
|
- lib/cfn-nag.rb
|
182
182
|
- lib/cfn-nag/base_rule.rb
|
183
|
-
- lib/cfn-nag/blacklist_loader.rb
|
184
183
|
- lib/cfn-nag/cfn_nag.rb
|
185
184
|
- lib/cfn-nag/cfn_nag_config.rb
|
186
185
|
- lib/cfn-nag/cfn_nag_executor.rb
|
@@ -359,6 +358,7 @@ files:
|
|
359
358
|
- lib/cfn-nag/custom_rules/password_base_rule.rb
|
360
359
|
- lib/cfn-nag/custom_rules/resource_base_rule.rb
|
361
360
|
- lib/cfn-nag/custom_rules/sub_property_with_list_password_base_rule.rb
|
361
|
+
- lib/cfn-nag/deny_list_loader.rb
|
362
362
|
- lib/cfn-nag/iam_complexity_metric/condition_metric.rb
|
363
363
|
- lib/cfn-nag/iam_complexity_metric/html_results_renderer.rb
|
364
364
|
- lib/cfn-nag/iam_complexity_metric/policy_document_metric.rb
|
@@ -371,6 +371,7 @@ files:
|
|
371
371
|
- lib/cfn-nag/result_view/colored_stdout_results.rb
|
372
372
|
- lib/cfn-nag/result_view/json_results.rb
|
373
373
|
- lib/cfn-nag/result_view/rules_view.rb
|
374
|
+
- lib/cfn-nag/result_view/sarif_results.rb
|
374
375
|
- lib/cfn-nag/result_view/simple_stdout_results.rb
|
375
376
|
- lib/cfn-nag/result_view/stdout_results.rb
|
376
377
|
- lib/cfn-nag/rule_definition.rb
|
@@ -388,6 +389,7 @@ files:
|
|
388
389
|
- lib/cfn-nag/util/enforce_string_or_dynamic_reference.rb
|
389
390
|
- lib/cfn-nag/util/truthy.rb
|
390
391
|
- lib/cfn-nag/util/wildcard_patterns.rb
|
392
|
+
- lib/cfn-nag/version.rb
|
391
393
|
- lib/cfn-nag/violation.rb
|
392
394
|
- lib/cfn-nag/violation_filtering.rb
|
393
395
|
homepage: https://github.com/stelligent/cfn_nag
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
class BlackListLoader
|
6
|
-
def initialize(rules_registry)
|
7
|
-
@rules_registry = rules_registry
|
8
|
-
end
|
9
|
-
|
10
|
-
def load(blacklist_definition:)
|
11
|
-
raise 'Empty profile' if blacklist_definition.strip == ''
|
12
|
-
|
13
|
-
blacklist_ruleset = RuleIdSet.new
|
14
|
-
|
15
|
-
blacklist_hash = load_blacklist_yaml(blacklist_definition)
|
16
|
-
raise 'Blacklist is malformed' unless blacklist_hash.is_a? Hash
|
17
|
-
|
18
|
-
rules_to_suppress = blacklist_hash.fetch('RulesToSuppress', {})
|
19
|
-
raise 'Missing RulesToSuppress key in black list' if rules_to_suppress.empty?
|
20
|
-
|
21
|
-
rule_ids_to_suppress = rules_to_suppress.map { |rule| rule['id'] }
|
22
|
-
rule_ids_to_suppress.each do |rule_id|
|
23
|
-
check_valid_rule_id rule_id
|
24
|
-
blacklist_ruleset.add_rule rule_id
|
25
|
-
end
|
26
|
-
|
27
|
-
blacklist_ruleset
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def load_blacklist_yaml(blacklist_definition)
|
33
|
-
YAML.safe_load(blacklist_definition)
|
34
|
-
rescue StandardError => yaml_parse_error
|
35
|
-
raise "YAML parse of blacklist failed: #{yaml_parse_error}"
|
36
|
-
end
|
37
|
-
|
38
|
-
def check_valid_rule_id(rule_id)
|
39
|
-
return true unless @rules_registry.by_id(rule_id).nil?
|
40
|
-
|
41
|
-
raise "#{rule_id} is not a legal rule identifier from: #{@rules_registry.ids}"
|
42
|
-
end
|
43
|
-
end
|