cfn-nag 0.0.19 → 0.0.20
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 +1 -1
- data/lib/cfn_nag.rb +16 -11
- data/lib/json_rules/basic_rules.rb +2 -2
- data/lib/rule.rb +14 -11
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcadc8f647c513a6b89a00d1f65dce2a58bfd67c
|
4
|
+
data.tar.gz: c2b937a48509a75a7794dd57bdab96515786b18b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69d402fae0584179a7c6ad6fee475fc0409f3ca817d030eae7c8be552a197290cb6e998db555e7d8fc446a443ec38cb57a843bc8ebe8f75de0633e80d246f6af
|
7
|
+
data.tar.gz: 42a9d0dc9efcfc155d2fac8b5b16f1ccbe41f732372495548f344038a9839a06263a2c9e5576946770cc5611d1e2533d5be8c314478f3b1e46cf7800f8746f5e
|
data/bin/cfn_nag
CHANGED
@@ -4,7 +4,7 @@ require 'cfn_nag'
|
|
4
4
|
require 'logging'
|
5
5
|
|
6
6
|
opts = Trollop::options do
|
7
|
-
opt :input_json_path, '
|
7
|
+
opt :input_json_path, 'CloudFormation template to nag on or directory of templates - all *.json and *.template recursively', type: :io, required: true
|
8
8
|
opt :output_format, 'Format of results: [txt, json]', type: :string, default: 'txt'
|
9
9
|
opt :debug, 'Enable debug output', type: :boolean, required: false, default: false
|
10
10
|
end
|
data/lib/cfn_nag.rb
CHANGED
@@ -92,19 +92,23 @@ class CfnNag
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def audit_file(input_json_path:)
|
95
|
+
audit_template(input_json: IO.read(input_json_path))
|
96
|
+
end
|
97
|
+
|
98
|
+
def audit_template(input_json:)
|
95
99
|
@stop_processing = false
|
96
100
|
@violations = []
|
97
101
|
|
98
|
-
unless legal_json?(
|
102
|
+
unless legal_json?(input_json)
|
99
103
|
@violations << Violation.new(type: Violation::FAILING_VIOLATION,
|
100
104
|
message: 'not even legit JSON',
|
101
|
-
violating_code:
|
105
|
+
violating_code: input_json)
|
102
106
|
@stop_processing = true
|
103
107
|
end
|
104
108
|
|
105
|
-
generic_json_rules
|
109
|
+
generic_json_rules input_json unless @stop_processing == true
|
106
110
|
|
107
|
-
custom_rules
|
111
|
+
custom_rules input_json unless @stop_processing == true
|
108
112
|
|
109
113
|
{
|
110
114
|
failure_count: Rule::count_failures(@violations),
|
@@ -141,9 +145,9 @@ class CfnNag
|
|
141
145
|
registry[output_format]
|
142
146
|
end
|
143
147
|
|
144
|
-
def legal_json?(
|
148
|
+
def legal_json?(input_json)
|
145
149
|
begin
|
146
|
-
JSON.parse(
|
150
|
+
JSON.parse(input_json)
|
147
151
|
true
|
148
152
|
rescue JSON::ParserError
|
149
153
|
return false
|
@@ -151,22 +155,23 @@ class CfnNag
|
|
151
155
|
end
|
152
156
|
|
153
157
|
def command?(command)
|
154
|
-
system("
|
158
|
+
not system("#{command} > /dev/null 2>&1").nil?
|
155
159
|
end
|
156
160
|
|
157
|
-
def generic_json_rules(
|
161
|
+
def generic_json_rules(input_json)
|
158
162
|
unless command? 'jq'
|
159
163
|
fail 'jq executable must be available in PATH'
|
160
164
|
end
|
161
165
|
|
166
|
+
puts "GENERIC JSON RULES FROM: #{__dir__}"
|
162
167
|
Dir[File.join(__dir__, 'json_rules', '*.rb')].sort.each do |rule_file|
|
163
|
-
@
|
168
|
+
@input_json = input_json
|
164
169
|
eval IO.read(rule_file)
|
165
170
|
end
|
166
171
|
end
|
167
172
|
|
168
|
-
def custom_rules(
|
169
|
-
cfn_model = CfnModel.new.parse(
|
173
|
+
def custom_rules(input_json)
|
174
|
+
cfn_model = CfnModel.new.parse(input_json)
|
170
175
|
custom_rule_registry.each do |rule_class|
|
171
176
|
audit_result = rule_class.new.audit(cfn_model)
|
172
177
|
@violations << audit_result unless audit_result.nil?
|
@@ -1,5 +1,5 @@
|
|
1
1
|
raw_fatal_assertion jq: '.Resources|length > 0',
|
2
|
-
message: 'A
|
2
|
+
message: 'A CloudFormation template must have at least 1 resource'
|
3
3
|
|
4
4
|
|
5
5
|
%w(
|
@@ -42,4 +42,4 @@ raw_fatal_violation jq: missing_reference_jq,
|
|
42
42
|
).each do |xgress|
|
43
43
|
fatal_violation jq: "[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == \"#{xgress}\" and .Properties.GroupName != null)]|map(.LogicalResourceId)",
|
44
44
|
message: "#{xgress} must not have GroupName - EC2 classic is a no-go!"
|
45
|
-
end
|
45
|
+
end
|
data/lib/rule.rb
CHANGED
@@ -2,7 +2,7 @@ require 'logging'
|
|
2
2
|
require_relative 'violation'
|
3
3
|
|
4
4
|
module Rule
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :input_json
|
6
6
|
|
7
7
|
# jq preamble to spit out Resources but as an array of key-value pairs
|
8
8
|
# can be used in jq rule definition but... this is probably reducing replication at the cost of opaqueness
|
@@ -10,7 +10,7 @@ module Rule
|
|
10
10
|
'.Resources|with_entries(.value.LogicalResourceId = .key)[]'
|
11
11
|
end
|
12
12
|
|
13
|
-
# jq to filter
|
13
|
+
# jq to filter CloudFormation resources by Type
|
14
14
|
# can be used in jq rule definition but... this is probably reducing replication at the cost of opaqueness
|
15
15
|
def resources_by_type(resource)
|
16
16
|
"#{resources}| select(.Type == \"#{resource}\")"
|
@@ -23,7 +23,7 @@ module Rule
|
|
23
23
|
|
24
24
|
Logging.logger['log'].debug jq
|
25
25
|
|
26
|
-
stdout = jq_command(@
|
26
|
+
stdout = jq_command(@input_json, jq)
|
27
27
|
result = $?.exitstatus
|
28
28
|
scrape_jq_output_for_error(jq, stdout)
|
29
29
|
|
@@ -145,7 +145,7 @@ module Rule
|
|
145
145
|
|
146
146
|
Logging.logger['log'].debug jq_expression
|
147
147
|
|
148
|
-
stdout = jq_command(@
|
148
|
+
stdout = jq_command(@input_json, jq_expression)
|
149
149
|
result = $?.exitstatus
|
150
150
|
scrape_jq_output_for_error(jq_expression, stdout)
|
151
151
|
if (fail_if_found and result == 0) or
|
@@ -175,13 +175,16 @@ module Rule
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
Logging.logger['log'].debug command
|
178
|
+
def quote(string)
|
179
|
+
"'#{string}'"
|
180
|
+
end
|
183
181
|
|
184
|
-
|
182
|
+
# the -e will return an exit code
|
183
|
+
def jq_command(input_json, jq_expression)
|
184
|
+
IO.popen(['jq', jq_expression, '-e'], 'r+', {:err=>[:child, :out]}) do |pipe|
|
185
|
+
pipe << input_json
|
186
|
+
pipe.close_write
|
187
|
+
pipe.readlines.join
|
188
|
+
end
|
185
189
|
end
|
186
190
|
end
|
187
|
-
|
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.0.
|
4
|
+
version: 0.0.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- someguy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logging
|
@@ -96,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
96
|
version: '0'
|
97
97
|
requirements: []
|
98
98
|
rubyforge_project:
|
99
|
-
rubygems_version: 2.6.
|
99
|
+
rubygems_version: 2.6.3
|
100
100
|
signing_key:
|
101
101
|
specification_version: 4
|
102
102
|
summary: cfn-nag
|