cfn-nag 0.8.1 → 0.8.2
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 +7 -11
- data/lib/cfn-nag/cfn_nag_executor.rb +2 -2
- data/lib/cfn-nag/cli_options.rb +4 -3
- data/lib/cfn-nag/custom_rules/base.rb +7 -1
- 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
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0dd505f40c9fd504634b10223a8742375032a6fd225febe29460692dae4b5d2
|
4
|
+
data.tar.gz: 6e535f22dde6837b2384a94a95f1a115ca0ec89c30450793ae490b092d034622
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d75d174639ebf1056c2add11c6acca90f273d545dd825703a710b1e15c0483c90dee85a161d4c7d4b6261371ac7d3ec1b6df3f80facbec2f59cb0adf683b060
|
7
|
+
data.tar.gz: cd3d89960bf8662a99e2a6e180c46ad587413872e30085e77b7db625a46a1e9d0d8d7a742debe3cdd7b8f8f51bc07190696eb9271479cf0ce13ee8b707320e05
|
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
|
@@ -96,10 +97,10 @@ class CfnNag
|
|
96
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
|
@@ -141,7 +142,7 @@ class CfnNag
|
|
141
142
|
violations: violations
|
142
143
|
)
|
143
144
|
rescue StandardError => deny_list_or_profile_parse_error
|
144
|
-
violations << fatal_violation(deny_list_or_profile_parse_error.to_s)
|
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
|
@@ -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|
|
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
|
@@ -89,7 +90,7 @@ class Options
|
|
89
90
|
required: false,
|
90
91
|
default: false
|
91
92
|
opt :output_format,
|
92
|
-
'Format of results: [txt, json, colortxt]',
|
93
|
+
'Format of results: [txt, json, colortxt, sarif]',
|
93
94
|
type: :string,
|
94
95
|
default: 'colortxt'
|
95
96
|
opt :rule_repository,
|
@@ -132,7 +133,7 @@ class Options
|
|
132
133
|
type: :string,
|
133
134
|
required: true
|
134
135
|
opt :output_format,
|
135
|
-
'Format of results: [txt, json, colortxt]',
|
136
|
+
'Format of results: [txt, json, colortxt, sarif]',
|
136
137
|
type: :string,
|
137
138
|
default: 'colortxt'
|
138
139
|
opt :debug,
|
@@ -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,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)
|
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.8.
|
4
|
+
version: 0.8.2
|
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-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -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
|