puppet-lint 4.0.1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c29efe87a1b5506f4849bf91bb2ebdd9aa76985bbfe0cb9206de80d309a5611
4
- data.tar.gz: f17c4c2195f16b27e5595c9e1546ae53ad255913f2ea42203a9eee221e11d809
3
+ metadata.gz: 3953f32f31f48881c186abdd6a5ce57c2debaf28d24afc4b207a2a84a2065ccf
4
+ data.tar.gz: 60730e1ecb6cbf54f72f23bbb96769d181b9132a2fb756bdc858949e953d3467
5
5
  SHA512:
6
- metadata.gz: '048132fc797b8f1ac6b31a310db4b4f654f71930847b6839783107381d7d46893d672ad3c879e6792f8f2c5367aa733addb855cd820c2578da63b4222853e13f'
7
- data.tar.gz: b9d4f0a474c89731757c336811e910885ce87bd4dca6c4041355f2646e51ad87c38eeaa66ced098aca4146d4c33b03c2bffeb970bd0c91c00d111984cd493718
6
+ metadata.gz: 2421fd601c8e371f8bcfa8ffff3f5f9674fa1334d7ced66e1c0bd4a376c8365822f57b11a6d3ad80e134ea2b6faf6c20281e3497715b34c3c22db163e424cb2e
7
+ data.tar.gz: 5ab8e9650e45521eb84ea8c8f89d0970c90f919bd51e82dc6be73fc5a2b0944875673a16058ad0894288730358772ef82f07540a8ac0230bdb32aa5727abab46
@@ -0,0 +1,130 @@
1
+ COMMANDS = Array['command', 'onlyif', 'unless']
2
+ INTERPOLATED_STRINGS = Array[:DQPRE, :DQMID]
3
+ USELESS_CHARS = Array[:WHITESPACE, :COMMA]
4
+
5
+ PuppetLint.new_check(:check_unsafe_interpolations) do
6
+ def check
7
+ # Gather any exec commands' resources into an array
8
+ exec_resources = resource_indexes.filter_map do |resource|
9
+ resource_parameters = resource[:param_tokens].map(&:value)
10
+ resource if resource[:type].value == 'exec' && !(COMMANDS & resource_parameters).empty?
11
+ end
12
+
13
+ # Iterate over title tokens and raise a warning if any are variables
14
+ unless get_exec_titles.empty?
15
+ get_exec_titles.each do |title|
16
+ check_unsafe_title(title)
17
+ end
18
+ end
19
+
20
+ # Iterate over each command found in any exec
21
+ exec_resources.each do |command_resources|
22
+ check_unsafe_interpolations(command_resources)
23
+ end
24
+ end
25
+
26
+ # Iterate over the tokens in a title and raise a warning if an interpolated variable is found
27
+ def check_unsafe_title(title)
28
+ title.each do |token|
29
+ notify_warning(token.next_code_token) if interpolated?(token)
30
+ end
31
+ end
32
+
33
+ # Iterates over an exec resource and if a command, onlyif or unless paramter is found, it is checked for unsafe interpolations
34
+ def check_unsafe_interpolations(command_resources)
35
+ command_resources[:tokens].each do |token|
36
+ # Skip iteration if token isn't a command of type :NAME
37
+ next unless COMMANDS.include?(token.value) && token.type == :NAME
38
+ # Don't check the command if it is parameterised
39
+ next if parameterised?(token)
40
+
41
+ check_command(token).each do |t|
42
+ notify_warning(t)
43
+ end
44
+ end
45
+ end
46
+
47
+ # Raises a warning given a token and message
48
+ def notify_warning(token)
49
+ notify :warning,
50
+ message: "unsafe interpolation of variable '#{token.value}' in exec command",
51
+ line: token.line,
52
+ column: token.column
53
+ end
54
+
55
+ # Iterates over the tokens in a command and adds it to an array of violations if it is an input variable
56
+ def check_command(token)
57
+ # Initialise variables needed in while loop
58
+ rule_violations = []
59
+ current_token = token
60
+
61
+ # Iterate through tokens in command
62
+ while current_token.type != :NEWLINE
63
+ # Check if token is a varibale and if it is parameterised
64
+ rule_violations.append(current_token.next_code_token) if interpolated?(current_token)
65
+ current_token = current_token.next_token
66
+ end
67
+
68
+ rule_violations
69
+ end
70
+
71
+ # A command is parameterised if its args are placed in an array
72
+ # This function checks if the current token is a :FARROW and if so, if it is followed by an LBRACK
73
+ def parameterised?(token)
74
+ current_token = token
75
+ while current_token.type != :NEWLINE
76
+ return true if current_token.type == :FARROW && current_token.next_token.next_token.type == :LBRACK
77
+
78
+ current_token = current_token.next_token
79
+ end
80
+ end
81
+
82
+ # This function is a replacement for puppet_lint's title_tokens function which assumes titles have single quotes
83
+ # This function adds a check for titles in double quotes where there could be interpolated variables
84
+ def get_exec_titles
85
+ result = []
86
+ tokens.each_with_index do |_token, token_idx|
87
+ next if tokens[token_idx].value != 'exec'
88
+
89
+ # We have a resource declaration. Now find the title
90
+ tokens_array = []
91
+ # Check if title is an array
92
+ if tokens[token_idx]&.next_code_token&.next_code_token&.type == :LBRACK
93
+ # Get the start and end indices of the array of titles
94
+ array_start_idx = tokens.rindex { |r| r.type == :LBRACK }
95
+ array_end_idx = tokens.rindex { |r| r.type == :RBRACK }
96
+
97
+ # Grab everything within the array
98
+ title_array_tokens = tokens[(array_start_idx + 1)..(array_end_idx - 1)]
99
+ tokens_array.concat(title_array_tokens.reject do |token|
100
+ USELESS_CHARS.include?(token.type)
101
+ end)
102
+ result << tokens_array
103
+ # Check if title is double quotes string
104
+ elsif tokens[token_idx].next_code_token.next_code_token.type == :DQPRE
105
+ # Find the start and end of the title
106
+ title_start_idx = tokens.find_index(tokens[token_idx].next_code_token.next_code_token)
107
+ title_end_idx = title_start_idx + index_offset_for(':', tokens[title_start_idx..tokens.length])
108
+
109
+ result << tokens[title_start_idx..title_end_idx]
110
+ # Title is in single quotes
111
+ else
112
+ tokens_array.concat([tokens[token_idx].next_code_token.next_code_token])
113
+
114
+ result << tokens_array
115
+ end
116
+ end
117
+ result
118
+ end
119
+
120
+ def interpolated?(token)
121
+ INTERPOLATED_STRINGS.include?(token.type)
122
+ end
123
+
124
+ # Finds the index offset of the next instance of `value` in `tokens_slice` from the original index
125
+ def index_offset_for(value, tokens_slice)
126
+ tokens_slice.each_with_index do |token, i|
127
+ return i if value.include?(token.value)
128
+ end
129
+ end
130
+ end
@@ -1,3 +1,3 @@
1
1
  class PuppetLint
2
- VERSION = '4.0.1'.freeze
2
+ VERSION = '4.1.0'.freeze
3
3
  end
@@ -0,0 +1,186 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'check_unsafe_interpolations' do
4
+ let(:msg) { "unsafe interpolation of variable 'foo' in exec command" }
5
+
6
+ context 'with fix disabled' do
7
+ context 'exec with unsafe interpolation in command' do
8
+ let(:code) do
9
+ <<-PUPPET
10
+ class foo {
11
+
12
+ exec { 'bar':
13
+ command => "echo ${foo}",
14
+ }
15
+
16
+ }
17
+ PUPPET
18
+ end
19
+
20
+ it 'detects an unsafe exec command argument' do
21
+ expect(problems).to have(1).problems
22
+ end
23
+
24
+ it 'creates one warning' do
25
+ expect(problems).to contain_warning(msg)
26
+ end
27
+ end
28
+
29
+ context 'exec with multiple unsafe interpolations in command' do
30
+ let(:code) do
31
+ <<-PUPPET
32
+ class foo {
33
+
34
+ exec { 'bar':
35
+ command => "echo ${foo} ${bar}",
36
+ }
37
+
38
+ }
39
+ PUPPET
40
+ end
41
+
42
+ it 'detects multiple unsafe exec command arguments' do
43
+ expect(problems).to have(2).problems
44
+ end
45
+
46
+ it 'creates two warnings' do
47
+ expect(problems).to contain_warning(msg)
48
+ expect(problems).to contain_warning(msg)
49
+ end
50
+ end
51
+
52
+ context 'code that uses title with unsafe string as command' do
53
+ let(:code) do
54
+ <<-PUPPET
55
+ class foo {
56
+
57
+ exec { "echo ${foo}": }
58
+
59
+ }
60
+ PUPPET
61
+ end
62
+
63
+ it 'detects one problem' do
64
+ expect(problems).to have(1).problems
65
+ end
66
+
67
+ it 'creates one warning' do
68
+ expect(problems).to contain_warning(msg)
69
+ end
70
+ end
71
+
72
+ context 'exec with a safe string in command' do
73
+ let(:code) do
74
+ <<-PUPPET
75
+ class foo {
76
+
77
+ exec { 'bar':
78
+ command => "echo foo",
79
+ }
80
+
81
+ }
82
+ PUPPET
83
+ end
84
+
85
+ it 'detects zero problems' do
86
+ expect(problems).to have(0).problems
87
+ end
88
+ end
89
+
90
+ context 'exec that has an array of args in command' do
91
+ let(:code) do
92
+ <<-PUPPET
93
+ class foo {
94
+
95
+ exec { 'bar':
96
+ command => ['echo', $foo],
97
+ }
98
+ }
99
+ PUPPET
100
+ end
101
+
102
+ it 'detects zero problems' do
103
+ expect(problems).to have(0).problems
104
+ end
105
+ end
106
+
107
+ context 'exec that has an array of args in command' do
108
+ let(:code) do
109
+ <<-PUPPET
110
+ class foo {
111
+
112
+ exec { ["foo", "bar", "baz"]:
113
+ command => echo qux,
114
+ }
115
+ }
116
+ PUPPET
117
+ end
118
+
119
+ it 'detects zero problems' do
120
+ expect(problems).to have(0).problems
121
+ end
122
+ end
123
+
124
+ context 'file resource' do
125
+ let(:code) do
126
+ <<-PUPPET
127
+ class foo {
128
+ file { '/etc/bar':
129
+ ensure => file,
130
+ backup => false,
131
+ content => $baz,
132
+ }
133
+ }
134
+ PUPPET
135
+ end
136
+
137
+ it 'detects zero problems' do
138
+ expect(problems).to have(0).problems
139
+ end
140
+ end
141
+
142
+ context 'file resource and an exec with unsafe interpolation in command' do
143
+ let(:code) do
144
+ <<-PUPPET
145
+ class foo {
146
+ file { '/etc/bar':
147
+ ensure => file,
148
+ backup => false,
149
+ content => $baz,
150
+ }
151
+
152
+ exec { 'qux':
153
+ command => "echo ${foo}",
154
+ }
155
+ }
156
+ PUPPET
157
+ end
158
+
159
+ it 'detects one problem' do
160
+ expect(problems).to have(1).problems
161
+ end
162
+ end
163
+
164
+ context 'case statement and an exec' do
165
+ let(:code) do
166
+ <<-PUPPET
167
+ class foo {
168
+ case bar {
169
+ baz : {
170
+ echo qux
171
+ }
172
+ }
173
+
174
+ exec { 'foo':
175
+ command => "echo bar",
176
+ }
177
+ }
178
+ PUPPET
179
+ end
180
+
181
+ it 'detects zero problems' do
182
+ expect(problems).to have(0).problems
183
+ end
184
+ end
185
+ end
186
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Sharpe
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-07-31 00:00:00.000000000 Z
13
+ date: 2023-08-25 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: " Checks your Puppet manifests against the Puppetlabs style guide
16
16
  and alerts you to any discrepancies.\n"
@@ -66,6 +66,7 @@ files:
66
66
  - lib/puppet-lint/plugins/check_strings/quoted_booleans.rb
67
67
  - lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb
68
68
  - lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb
69
+ - lib/puppet-lint/plugins/check_unsafe_interpolations/check_unsafe_interpolations.rb
69
70
  - lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb
70
71
  - lib/puppet-lint/plugins/check_variables/variable_is_lowercase.rb
71
72
  - lib/puppet-lint/plugins/check_whitespace/140chars.rb
@@ -139,6 +140,7 @@ files:
139
140
  - spec/unit/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb
140
141
  - spec/unit/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb
141
142
  - spec/unit/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb
143
+ - spec/unit/puppet-lint/plugins/check_unsafe_interpolations/check_unsafe_interpolations_spec.rb
142
144
  - spec/unit/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb
143
145
  - spec/unit/puppet-lint/plugins/check_variables/variable_is_lowercase_spec.rb
144
146
  - spec/unit/puppet-lint/plugins/check_whitespace/140chars_spec.rb