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