puppet_auditor 0.1.0 → 0.2.0
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/Gemfile.lock +14 -8
- data/README.md +3 -0
- data/lib/puppet_auditor/cli.rb +11 -0
- data/lib/puppet_auditor/lint_plugin.rb +116 -4
- data/lib/puppet_auditor/version.rb +1 -1
- data/puppet_auditor.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84f7e5cffe4df624ca9e10438b1d30199fc56560c954a0eab2bb166b8cc46cf7
|
4
|
+
data.tar.gz: be50f8f05976de06718e2285de06ab04d0af18856b6aceb3be42bf7125392aa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f0c3058f2a7765dd714e1ed28a45c77d755eb8494771d55f5d46749a29fd072b891d9a28bc2a5d627a4fec47942bfd8b41282d704e4e67a155f17e02d76188f
|
7
|
+
data.tar.gz: 523be5ff715b774b387eb99b786608da7fe952d83a6d9a454db8c8a96057c738c79d5fbd904011ac3328d0c064092ba95c12bf30b446ab00f87b07ccc04c263c
|
data/Gemfile.lock
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
puppet_auditor (0.
|
4
|
+
puppet_auditor (0.2.0)
|
5
|
+
puppet (~> 5.5)
|
5
6
|
puppet-lint (>= 1.1, < 3.0)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
|
-
coderay (1.1.2)
|
11
11
|
diff-lcs (1.3)
|
12
12
|
docile (1.3.0)
|
13
|
+
facter (2.5.1)
|
14
|
+
fast_gettext (1.1.2)
|
15
|
+
hiera (3.4.4)
|
13
16
|
json (2.1.0)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
locale (2.1.2)
|
18
|
+
multi_json (1.13.1)
|
19
|
+
puppet (5.5.6)
|
20
|
+
facter (> 2.0.1, < 4)
|
21
|
+
fast_gettext (~> 1.1.2)
|
22
|
+
hiera (>= 3.2.1, < 4)
|
23
|
+
locale (~> 2.1)
|
24
|
+
multi_json (~> 1.10)
|
25
|
+
puppet-lint (2.3.6)
|
19
26
|
rake (10.5.0)
|
20
27
|
rspec (3.7.0)
|
21
28
|
rspec-core (~> 3.7.0)
|
@@ -46,7 +53,6 @@ PLATFORMS
|
|
46
53
|
|
47
54
|
DEPENDENCIES
|
48
55
|
bundler (~> 1.16)
|
49
|
-
pry
|
50
56
|
puppet_auditor!
|
51
57
|
rake (~> 10.0)
|
52
58
|
rspec (~> 3.0)
|
data/README.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
[](https://travis-ci.org/instruct-br/puppet_auditor)
|
2
|
+
[](https://badge.fury.io/rb/puppet_auditor)
|
3
|
+
|
1
4
|
# PuppetAuditor
|
2
5
|
|
3
6
|
PuppetAuditor is a tool to test Puppet manifests against a set of defined rules.
|
data/lib/puppet_auditor/cli.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
module PuppetAuditor
|
2
2
|
class Cli
|
3
|
+
|
4
|
+
@@path = ''
|
5
|
+
|
6
|
+
def self.path
|
7
|
+
@@path
|
8
|
+
end
|
9
|
+
|
3
10
|
def initialize(args)
|
4
11
|
@checks = []
|
12
|
+
|
5
13
|
OptionParser.new do |opts|
|
6
14
|
opts.banner = "Usage: puppet_auditor [options]"
|
7
15
|
|
@@ -30,6 +38,9 @@ module PuppetAuditor
|
|
30
38
|
load_checks('~/.puppet_auditor.yaml') if user_default && ENV.key?('HOME')
|
31
39
|
load_checks('.puppet_auditor.yaml') if project_default
|
32
40
|
load_checks(specific_yaml_rules) if specific_yaml_rules
|
41
|
+
|
42
|
+
@@path = File.expand_path('.')
|
43
|
+
|
33
44
|
end.parse!
|
34
45
|
end
|
35
46
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'puppet'
|
2
|
+
|
1
3
|
module PuppetAuditor
|
2
4
|
class LintPlugin < PuppetLint::CheckPlugin
|
3
5
|
|
@@ -14,17 +16,112 @@ module PuppetAuditor
|
|
14
16
|
|
15
17
|
def initialize
|
16
18
|
super
|
17
|
-
@resource
|
18
|
-
@attributes
|
19
|
-
@message
|
19
|
+
@resource = self.class::RESOURCE
|
20
|
+
@attributes = self.class::ATTRIBUTES
|
21
|
+
@message = self.class::MESSAGE
|
22
|
+
@scoped_variables = { 'global' => {} }
|
23
|
+
@scopes = {}
|
20
24
|
end
|
21
25
|
|
22
26
|
def check
|
27
|
+
discover_scopes
|
28
|
+
build_scope
|
29
|
+
scan_variables
|
23
30
|
resource_indexes.each { |resource| resource_block(resource) if resource[:type].value == @resource }
|
24
31
|
end
|
25
32
|
|
26
33
|
private
|
27
34
|
|
35
|
+
def build_scope
|
36
|
+
Puppet.settings[:hiera_config] = File.join(PuppetAuditor::Cli.path, 'hiera.yaml')
|
37
|
+
|
38
|
+
env = Puppet::Node::Environment.create(:_p_auditor, [])
|
39
|
+
node = Puppet::Node.new('localhost', environment: env)
|
40
|
+
Puppet.push_context({environments: Puppet::Environments::Static.new(env)})
|
41
|
+
compiler = Puppet::Parser::Compiler.new(node)
|
42
|
+
@scope = compiler.topscope
|
43
|
+
end
|
44
|
+
|
45
|
+
def lookup(key)
|
46
|
+
Puppet::Pops::Lookup.lookup(key, nil, nil, false, :default, Puppet::Pops::Lookup::Invocation.new(@scope, {}, {}))
|
47
|
+
end
|
48
|
+
|
49
|
+
def class_scopes
|
50
|
+
class_indexes.each do |class_hash|
|
51
|
+
class_name = class_hash[:tokens].first.next_code_token
|
52
|
+
# class name { -> :NAME
|
53
|
+
# (...)
|
54
|
+
# }
|
55
|
+
#
|
56
|
+
# class name( -> :FUNCTION_NAME
|
57
|
+
# Type $parameter = 'default',
|
58
|
+
# ) {
|
59
|
+
# (...)
|
60
|
+
# }
|
61
|
+
if class_name.type == :NAME || class_name.type == :FUNCTION_NAME
|
62
|
+
@scopes["class_#{class_name.value}"] = [class_hash[:start], class_hash[:end]]
|
63
|
+
@scoped_variables["class_#{class_name.value}"] = {}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def defined_type_scopes
|
69
|
+
defined_type_indexes.each do |defined_type_hash|
|
70
|
+
defined_type_name = defined_type_hash[:tokens].first.next_code_token
|
71
|
+
if defined_type_name.type == :NAME
|
72
|
+
@scopes["dtype_#{defined_type_name.value}"] = [defined_type_hash[:start], defined_type_hash[:end]]
|
73
|
+
@scoped_variables["dtype_#{defined_type_name.value}"] = {}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def node_scopes
|
79
|
+
node_indexes.each do |node_hash|
|
80
|
+
node_name = node_hash[:tokens].first.next_code_token
|
81
|
+
if node_name.type == :SSTRING
|
82
|
+
@scopes["node_#{node_name.value}"] = [node_hash[:start], node_hash[:end]]
|
83
|
+
@scoped_variables["node_#{node_name.value}"] = {}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def scope(index)
|
89
|
+
@scopes.sort_by { |name, range|
|
90
|
+
if name.start_with?('class')
|
91
|
+
0
|
92
|
+
elsif name.start_with?('dtype')
|
93
|
+
1
|
94
|
+
elsif name.start_with?('node')
|
95
|
+
2
|
96
|
+
else
|
97
|
+
3
|
98
|
+
end
|
99
|
+
}.find(-> { ['global'] }) { |name, range| index.between?(*range) }.first
|
100
|
+
end
|
101
|
+
|
102
|
+
def token_index(unknown)
|
103
|
+
tokens.find_index { |indexed| indexed.line == unknown.line && indexed.column == unknown.column }
|
104
|
+
end
|
105
|
+
|
106
|
+
def discover_scopes
|
107
|
+
class_scopes
|
108
|
+
defined_type_scopes
|
109
|
+
node_scopes
|
110
|
+
end
|
111
|
+
|
112
|
+
def scan_variables
|
113
|
+
# This method works because:
|
114
|
+
# - "variable assignments are evaluation-order dependent"
|
115
|
+
# - "Unlike most other languages, Puppet only allows a given variable to be assigned once within a given scope"
|
116
|
+
#
|
117
|
+
# See: https://puppet.com/docs/puppet/5.5/lang_variables.html
|
118
|
+
tokens.each_with_index do |token, index|
|
119
|
+
if token.type == :VARIABLE && token.next_code_token.type == :EQUALS
|
120
|
+
@scoped_variables[scope(index)][token.value] = cast_token(token.next_code_token.next_code_token)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
28
125
|
def resource_block(resource)
|
29
126
|
@attributes.each do |attribute_name, comparison_rules|
|
30
127
|
attribute = resource[:tokens].find { |t| t.type == :NAME && t.value == attribute_name && t.next_code_token.type == :FARROW }
|
@@ -63,12 +160,27 @@ module PuppetAuditor
|
|
63
160
|
while next_token.type != :DQPOST
|
64
161
|
next_token = next_token.next_code_token
|
65
162
|
if next_token.type == :VARIABLE
|
66
|
-
full_str += "${#{next_token.value}}"
|
163
|
+
full_str += cast_token(next_token) || "${#{next_token.value}}"
|
67
164
|
else
|
68
165
|
full_str += next_token.value
|
69
166
|
end
|
70
167
|
end
|
71
168
|
full_str
|
169
|
+
when :VARIABLE
|
170
|
+
@scoped_variables[scope(token_index(token))][token.value]
|
171
|
+
when :NAME, :FUNCTION_NAME
|
172
|
+
if token.value == 'hiera' || token.value == 'lookup'
|
173
|
+
next_token = token
|
174
|
+
while next_token.type != :SSTRING && next_token.type != :RPAREN
|
175
|
+
next_token = next_token.next_code_token
|
176
|
+
if next_token.type == :SSTRING
|
177
|
+
return lookup(next_token.value)
|
178
|
+
elsif next_token.type == :NAME || next_token.type == :FUNCTION_NAME
|
179
|
+
return lookup(cast_token(next_token))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
token.value
|
72
184
|
else
|
73
185
|
token.value
|
74
186
|
end
|
data/puppet_auditor.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
28
|
spec.add_dependency 'puppet-lint', '>= 1.1', '< 3.0'
|
29
|
+
spec.add_dependency 'puppet', '~> 5.5'
|
29
30
|
|
30
31
|
spec.add_development_dependency "bundler", "~> 1.16"
|
31
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet_auditor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Esgalha
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: puppet-lint
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '3.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: puppet
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '5.5'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '5.5'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: bundler
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|