puppet 6.16.0-x64-mingw32 → 6.17.0-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +4 -2
- data/Gemfile.lock +10 -10
- data/README.md +2 -2
- data/lib/puppet/agent.rb +2 -2
- data/lib/puppet/application/agent.rb +14 -3
- data/lib/puppet/configurer.rb +20 -12
- data/lib/puppet/confine.rb +1 -1
- data/lib/puppet/defaults.rb +25 -8
- data/lib/puppet/file_serving/http_metadata.rb +13 -1
- data/lib/puppet/file_serving/metadata.rb +4 -1
- data/lib/puppet/file_serving/terminus_selector.rb +7 -8
- data/lib/puppet/file_system/file_impl.rb +1 -1
- data/lib/puppet/file_system/uniquefile.rb +8 -16
- data/lib/puppet/forge.rb +1 -1
- data/lib/puppet/forge/cache.rb +1 -1
- data/lib/puppet/forge/repository.rb +3 -7
- data/lib/puppet/http/client.rb +5 -0
- data/lib/puppet/http/redirector.rb +9 -7
- data/lib/puppet/http/response.rb +19 -0
- data/lib/puppet/indirector.rb +1 -1
- data/lib/puppet/indirector/file_content/rest.rb +1 -1
- data/lib/puppet/indirector/file_metadata/http.rb +24 -5
- data/lib/puppet/indirector/file_metadata/rest.rb +2 -2
- data/lib/puppet/indirector/request.rb +1 -1
- data/lib/puppet/network/http/api/indirected_routes.rb +1 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +3 -0
- data/lib/puppet/network/http/connection_adapter.rb +6 -4
- data/lib/puppet/parser/ast/leaf.rb +5 -5
- data/lib/puppet/parser/ast/pops_bridge.rb +0 -4
- data/lib/puppet/parser/compiler.rb +1 -1
- data/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +2 -0
- data/lib/puppet/parser/compiler/catalog_validator/site_validator.rb +2 -0
- data/lib/puppet/parser/environment_compiler.rb +4 -1
- data/lib/puppet/parser/resource.rb +3 -2
- data/lib/puppet/parser/resource/param.rb +6 -0
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -5
- data/lib/puppet/pops/issues.rb +5 -0
- data/lib/puppet/pops/resource/resource_type_impl.rb +2 -0
- data/lib/puppet/pops/validation/checker4_0.rb +10 -0
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/provider/package/aptitude.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/service/windows.rb +23 -7
- data/lib/puppet/provider/user/useradd.rb +11 -4
- data/lib/puppet/reports/http.rb +2 -0
- data/lib/puppet/resource.rb +2 -1
- data/lib/puppet/resource/type.rb +8 -0
- data/lib/puppet/ssl/ssl_context.rb +2 -2
- data/lib/puppet/ssl/ssl_provider.rb +20 -1
- data/lib/puppet/test/test_helper.rb +8 -10
- data/lib/puppet/trusted_external.rb +29 -1
- data/lib/puppet/type.rb +12 -5
- data/lib/puppet/type/file.rb +38 -13
- data/lib/puppet/type/file/checksum.rb +4 -4
- data/lib/puppet/type/file/source.rb +4 -4
- data/lib/puppet/type/service.rb +49 -0
- data/lib/puppet/util.rb +39 -15
- data/lib/puppet/util/checksums.rb +19 -4
- data/lib/puppet/util/fileparsing.rb +2 -2
- data/lib/puppet/util/provider_features.rb +1 -1
- data/lib/puppet/util/reference.rb +1 -1
- data/lib/puppet/util/windows/api_types.rb +45 -32
- data/lib/puppet/util/windows/eventlog.rb +1 -6
- data/lib/puppet/util/windows/principal.rb +8 -6
- data/lib/puppet/util/windows/registry.rb +11 -11
- data/lib/puppet/util/windows/service.rb +43 -26
- data/lib/puppet/util/windows/user.rb +23 -8
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +249 -221
- data/man/man5/puppet.conf.5 +19 -8
- data/man/man8/puppet-agent.8 +2 -2
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/application/agent_spec.rb +89 -0
- data/spec/integration/defaults_spec.rb +1 -2
- data/spec/integration/network/http_pool_spec.rb +26 -9
- data/spec/integration/parser/compiler_spec.rb +11 -0
- data/spec/integration/type/file_spec.rb +1 -1
- data/spec/integration/util/windows/registry_spec.rb +7 -7
- data/spec/integration/util/windows/user_spec.rb +40 -5
- data/spec/unit/configurer/fact_handler_spec.rb +4 -4
- data/spec/unit/context/trusted_information_spec.rb +10 -4
- data/spec/unit/file_serving/http_metadata_spec.rb +37 -14
- data/spec/unit/file_serving/terminus_selector_spec.rb +45 -26
- data/spec/unit/http/client_spec.rb +64 -8
- data/spec/unit/http/response_spec.rb +6 -0
- data/spec/unit/indirector/file_metadata/http_spec.rb +27 -0
- data/spec/unit/indirector/request_spec.rb +1 -1
- data/spec/unit/interface_spec.rb +3 -3
- data/spec/unit/network/http/api/indirected_routes_spec.rb +2 -1
- data/spec/unit/network/http/connection_spec.rb +42 -32
- data/spec/unit/parser/ast/block_expression_spec.rb +1 -1
- data/spec/unit/parser/environment_compiler_spec.rb +7 -0
- data/spec/unit/parser/scope_spec.rb +1 -1
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +15 -1
- data/spec/unit/pops/loaders/loaders_spec.rb +1 -1
- data/spec/unit/pops/types/type_calculator_spec.rb +1 -11
- data/spec/unit/provider/service/windows_spec.rb +22 -14
- data/spec/unit/provider/user/openbsd_spec.rb +1 -0
- data/spec/unit/provider/user/useradd_spec.rb +22 -16
- data/spec/unit/resource_spec.rb +3 -3
- data/spec/unit/ssl/ssl_provider_spec.rb +69 -43
- data/spec/unit/test/test_helper_spec.rb +17 -0
- data/spec/unit/transaction/report_spec.rb +1 -1
- data/spec/unit/type/file/source_spec.rb +3 -3
- data/spec/unit/type/file_spec.rb +122 -96
- data/spec/unit/type/service_spec.rb +176 -0
- data/spec/unit/type_spec.rb +50 -0
- data/spec/unit/util/checksums_spec.rb +16 -0
- data/spec/unit/util/windows/api_types_spec.rb +104 -40
- data/spec/unit/util/windows/service_spec.rb +4 -4
- data/spec/unit/util_spec.rb +3 -3
- data/spec/unit/x509/cert_provider_spec.rb +1 -1
- metadata +5 -5
- data/spec/integration/test/test_helper_spec.rb +0 -31
@@ -122,7 +122,7 @@ describe Puppet::Network::HttpPool, unless: Puppet::Util::Platform.jruby? do
|
|
122
122
|
Puppet::Network::HttpPool.http_client_class = klass
|
123
123
|
end
|
124
124
|
|
125
|
-
it "connects using the scheme, host and port from the http instance" do
|
125
|
+
it "connects using the scheme, host and port from the http instance preserving the URL path and query" do
|
126
126
|
request_line = nil
|
127
127
|
|
128
128
|
response_proc = -> (req, res) {
|
@@ -131,20 +131,20 @@ describe Puppet::Network::HttpPool, unless: Puppet::Util::Platform.jruby? do
|
|
131
131
|
|
132
132
|
server.start_server(response_proc: response_proc) do |port|
|
133
133
|
http = Puppet::Network::HttpPool.http_instance(hostname, port, true)
|
134
|
-
path = "http://bogus.example.com:443/foo"
|
134
|
+
path = "http://bogus.example.com:443/foo?q=a"
|
135
135
|
http.get(path)
|
136
136
|
|
137
137
|
if legacy_api
|
138
|
-
# The old API
|
139
|
-
# the host we connected to.
|
140
|
-
expect(request_line).to eq("GET http://bogus.example.com:443/foo HTTP/1.1\r\n")
|
138
|
+
# The old API uses 'absolute-form' and passes the bogus hostname
|
139
|
+
# which isn't the host we connected to.
|
140
|
+
expect(request_line).to eq("GET http://bogus.example.com:443/foo?q=a HTTP/1.1\r\n")
|
141
141
|
else
|
142
|
-
expect(request_line).to eq("GET /foo HTTP/1.1\r\n")
|
142
|
+
expect(request_line).to eq("GET /foo?q=a HTTP/1.1\r\n")
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
-
it "requires the caller to URL encode the path" do
|
147
|
+
it "requires the caller to URL encode the path and query when using absolute form" do
|
148
148
|
request_line = nil
|
149
149
|
|
150
150
|
response_proc = -> (req, res) {
|
@@ -153,16 +153,33 @@ describe Puppet::Network::HttpPool, unless: Puppet::Util::Platform.jruby? do
|
|
153
153
|
|
154
154
|
server.start_server(response_proc: response_proc) do |port|
|
155
155
|
http = Puppet::Network::HttpPool.http_instance(hostname, port, true)
|
156
|
-
|
156
|
+
params = { 'key' => 'a value' }
|
157
|
+
encoded_url = "https://#{hostname}:#{port}/foo%20bar?q=#{Puppet::Util.uri_query_encode(params.to_json)}"
|
157
158
|
http.get(encoded_url)
|
158
159
|
|
159
160
|
if legacy_api
|
160
161
|
expect(request_line).to eq("GET #{encoded_url} HTTP/1.1\r\n")
|
161
162
|
else
|
162
|
-
expect(request_line).to eq("GET /foo%20bar HTTP/1.1\r\n")
|
163
|
+
expect(request_line).to eq("GET /foo%20bar?q=%7B%22key%22%3A%22a%20value%22%7D HTTP/1.1\r\n")
|
163
164
|
end
|
164
165
|
end
|
165
166
|
end
|
167
|
+
|
168
|
+
it "requires the caller to URL encode the path and query when using a path" do
|
169
|
+
request_line = nil
|
170
|
+
|
171
|
+
response_proc = -> (req, res) {
|
172
|
+
request_line = req.request_line
|
173
|
+
}
|
174
|
+
|
175
|
+
server.start_server(response_proc: response_proc) do |port|
|
176
|
+
http = Puppet::Network::HttpPool.http_instance(hostname, port, true)
|
177
|
+
params = { 'key' => 'a value' }
|
178
|
+
http.get("/foo%20bar?q=#{Puppet::Util.uri_query_encode(params.to_json)}")
|
179
|
+
|
180
|
+
expect(request_line).to eq("GET /foo%20bar?q=%7B%22key%22%3A%22a%20value%22%7D HTTP/1.1\r\n")
|
181
|
+
end
|
182
|
+
end
|
166
183
|
end
|
167
184
|
|
168
185
|
describe Puppet::Network::HTTP::Connection do
|
@@ -834,6 +834,17 @@ describe Puppet::Parser::Compiler do
|
|
834
834
|
MANIFEST
|
835
835
|
end.to raise_error(/Foo\[bar\]:\s+parameter 'a' expects a value for key 'd'\s+parameter 'a' unrecognized key 'c'/m)
|
836
836
|
end
|
837
|
+
|
838
|
+
it 'handles Sensitive type in resource array' do
|
839
|
+
catalog = compile_to_catalog(<<-MANIFEST)
|
840
|
+
define foo(Sensitive[String] $password) {
|
841
|
+
notify{ "${title}": message => "${password}" }
|
842
|
+
}
|
843
|
+
foo { ['testA', 'testB']: password =>Sensitive('some password') }
|
844
|
+
MANIFEST
|
845
|
+
expect(catalog).to have_resource("Notify[testA]").with_parameter(:message, 'Sensitive [value redacted]')
|
846
|
+
expect(catalog).to have_resource("Notify[testB]").with_parameter(:message, 'Sensitive [value redacted]')
|
847
|
+
end
|
837
848
|
end
|
838
849
|
|
839
850
|
context 'when using typed parameters in class' do
|
@@ -1160,7 +1160,7 @@ describe Puppet::Type.type(:file), :uses_checksums => true do
|
|
1160
1160
|
source_prefix = Puppet::Util::Platform.windows? ? '/' : ''
|
1161
1161
|
|
1162
1162
|
# the URI can be round-tripped through unescape
|
1163
|
-
expect(
|
1163
|
+
expect(Puppet::Util.uri_unescape(uri_path)).to eq(source_prefix + source)
|
1164
1164
|
# and is properly UTF-8
|
1165
1165
|
expect(uri_path.encoding).to eq (Encoding::UTF_8)
|
1166
1166
|
|
@@ -259,23 +259,23 @@ describe Puppet::Util::Windows::Registry do
|
|
259
259
|
{
|
260
260
|
name: 'REG_SZ',
|
261
261
|
type: Win32::Registry::REG_SZ,
|
262
|
-
value: "reg sz\u0000 string",
|
263
|
-
expected_value: "reg sz
|
262
|
+
value: "reg sz\u0000\u0000 string",
|
263
|
+
expected_value: "reg sz"
|
264
264
|
},
|
265
265
|
{
|
266
266
|
name: 'REG_SZ_2',
|
267
267
|
type: Win32::Registry::REG_SZ,
|
268
|
-
value: "reg sz\x00 string",
|
269
|
-
expected_value: "reg sz
|
268
|
+
value: "reg sz 2\x00\x00 string",
|
269
|
+
expected_value: "reg sz 2"
|
270
270
|
},
|
271
271
|
{
|
272
272
|
name: 'REG_EXPAND_SZ',
|
273
273
|
type: Win32::Registry::REG_EXPAND_SZ,
|
274
|
-
value: "\0reg expand string",
|
275
|
-
expected_value: "
|
274
|
+
value: "\0\0\0reg expand string",
|
275
|
+
expected_value: ""
|
276
276
|
}
|
277
277
|
].each do |pair|
|
278
|
-
it '
|
278
|
+
it 'reads up to the first wide null' do
|
279
279
|
hklm.create("#{puppet_key}\\#{subkey_name}", Win32::Registry::KEY_ALL_ACCESS) do |reg|
|
280
280
|
reg.write(value_name, pair[:type], pair[:value])
|
281
281
|
end
|
@@ -125,19 +125,16 @@ describe "Puppet::Util::Windows::User", :if => Puppet::Util::Platform.windows? d
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'should raise error given that logon returns false' do
|
128
|
-
|
129
128
|
allow(Puppet::Util::Windows::User).to receive(:logon_user_by_logon_type).with(
|
130
|
-
user, passwd, fLOGON32_LOGON_NETWORK, fLOGON32_PROVIDER_DEFAULT, anything).and_return (0)
|
129
|
+
user, '.', passwd, fLOGON32_LOGON_NETWORK, fLOGON32_PROVIDER_DEFAULT, anything).and_return (0)
|
131
130
|
allow(Puppet::Util::Windows::User).to receive(:logon_user_by_logon_type).with(
|
132
|
-
user, passwd, fLOGON32_LOGON_INTERACTIVE, fLOGON32_PROVIDER_DEFAULT, anything).and_return(0)
|
131
|
+
user, '.', passwd, fLOGON32_LOGON_INTERACTIVE, fLOGON32_PROVIDER_DEFAULT, anything).and_return(0)
|
133
132
|
|
134
133
|
expect {Puppet::Util::Windows::User.logon_user(user, passwd) {}}
|
135
134
|
.to raise_error(Puppet::Util::Windows::Error, /Failed to logon user/)
|
136
|
-
|
137
135
|
end
|
138
136
|
end
|
139
137
|
|
140
|
-
|
141
138
|
describe "password_is?" do
|
142
139
|
it "should return false given an incorrect username and password" do
|
143
140
|
expect(Puppet::Util::Windows::User.password_is?(username, bad_password)).to be_falsey
|
@@ -180,5 +177,43 @@ describe "Puppet::Util::Windows::User", :if => Puppet::Util::Platform.windows? d
|
|
180
177
|
expect { Puppet::Util::Windows::User.check_token_membership }.not_to raise_error
|
181
178
|
end
|
182
179
|
end
|
180
|
+
|
181
|
+
describe "default_system_account?" do
|
182
|
+
it "should succesfully identify 'SYSTEM' user as a default system account" do
|
183
|
+
allow(Puppet::Util::Windows::SID).to receive(:name_to_sid).with('SYSTEM').and_return(Puppet::Util::Windows::SID::LocalSystem)
|
184
|
+
expect(Puppet::Util::Windows::User.default_system_account?('SYSTEM')).to eq(true)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should succesfully identify 'NETWORK SERVICE' user as a default system account" do
|
188
|
+
allow(Puppet::Util::Windows::SID).to receive(:name_to_sid).with('NETWORK SERVICE').and_return(Puppet::Util::Windows::SID::NtNetwork)
|
189
|
+
expect(Puppet::Util::Windows::User.default_system_account?('NETWORK SERVICE')).to eq(true)
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should succesfully identify 'LOCAL SERVICE' user as a default system account" do
|
193
|
+
allow(Puppet::Util::Windows::SID).to receive(:name_to_sid).with('LOCAL SERVICE').and_return(Puppet::Util::Windows::SID::NtLocal)
|
194
|
+
expect(Puppet::Util::Windows::User.default_system_account?('LOCAL SERVICE')).to eq(true)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should not identify user with unknown sid as a default system account" do
|
198
|
+
allow(Puppet::Util::Windows::SID).to receive(:name_to_sid).with('UnknownUser').and_return(Puppet::Util::Windows::SID::Null)
|
199
|
+
expect(Puppet::Util::Windows::User.default_system_account?('UnknownUser')).to eq(false)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "localsystem?" do
|
204
|
+
before do
|
205
|
+
allow(Puppet::Util::Windows::ADSI).to receive(:computer_name).and_return("myPC")
|
206
|
+
end
|
207
|
+
|
208
|
+
['LocalSystem', '.\LocalSystem', 'myPC\LocalSystem', 'lOcALsysTem'].each do |input|
|
209
|
+
it "should succesfully identify #{input} as the 'LocalSystem' account" do
|
210
|
+
expect(Puppet::Util::Windows::User.localsystem?(input)).to eq(true)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should not identify any other user as the 'LocalSystem' account" do
|
215
|
+
expect(Puppet::Util::Windows::User.localsystem?('OtherUser')).to eq(false)
|
216
|
+
end
|
217
|
+
end
|
183
218
|
end
|
184
219
|
end
|
@@ -104,7 +104,7 @@ describe Puppet::Configurer::FactHandler do
|
|
104
104
|
expect(text).to include(test_fact[:encoded])
|
105
105
|
|
106
106
|
# this is not sufficient to test whether these values are sent via HTTP GET or HTTP POST in actual catalog request
|
107
|
-
expect(JSON.parse(
|
107
|
+
expect(JSON.parse(Puppet::Util.uri_unescape(to_upload[:facts]))['values']).to eq(test_fact[:hash])
|
108
108
|
end
|
109
109
|
end
|
110
110
|
end
|
@@ -129,7 +129,7 @@ describe Puppet::Configurer::FactHandler do
|
|
129
129
|
expect(to_upload).to eq({:facts_format => 'application/json', :facts => text})
|
130
130
|
expect(text).to include(test_fact[:encoded])
|
131
131
|
|
132
|
-
expect(JSON.parse(
|
132
|
+
expect(JSON.parse(Puppet::Util.uri_unescape(to_upload[:facts]))['values']).to eq(test_fact[:hash])
|
133
133
|
end
|
134
134
|
end
|
135
135
|
end
|
@@ -138,9 +138,9 @@ describe Puppet::Configurer::FactHandler do
|
|
138
138
|
facts = Puppet::Node::Facts.new(Puppet[:node_name_value], 'my_name_fact' => 'other_node_name')
|
139
139
|
Puppet::Node::Facts.indirection.save(facts)
|
140
140
|
|
141
|
-
# prefer
|
141
|
+
# prefer Puppet::Util.uri_unescape but validate CGI also works
|
142
142
|
encoded_facts = facthandler.facts_for_uploading[:facts]
|
143
|
-
expect(
|
143
|
+
expect(Puppet::Util.uri_unescape(encoded_facts)).to validate_against('api/schemas/facts.json')
|
144
144
|
expect(CGI.unescape(encoded_facts)).to validate_against('api/schemas/facts.json')
|
145
145
|
end
|
146
146
|
end
|
@@ -41,8 +41,12 @@ describe Puppet::Context::TrustedInformation, :unless => RUBY_PLATFORM == 'java'
|
|
41
41
|
}
|
42
42
|
|
43
43
|
def allow_external_trusted_data(certname, data)
|
44
|
-
|
45
|
-
|
44
|
+
command = 'generate_data.sh'
|
45
|
+
Puppet[:trusted_external_command] = command
|
46
|
+
# The expand_path bit is necessary b/c :trusted_external_command is a
|
47
|
+
# file_or_directory setting, and file_or_directory settings automatically
|
48
|
+
# expand the given path.
|
49
|
+
allow(Puppet::Util::Execution).to receive(:execute).with([File.expand_path(command), certname], anything).and_return(JSON.dump(data))
|
46
50
|
end
|
47
51
|
|
48
52
|
it "defaults external to an empty hash" do
|
@@ -99,9 +103,11 @@ describe Puppet::Context::TrustedInformation, :unless => RUBY_PLATFORM == 'java'
|
|
99
103
|
end
|
100
104
|
|
101
105
|
it 'only runs the trusted external command the first time it is invoked' do
|
102
|
-
|
106
|
+
command = 'generate_data.sh'
|
107
|
+
Puppet[:trusted_external_command] = command
|
103
108
|
|
104
|
-
|
109
|
+
# See allow_external_trusted_data to understand why expand_path is necessary
|
110
|
+
expect(Puppet::Util::Execution).to receive(:execute).with([File.expand_path(command), 'cert name'], anything).and_return(JSON.dump(external_data)).once
|
105
111
|
|
106
112
|
trusted = Puppet::Context::TrustedInformation.remote(true, 'cert name', cert)
|
107
113
|
trusted.external
|
@@ -30,11 +30,6 @@ describe Puppet::FileServing::HttpMetadata do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context "with no Last-Modified or Content-MD5 header from the server" do
|
33
|
-
before do
|
34
|
-
allow(http_response).to receive(:[]).with('last-modified').and_return(nil)
|
35
|
-
allow(http_response).to receive(:[]).with('content-md5').and_return(nil)
|
36
|
-
end
|
37
|
-
|
38
33
|
it "should use :mtime as the checksum type, based on current time" do
|
39
34
|
# Stringifying Time.now does some rounding; do so here so we don't end up with a time
|
40
35
|
# that's greater than the stringified version returned by collect.
|
@@ -51,13 +46,9 @@ describe Puppet::FileServing::HttpMetadata do
|
|
51
46
|
context "with a Last-Modified header from the server" do
|
52
47
|
let(:time) { Time.now.utc }
|
53
48
|
|
54
|
-
before do
|
55
|
-
allow(http_response).to receive(:[]).with('content-md5').and_return(nil)
|
56
|
-
end
|
57
|
-
|
58
49
|
it "should use :mtime as the checksum type, based on Last-Modified" do
|
59
50
|
# HTTP uses "GMT" not "UTC"
|
60
|
-
|
51
|
+
http_response.add_field('last-modified', time.strftime("%a, %d %b %Y %T GMT"))
|
61
52
|
metadata = described_class.new(http_response)
|
62
53
|
metadata.collect
|
63
54
|
expect( metadata.checksum_type ).to eq :mtime
|
@@ -70,16 +61,48 @@ describe Puppet::FileServing::HttpMetadata do
|
|
70
61
|
let(:base64) { Digest::MD5.new.base64digest input }
|
71
62
|
let(:hex) { Digest::MD5.new.hexdigest input }
|
72
63
|
|
73
|
-
|
74
|
-
|
75
|
-
|
64
|
+
it "should use the md5 checksum" do
|
65
|
+
http_response.add_field('content-md5', base64)
|
66
|
+
metadata = described_class.new(http_response)
|
67
|
+
metadata.collect
|
68
|
+
expect( metadata.checksum_type ).to eq :md5
|
69
|
+
expect( metadata.checksum ).to eq "{md5}#{hex}"
|
76
70
|
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with X-Checksum-Md5" do
|
74
|
+
let(:md5) { "c58989e9740a748de4f5054286faf99b" }
|
77
75
|
|
78
76
|
it "should use the md5 checksum" do
|
77
|
+
http_response.add_field('X-Checksum-Md5', md5)
|
79
78
|
metadata = described_class.new(http_response)
|
80
79
|
metadata.collect
|
81
80
|
expect( metadata.checksum_type ).to eq :md5
|
82
|
-
expect( metadata.checksum ).to eq "{md5}#{
|
81
|
+
expect( metadata.checksum ).to eq "{md5}#{md5}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with X-Checksum-Sha1" do
|
86
|
+
let(:sha1) { "01e4d15746f4274b84d740a93e04b9fd2882e3ea" }
|
87
|
+
|
88
|
+
it "should use the SHA1 checksum" do
|
89
|
+
http_response.add_field('X-Checksum-Sha1', sha1)
|
90
|
+
metadata = described_class.new(http_response)
|
91
|
+
metadata.collect
|
92
|
+
expect( metadata.checksum_type ).to eq :sha1
|
93
|
+
expect( metadata.checksum ).to eq "{sha1}#{sha1}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "with X-Checksum-Sha256" do
|
98
|
+
let(:sha256) { "a3eda98259c30e1e75039c2123670c18105e1c46efb672e42ca0e4cbe77b002a" }
|
99
|
+
|
100
|
+
it "should use the SHA256 checksum" do
|
101
|
+
http_response.add_field('X-Checksum-Sha256', sha256)
|
102
|
+
metadata = described_class.new(http_response)
|
103
|
+
metadata.collect
|
104
|
+
expect( metadata.checksum_type ).to eq :sha256
|
105
|
+
expect( metadata.checksum ).to eq "{sha256}#{sha256}"
|
83
106
|
end
|
84
107
|
end
|
85
108
|
end
|
@@ -3,62 +3,81 @@ require 'spec_helper'
|
|
3
3
|
require 'puppet/file_serving/terminus_selector'
|
4
4
|
|
5
5
|
describe Puppet::FileServing::TerminusSelector do
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
class TestSelector
|
7
|
+
include Puppet::FileServing::TerminusSelector
|
8
|
+
end
|
9
9
|
|
10
|
-
|
10
|
+
def create_request(key)
|
11
|
+
Puppet::Indirector::Request.new(:indirection_name, :find, key, nil, {node: 'whatever'})
|
11
12
|
end
|
12
13
|
|
14
|
+
subject { TestSelector.new }
|
15
|
+
|
13
16
|
describe "when being used to select termini" do
|
14
17
|
it "should return :file if the request key is fully qualified" do
|
15
|
-
|
16
|
-
|
18
|
+
request = create_request(File.expand_path('/foo'))
|
19
|
+
|
20
|
+
expect(subject.select(request)).to eq(:file)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return :file_server if the request key is relative" do
|
24
|
+
request = create_request('modules/my_module/path/to_file')
|
25
|
+
|
26
|
+
expect(subject.select(request)).to eq(:file_server)
|
17
27
|
end
|
18
28
|
|
19
29
|
it "should return :file if the URI protocol is set to 'file'" do
|
20
|
-
|
21
|
-
|
30
|
+
request = create_request(Puppet::Util.path_to_uri(File.expand_path("/foo")).to_s)
|
31
|
+
|
32
|
+
expect(subject.select(request)).to eq(:file)
|
22
33
|
end
|
23
34
|
|
24
35
|
it "should return :http if the URI protocol is set to 'http'" do
|
25
|
-
|
26
|
-
|
36
|
+
request = create_request("http://www.example.com")
|
37
|
+
|
38
|
+
expect(subject.select(request)).to eq(:http)
|
27
39
|
end
|
28
40
|
|
29
41
|
it "should return :http if the URI protocol is set to 'https'" do
|
30
|
-
|
31
|
-
|
42
|
+
request = create_request("https://www.example.com")
|
43
|
+
|
44
|
+
expect(subject.select(request)).to eq(:http)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return :http if the path starts with a double slash" do
|
48
|
+
request = create_request("https://www.example.com//index.html")
|
49
|
+
|
50
|
+
expect(subject.select(request)).to eq(:http)
|
32
51
|
end
|
33
52
|
|
34
53
|
it "should fail when a protocol other than :puppet, :http(s) or :file is used" do
|
35
|
-
|
36
|
-
|
54
|
+
request = create_request("ftp://ftp.example.com")
|
55
|
+
|
56
|
+
expect {
|
57
|
+
subject.select(request)
|
58
|
+
}.to raise_error(ArgumentError, /URI protocol 'ftp' is not currently supported for file serving/)
|
37
59
|
end
|
38
60
|
|
39
61
|
describe "and the protocol is 'puppet'" do
|
40
|
-
before do
|
41
|
-
allow(@request).to receive(:protocol).and_return("puppet")
|
42
|
-
end
|
43
|
-
|
44
62
|
it "should choose :rest when a server is specified" do
|
45
|
-
|
46
|
-
|
47
|
-
expect(
|
63
|
+
request = create_request("puppet://puppetserver.example.com")
|
64
|
+
|
65
|
+
expect(subject.select(request)).to eq(:rest)
|
48
66
|
end
|
49
67
|
|
50
68
|
# This is so a given file location works when bootstrapping with no server.
|
51
69
|
it "should choose :rest when default_file_terminus is rest" do
|
52
|
-
allow(@request).to receive(:protocol).and_return("puppet")
|
53
70
|
Puppet[:server] = 'localhost'
|
54
|
-
|
71
|
+
request = create_request("puppet:///plugins")
|
72
|
+
|
73
|
+
expect(subject.select(request)).to eq(:rest)
|
55
74
|
end
|
56
75
|
|
57
76
|
it "should choose :file_server when default_file_terminus is file_server and no server is specified on the request" do
|
58
|
-
expect(@request).to receive(:protocol).and_return("puppet")
|
59
|
-
expect(@request).to receive(:server).and_return(nil)
|
60
77
|
Puppet[:default_file_terminus] = 'file_server'
|
61
|
-
|
78
|
+
request = create_request("puppet:///plugins")
|
79
|
+
|
80
|
+
expect(subject.select(request)).to eq(:file_server)
|
62
81
|
end
|
63
82
|
end
|
64
83
|
end
|
@@ -507,6 +507,20 @@ describe Puppet::HTTP::Client do
|
|
507
507
|
|
508
508
|
client.get(uri, options: {basic_auth: {user: 'user', password: nil}})
|
509
509
|
end
|
510
|
+
|
511
|
+
it 'observes userinfo in the URL' do
|
512
|
+
stub_request(:get, uri).with(basic_auth: credentials)
|
513
|
+
|
514
|
+
client.get(URI("https://user:pass@www.example.com"))
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'prefers explicit basic_auth credentials' do
|
518
|
+
uri = URI("https://ignored_user:ignored_pass@www.example.com")
|
519
|
+
|
520
|
+
stub_request(:get, "https://www.example.com").with(basic_auth: credentials)
|
521
|
+
|
522
|
+
client.get(uri, options: {basic_auth: {user: 'user', password: 'pass'}})
|
523
|
+
end
|
510
524
|
end
|
511
525
|
|
512
526
|
context "when redirecting" do
|
@@ -535,10 +549,41 @@ describe Puppet::HTTP::Client do
|
|
535
549
|
expect(response).to be_success
|
536
550
|
end
|
537
551
|
|
538
|
-
it "
|
539
|
-
|
540
|
-
|
541
|
-
stub_request(:get,
|
552
|
+
it "updates the Host header from the Location host and port" do
|
553
|
+
stub_request(:get, start_url).with(headers: { 'Host' => 'www.example.com:8140' })
|
554
|
+
.to_return(redirect_to(url: other_host))
|
555
|
+
stub_request(:get, other_host).with(headers: { 'Host' => 'other.example.com:8140' })
|
556
|
+
.to_return(status: 200)
|
557
|
+
|
558
|
+
response = client.get(start_url)
|
559
|
+
expect(response).to be_success
|
560
|
+
end
|
561
|
+
|
562
|
+
it "omits the default HTTPS port from the Host header" do
|
563
|
+
stub_request(:get, start_url).with(headers: { 'Host' => 'www.example.com:8140' })
|
564
|
+
.to_return(redirect_to(url: "https://other.example.com/qux"))
|
565
|
+
stub_request(:get, "https://other.example.com/qux").with(headers: { 'Host' => 'other.example.com' })
|
566
|
+
.to_return(status: 200)
|
567
|
+
|
568
|
+
response = client.get(start_url)
|
569
|
+
expect(response).to be_success
|
570
|
+
end
|
571
|
+
|
572
|
+
it "omits the default HTTP port from the Host header" do
|
573
|
+
stub_request(:get, start_url).with(headers: { 'Host' => 'www.example.com:8140' })
|
574
|
+
.to_return(redirect_to(url: "http://other.example.com/qux"))
|
575
|
+
stub_request(:get, "http://other.example.com/qux").with(headers: { 'Host' => 'other.example.com' })
|
576
|
+
.to_return(status: 200)
|
577
|
+
|
578
|
+
response = client.get(start_url)
|
579
|
+
expect(response).to be_success
|
580
|
+
end
|
581
|
+
|
582
|
+
it "applies query parameters from the location header" do
|
583
|
+
query = { 'redirected' => false }
|
584
|
+
|
585
|
+
stub_request(:get, start_url).with(query: query).to_return(redirect_to(url: "#{bar_url}?redirected=true"))
|
586
|
+
stub_request(:get, bar_url).with(query: {'redirected' => 'true'}).to_return(status: 200)
|
542
587
|
|
543
588
|
response = client.get(start_url, params: query)
|
544
589
|
expect(response).to be_success
|
@@ -569,16 +614,27 @@ describe Puppet::HTTP::Client do
|
|
569
614
|
expect(response).to be_success
|
570
615
|
end
|
571
616
|
|
572
|
-
it "
|
617
|
+
it "applies query parameters from the location header" do
|
573
618
|
relative_url = "/people.html"
|
574
|
-
query = { '
|
575
|
-
stub_request(:get, start_url).with(query: query).to_return(redirect_to(url: relative_url))
|
576
|
-
stub_request(:get, "https://www.example.com:8140/people.html").with(query:
|
619
|
+
query = { 'redirected' => false }
|
620
|
+
stub_request(:get, start_url).with(query: query).to_return(redirect_to(url: "#{relative_url}?redirected=true"))
|
621
|
+
stub_request(:get, "https://www.example.com:8140/people.html").with(query: {'redirected' => 'true'}).to_return(status: 200)
|
577
622
|
|
578
623
|
response = client.get(start_url, params: query)
|
579
624
|
expect(response).to be_success
|
580
625
|
end
|
581
626
|
|
627
|
+
it "removes dot segments from a relative location" do
|
628
|
+
# from https://tools.ietf.org/html/rfc3986#section-5.4.2
|
629
|
+
base_url = URI("http://a/b/c/d;p?q")
|
630
|
+
relative_url = "../../../../g"
|
631
|
+
stub_request(:get, base_url).to_return(redirect_to(url: relative_url))
|
632
|
+
stub_request(:get, "http://a/g").to_return(status: 200)
|
633
|
+
|
634
|
+
response = client.get(base_url)
|
635
|
+
expect(response).to be_success
|
636
|
+
end
|
637
|
+
|
582
638
|
it "preserves request body for each request" do
|
583
639
|
data = 'some data'
|
584
640
|
stub_request(:put, start_url).with(body: data).to_return(redirect_to(url: bar_url))
|