puppet 4.9.4 → 4.10.0
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 +7 -0
- data/Rakefile +6 -0
- data/ext/project_data.yaml +2 -2
- data/lib/hiera/puppet_function.rb +1 -1
- data/lib/puppet.rb +1 -0
- data/lib/puppet/application.rb +14 -0
- data/lib/puppet/application/inspect.rb +3 -0
- data/lib/puppet/defaults.rb +12 -2
- data/lib/puppet/etc.rb +125 -0
- data/lib/puppet/face/help.rb +1 -1
- data/lib/puppet/functions.rb +49 -4
- data/lib/puppet/functions/eyaml_lookup_key.rb +12 -3
- data/lib/puppet/functions/hocon_data.rb +9 -0
- data/lib/puppet/functions/json_data.rb +9 -0
- data/lib/puppet/functions/yaml_data.rb +9 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +69 -22
- data/lib/puppet/indirector/key/file.rb +2 -1
- data/lib/puppet/indirector/ssl_file.rb +24 -3
- data/lib/puppet/module.rb +28 -22
- data/lib/puppet/network/http/compression.rb +2 -1
- data/lib/puppet/parser/compiler.rb +15 -38
- data/lib/puppet/parser/functions/hiera.rb +1 -1
- data/lib/puppet/parser/functions/hiera_array.rb +1 -1
- data/lib/puppet/parser/functions/hiera_hash.rb +1 -1
- data/lib/puppet/parser/functions/hiera_include.rb +1 -1
- data/lib/puppet/parser/scope.rb +59 -17
- data/lib/puppet/pops/evaluator/callable_signature.rb +7 -0
- data/lib/puppet/pops/functions/dispatch.rb +18 -5
- data/lib/puppet/pops/functions/dispatcher.rb +7 -13
- data/lib/puppet/pops/issue_reporter.rb +1 -1
- data/lib/puppet/pops/issues.rb +84 -0
- data/lib/puppet/pops/loader/base_loader.rb +13 -5
- data/lib/puppet/pops/lookup/configured_data_provider.rb +8 -2
- data/lib/puppet/pops/lookup/data_dig_function_provider.rb +109 -19
- data/lib/puppet/pops/lookup/data_hash_function_provider.rb +19 -4
- data/lib/puppet/pops/lookup/data_provider.rb +43 -29
- data/lib/puppet/pops/lookup/environment_data_provider.rb +1 -1
- data/lib/puppet/pops/lookup/explainer.rb +1 -0
- data/lib/puppet/pops/lookup/function_provider.rb +36 -11
- data/lib/puppet/pops/lookup/global_data_provider.rb +18 -5
- data/lib/puppet/pops/lookup/hiera_config.rb +203 -84
- data/lib/puppet/pops/lookup/interpolation.rb +21 -6
- data/lib/puppet/pops/lookup/invocation.rb +14 -9
- data/lib/puppet/pops/lookup/location_resolver.rb +27 -0
- data/lib/puppet/pops/lookup/lookup_adapter.rb +59 -6
- data/lib/puppet/pops/lookup/lookup_key_function_provider.rb +9 -77
- data/lib/puppet/pops/lookup/module_data_provider.rb +27 -4
- data/lib/puppet/pops/parser/lexer2.rb +1 -1
- data/lib/puppet/pops/pcore.rb +3 -3
- data/lib/puppet/pops/types/p_object_type.rb +4 -6
- data/lib/puppet/pops/types/ruby_generator.rb +2 -2
- data/lib/puppet/pops/types/type_asserter.rb +3 -3
- data/lib/puppet/pops/types/type_mismatch_describer.rb +25 -7
- data/lib/puppet/pops/types/types.rb +20 -29
- data/lib/puppet/provider/exec.rb +4 -2
- data/lib/puppet/provider/nameservice.rb +8 -8
- data/lib/puppet/provider/selmodule/semodule.rb +20 -16
- data/lib/puppet/provider/service/src.rb +39 -39
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/user/aix.rb +7 -2
- data/lib/puppet/settings.rb +30 -17
- data/lib/puppet/ssl/base.rb +14 -1
- data/lib/puppet/ssl/certificate_authority.rb +4 -2
- data/lib/puppet/ssl/configuration.rb +4 -1
- data/lib/puppet/ssl/inventory.rb +10 -3
- data/lib/puppet/ssl/key.rb +7 -3
- data/lib/puppet/test/test_helper.rb +3 -0
- data/lib/puppet/type.rb +13 -1
- data/lib/puppet/type/exec.rb +16 -1
- data/lib/puppet/type/group.rb +17 -11
- data/lib/puppet/type/user.rb +3 -1
- data/lib/puppet/util.rb +1 -0
- data/lib/puppet/util/character_encoding.rb +95 -0
- data/lib/puppet/util/execution.rb +9 -6
- data/lib/puppet/util/reference.rb +4 -2
- data/lib/puppet/util/windows/file.rb +5 -1
- data/lib/puppet/version.rb +6 -2
- data/locales/config.yaml +1 -1
- data/locales/puppet.pot +18 -4
- data/spec/integration/ssl/autosign_spec.rb +18 -3
- data/spec/integration/ssl/key_spec.rb +104 -0
- data/spec/integration/type/user_spec.rb +13 -6
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/application/inspect_spec.rb +9 -2
- data/spec/unit/data_providers/function_data_provider_spec.rb +2 -2
- data/spec/unit/etc_spec.rb +234 -0
- data/spec/unit/face/certificate_spec.rb +10 -2
- data/spec/unit/functions/dig_spec.rb +1 -1
- data/spec/unit/functions/hiera_spec.rb +40 -1
- data/spec/unit/functions/lookup_fixture_spec.rb +10 -10
- data/spec/unit/functions/lookup_spec.rb +1217 -357
- data/spec/unit/functions4_spec.rb +37 -1
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +33 -2
- data/spec/unit/indirector/key/file_spec.rb +1 -1
- data/spec/unit/indirector/ssl_file_spec.rb +3 -3
- data/spec/unit/module_spec.rb +52 -59
- data/spec/unit/network/http/compression_spec.rb +39 -8
- data/spec/unit/parser/compiler_spec.rb +14 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +21 -3
- data/spec/unit/pops/loaders/module_loaders_spec.rb +61 -0
- data/spec/unit/pops/lookup/context_spec.rb +56 -8
- data/spec/unit/pops/lookup/lookup_spec.rb +32 -1
- data/spec/unit/pops/parser/lexer2_spec.rb +8 -0
- data/spec/unit/pops/types/ruby_generator_spec.rb +48 -0
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +12 -3
- data/spec/unit/pops/types/types_spec.rb +6 -7
- data/spec/unit/provider/nameservice_spec.rb +12 -12
- data/spec/unit/provider/package/pkg_spec.rb +2 -0
- data/spec/unit/provider/service/src_spec.rb +5 -0
- data/spec/unit/ssl/base_spec.rb +9 -0
- data/spec/unit/ssl/certificate_authority_spec.rb +2 -2
- data/spec/unit/ssl/certificate_request_attributes_spec.rb +6 -0
- data/spec/unit/ssl/certificate_request_spec.rb +1 -1
- data/spec/unit/ssl/certificate_spec.rb +1 -1
- data/spec/unit/ssl/configuration_spec.rb +11 -2
- data/spec/unit/ssl/inventory_spec.rb +27 -3
- data/spec/unit/ssl/key_spec.rb +7 -7
- data/spec/unit/type/exec_spec.rb +41 -4
- data/spec/unit/type/file_spec.rb +4 -1
- data/spec/unit/util/character_encoding_spec.rb +88 -0
- data/spec/unit/util/execution_spec.rb +12 -0
- data/spec/unit/version_spec.rb +4 -0
- metadata +3803 -3808
- data/tasks/i18n.rake +0 -20
@@ -153,15 +153,18 @@ module Puppet::Util::Execution
|
|
153
153
|
:squelch => false,
|
154
154
|
:override_locale => true,
|
155
155
|
:custom_environment => {},
|
156
|
+
:sensitive => false,
|
156
157
|
}
|
157
158
|
|
158
159
|
options = default_options.merge(options)
|
159
160
|
|
160
|
-
if
|
161
|
+
if options[:sensitive]
|
162
|
+
command_str = '[redacted]'
|
163
|
+
elsif command.is_a?(Array)
|
161
164
|
command = command.flatten.map(&:to_s)
|
162
|
-
|
165
|
+
command_str = command.join(" ")
|
163
166
|
elsif command.is_a?(String)
|
164
|
-
|
167
|
+
command_str = command
|
165
168
|
end
|
166
169
|
|
167
170
|
user_log_s = ''
|
@@ -176,9 +179,9 @@ module Puppet::Util::Execution
|
|
176
179
|
end
|
177
180
|
|
178
181
|
if respond_to? :debug
|
179
|
-
debug "Executing#{user_log_s}: '#{
|
182
|
+
debug "Executing#{user_log_s}: '#{command_str}'"
|
180
183
|
else
|
181
|
-
Puppet.debug "Executing#{user_log_s}: '#{
|
184
|
+
Puppet.debug "Executing#{user_log_s}: '#{command_str}'"
|
182
185
|
end
|
183
186
|
|
184
187
|
null_file = Puppet.features.microsoft_windows? ? 'NUL' : '/dev/null'
|
@@ -229,7 +232,7 @@ module Puppet::Util::Execution
|
|
229
232
|
end
|
230
233
|
|
231
234
|
if options[:failonfail] and exit_status != 0
|
232
|
-
raise Puppet::ExecutionFailure, "Execution of '#{
|
235
|
+
raise Puppet::ExecutionFailure, "Execution of '#{command_str}' returned #{exit_status}: #{output.strip}"
|
233
236
|
end
|
234
237
|
ensure
|
235
238
|
if !options[:squelch] && stdout
|
@@ -13,7 +13,8 @@ class Puppet::Util::Reference
|
|
13
13
|
instance_load(:reference, 'puppet/reference')
|
14
14
|
|
15
15
|
def self.footer
|
16
|
-
|
16
|
+
#TRANSLATORS message accompanied by date of generation
|
17
|
+
"\n\n----------------\n\n*" + _("This page autogenerated on ") + "#{Time.now}*\n"
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.modes
|
@@ -111,7 +112,8 @@ class Puppet::Util::Reference
|
|
111
112
|
def to_markdown(withcontents = true)
|
112
113
|
# First the header
|
113
114
|
text = markdown_header(@title, 1)
|
114
|
-
|
115
|
+
#TRANSLATORS message accompanied by date of generation
|
116
|
+
text << _("\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on ") + "#{Time.now.to_s})*\n\n"
|
115
117
|
|
116
118
|
text << @header
|
117
119
|
|
@@ -48,11 +48,15 @@ module Puppet::Util::Windows::File
|
|
48
48
|
FILE_EXECUTE |
|
49
49
|
SYNCHRONIZE
|
50
50
|
|
51
|
+
REPLACEFILE_WRITE_THROUGH = 0x1
|
52
|
+
REPLACEFILE_IGNORE_MERGE_ERRORS = 0x2
|
53
|
+
REPLACEFILE_IGNORE_ACL_ERRORS = 0x3
|
54
|
+
|
51
55
|
def replace_file(target, source)
|
52
56
|
target_encoded = wide_string(target.to_s)
|
53
57
|
source_encoded = wide_string(source.to_s)
|
54
58
|
|
55
|
-
flags =
|
59
|
+
flags = REPLACEFILE_IGNORE_MERGE_ERRORS
|
56
60
|
backup_file = nil
|
57
61
|
result = ReplaceFileW(
|
58
62
|
target_encoded,
|
data/lib/puppet/version.rb
CHANGED
@@ -5,9 +5,8 @@
|
|
5
5
|
# The version can be set programmatically because we want to allow the
|
6
6
|
# Raketasks and such to set the version based on the output of `git describe`
|
7
7
|
|
8
|
-
|
9
8
|
module Puppet
|
10
|
-
PUPPETVERSION = '4.
|
9
|
+
PUPPETVERSION = '4.10.0'
|
11
10
|
|
12
11
|
##
|
13
12
|
# version is a public API method intended to always provide a fast and
|
@@ -68,6 +67,11 @@ module Puppet
|
|
68
67
|
@puppet_version ||= PUPPETVERSION
|
69
68
|
end
|
70
69
|
|
70
|
+
# @return [String] containing the puppet version to minor specificity, e.g. "3.0"
|
71
|
+
def self.minor_version
|
72
|
+
self.version.split('.')[0..1].join('.')
|
73
|
+
end
|
74
|
+
|
71
75
|
def self.version=(version)
|
72
76
|
@puppet_version = version
|
73
77
|
end
|
data/locales/config.yaml
CHANGED
data/locales/puppet.pot
CHANGED
@@ -6,11 +6,11 @@
|
|
6
6
|
#, fuzzy
|
7
7
|
msgid ""
|
8
8
|
msgstr ""
|
9
|
-
"Project-Id-Version: Puppet automation framework 4.
|
9
|
+
"Project-Id-Version: Puppet automation framework 4.9.4-162-g7637326\n"
|
10
10
|
"\n"
|
11
11
|
"Report-Msgid-Bugs-To: https://tickets.puppetlabs.com\n"
|
12
|
-
"POT-Creation-Date: 2017-
|
13
|
-
"PO-Revision-Date: 2017-
|
12
|
+
"POT-Creation-Date: 2017-03-22 13:57-0700\n"
|
13
|
+
"PO-Revision-Date: 2017-03-22 13:57-0700\n"
|
14
14
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
15
15
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
16
16
|
"Language: \n"
|
@@ -40,7 +40,7 @@ msgid ""
|
|
40
40
|
" $ puppet help\n"
|
41
41
|
msgstr ""
|
42
42
|
|
43
|
-
msgid "
|
43
|
+
msgid "VERSION"
|
44
44
|
msgstr ""
|
45
45
|
|
46
46
|
msgid "The version of the subcommand for which to show help."
|
@@ -77,3 +77,17 @@ msgstr ""
|
|
77
77
|
|
78
78
|
msgid "! Subcommand unavailable due to error. Check error logs."
|
79
79
|
msgstr ""
|
80
|
+
|
81
|
+
msgid "%{error}: %{value} is not valid UTF-8 and cannot be transcoded by Puppet."
|
82
|
+
msgstr ""
|
83
|
+
|
84
|
+
#. TRANSLATORS message accompanied by date of generation
|
85
|
+
msgid "This page autogenerated on "
|
86
|
+
msgstr ""
|
87
|
+
|
88
|
+
#. TRANSLATORS message accompanied by date of generation
|
89
|
+
msgid ""
|
90
|
+
"\n"
|
91
|
+
"\n"
|
92
|
+
"**This page is autogenerated; any changes will get overwritten** *(last generated on "
|
93
|
+
msgstr ""
|
@@ -4,6 +4,8 @@ describe "autosigning" do
|
|
4
4
|
include PuppetSpec::Files
|
5
5
|
|
6
6
|
let(:puppet_dir) { tmpdir("ca_autosigning") }
|
7
|
+
let(:utf8_value) { "utf8_\u06FF\u16A0\u{2070E}" }
|
8
|
+
let(:utf8_value_binary_string) { utf8_value.force_encoding(Encoding::BINARY) }
|
7
9
|
let(:csr_attributes_content) do
|
8
10
|
{
|
9
11
|
'custom_attributes' => {
|
@@ -12,10 +14,16 @@ describe "autosigning" do
|
|
12
14
|
'1.3.6.1.4.1.34380.2.2' => # system IPs in hex
|
13
15
|
[ 0xC0A80001, # 192.168.0.1
|
14
16
|
0xC0A80101 ], # 192.168.1.1
|
17
|
+
# different UTF-8 widths
|
18
|
+
# 1-byte A
|
19
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
20
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
21
|
+
# 4-byte 𠜎 - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
22
|
+
'1.2.840.113549.1.9.7' => utf8_value,
|
15
23
|
},
|
16
24
|
'extension_requests' => {
|
17
25
|
'pp_uuid' => 'abcdef',
|
18
|
-
'1.3.6.1.4.1.34380.1.1.2' =>
|
26
|
+
'1.3.6.1.4.1.34380.1.1.2' => utf8_value, # pp_instance_id
|
19
27
|
'1.3.6.1.4.1.34380.1.2.1' => 'some-value', # private extension
|
20
28
|
},
|
21
29
|
}
|
@@ -107,14 +115,20 @@ describe "autosigning" do
|
|
107
115
|
csr = Puppet::SSL::CertificateRequest.indirection.find(host.name)
|
108
116
|
expect(csr.request_extensions).to have(3).items
|
109
117
|
expect(csr.request_extensions).to include('oid' => 'pp_uuid', 'value' => 'abcdef')
|
110
|
-
expect(csr.request_extensions).to include('oid' => 'pp_instance_id', 'value' =>
|
118
|
+
expect(csr.request_extensions).to include('oid' => 'pp_instance_id', 'value' => utf8_value_binary_string)
|
111
119
|
expect(csr.request_extensions).to include('oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'some-value')
|
112
120
|
end
|
113
121
|
|
122
|
+
it "pulls custom attributes from the csr_attributes file into the certificate" do
|
123
|
+
csr = Puppet::SSL::CertificateRequest.indirection.find(host.name)
|
124
|
+
expect(csr.custom_attributes).to have(4).items
|
125
|
+
expect(csr.custom_attributes).to include('oid' => 'challengePassword', 'value' => utf8_value_binary_string)
|
126
|
+
end
|
127
|
+
|
114
128
|
it "copies extension requests to certificate" do
|
115
129
|
cert = ca.sign(host.name)
|
116
130
|
expect(cert.custom_extensions).to include('oid' => 'pp_uuid', 'value' => 'abcdef')
|
117
|
-
expect(cert.custom_extensions).to include('oid' => 'pp_instance_id', 'value' =>
|
131
|
+
expect(cert.custom_extensions).to include('oid' => 'pp_instance_id', 'value' => utf8_value_binary_string)
|
118
132
|
expect(cert.custom_extensions).to include('oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'some-value')
|
119
133
|
end
|
120
134
|
|
@@ -122,6 +136,7 @@ describe "autosigning" do
|
|
122
136
|
cert = ca.sign(host.name)
|
123
137
|
cert.custom_extensions.each do |ext|
|
124
138
|
expect(Puppet::SSL::Oids.subtree_of?('1.3.6.1.4.1.34380.2', ext['oid'])).to be_falsey
|
139
|
+
expect(ext['oid']).to_not eq('1.2.840.113549.1.9.7')
|
125
140
|
end
|
126
141
|
end
|
127
142
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
require 'puppet/ssl/key'
|
5
|
+
|
6
|
+
describe Puppet::SSL::Key do
|
7
|
+
include PuppetSpec::Files
|
8
|
+
|
9
|
+
# different UTF-8 widths
|
10
|
+
# 1-byte A
|
11
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
12
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
13
|
+
# 4-byte - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
14
|
+
let (:mixed_utf8) { "A\u06FF\u16A0\u{2070E}" } # Aۿᚠ
|
15
|
+
|
16
|
+
before do
|
17
|
+
# Get a safe temporary file
|
18
|
+
dir = tmpdir('key_integration_testing')
|
19
|
+
|
20
|
+
Puppet.settings[:confdir] = dir
|
21
|
+
Puppet.settings[:vardir] = dir
|
22
|
+
|
23
|
+
# This is necessary so the terminus instances don't lie around.
|
24
|
+
# and so that Puppet::SSL::Key.indirection.save may be used
|
25
|
+
Puppet::SSL::Key.indirection.termini.clear
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'with a custom user-specified passfile' do
|
29
|
+
|
30
|
+
before do
|
31
|
+
# write custom password file to where Puppet expects
|
32
|
+
password_file = tmpfile('passfile')
|
33
|
+
Puppet[:passfile] = password_file
|
34
|
+
Puppet::FileSystem.open(password_file, nil, 'w:UTF-8') { |f| f.print(mixed_utf8) }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should use the configured password file if it is not the CA key' do
|
38
|
+
key = Puppet::SSL::Key.new('test')
|
39
|
+
expect(key.password_file).to eq(Puppet[:passfile])
|
40
|
+
expect(key.password).to eq(mixed_utf8.force_encoding(Encoding::BINARY))
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be able to read an existing private key given the correct password" do
|
44
|
+
Puppet[:keylength] = '50'
|
45
|
+
|
46
|
+
key_name = 'test'
|
47
|
+
# use OpenSSL APIs to generate a private key
|
48
|
+
private_key = OpenSSL::PKey::RSA.generate(512)
|
49
|
+
|
50
|
+
# stash it in Puppets private key directory
|
51
|
+
FileUtils.mkdir_p(Puppet[:privatekeydir])
|
52
|
+
pem_path = File.join(Puppet[:privatekeydir], "#{key_name}.pem")
|
53
|
+
Puppet::FileSystem.open(pem_path, nil, 'w:UTF-8') do |f|
|
54
|
+
# with password protection enabled
|
55
|
+
pem = private_key.to_pem(OpenSSL::Cipher::DES.new(:EDE3, :CBC), mixed_utf8)
|
56
|
+
f.print(pem)
|
57
|
+
end
|
58
|
+
|
59
|
+
# indirector loads existing .pem off disk instead of replacing it
|
60
|
+
host = Puppet::SSL::Host.new(key_name)
|
61
|
+
host.generate
|
62
|
+
|
63
|
+
# newly loaded host private key matches the manually created key
|
64
|
+
# Private-Key: (512 bit) style data
|
65
|
+
expect(host.key.content.to_text).to eq(private_key.to_text)
|
66
|
+
# -----BEGIN RSA PRIVATE KEY-----
|
67
|
+
expect(host.key.content.to_s).to eq(private_key.to_s)
|
68
|
+
expect(host.key.password).to eq(mixed_utf8.force_encoding(Encoding::BINARY))
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should export the private key to PEM using the password' do
|
72
|
+
Puppet[:keylength] = '50'
|
73
|
+
|
74
|
+
key_name = 'test'
|
75
|
+
|
76
|
+
# uses specified :passfile when writing the private key
|
77
|
+
key = Puppet::SSL::Key.new(key_name)
|
78
|
+
key.generate
|
79
|
+
Puppet::SSL::Key.indirection.save(key)
|
80
|
+
|
81
|
+
# indirector writes file here
|
82
|
+
pem_path = File.join(Puppet[:privatekeydir], "#{key_name}.pem")
|
83
|
+
|
84
|
+
# note incorrect password is an error
|
85
|
+
expect do
|
86
|
+
Puppet::FileSystem.open(pem_path, nil, 'r:ASCII') do |f|
|
87
|
+
reloaded_key = OpenSSL::PKey::RSA.new(f.read, 'invalid_password')
|
88
|
+
end
|
89
|
+
end.to raise_error(OpenSSL::PKey::RSAError)
|
90
|
+
|
91
|
+
# but when specifying the correct password
|
92
|
+
reloaded_key = nil
|
93
|
+
Puppet::FileSystem.open(pem_path, nil, 'r:ASCII') do |f|
|
94
|
+
reloaded_key = OpenSSL::PKey::RSA.new(f.read, mixed_utf8)
|
95
|
+
end
|
96
|
+
|
97
|
+
# the original key matches the manually reloaded key
|
98
|
+
# Private-Key: (512 bit) style data
|
99
|
+
expect(key.content.to_text).to eq(reloaded_key.to_text)
|
100
|
+
# -----BEGIN RSA PRIVATE KEY-----
|
101
|
+
expect(key.content.to_s).to eq(reloaded_key.to_s)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -8,9 +8,16 @@ describe Puppet::Type.type(:user), '(integration)', :unless => Puppet.features.m
|
|
8
8
|
include PuppetSpec::Compiler
|
9
9
|
|
10
10
|
context "when set to purge ssh keys from a file" do
|
11
|
+
# different UTF-8 widths
|
12
|
+
# 1-byte A
|
13
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
14
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
15
|
+
# 4-byte 𠜎 - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
16
|
+
let (:mixed_utf8) { "A\u06FF\u16A0\u{2070E}" } # Aۿᚠ𠜎
|
17
|
+
|
11
18
|
let(:tempfile) do
|
12
19
|
file_containing('user_spec', <<-EOF)
|
13
|
-
# comment
|
20
|
+
# comment #{mixed_utf8}
|
14
21
|
ssh-rsa KEY-DATA key-name
|
15
22
|
ssh-rsa KEY-DATA key name
|
16
23
|
EOF
|
@@ -22,12 +29,12 @@ describe Puppet::Type.type(:user), '(integration)', :unless => Puppet.features.m
|
|
22
29
|
|
23
30
|
it "should purge authorized ssh keys" do
|
24
31
|
apply_compiled_manifest(manifest)
|
25
|
-
expect(File.read(tempfile)).not_to match(/key-name/)
|
32
|
+
expect(File.read(tempfile, :encoding => Encoding::UTF_8)).not_to match(/key-name/)
|
26
33
|
end
|
27
34
|
|
28
35
|
it "should purge keys with spaces in the comment string" do
|
29
36
|
apply_compiled_manifest(manifest)
|
30
|
-
expect(File.read(tempfile)).not_to match(/key name/)
|
37
|
+
expect(File.read(tempfile, :encoding => Encoding::UTF_8)).not_to match(/key name/)
|
31
38
|
end
|
32
39
|
|
33
40
|
context "with other prefetching resources evaluated first" do
|
@@ -35,14 +42,14 @@ describe Puppet::Type.type(:user), '(integration)', :unless => Puppet.features.m
|
|
35
42
|
|
36
43
|
it "should purge authorized ssh keys" do
|
37
44
|
apply_compiled_manifest(manifest)
|
38
|
-
expect(File.read(tempfile)).not_to match(/key-name/)
|
45
|
+
expect(File.read(tempfile, :encoding => Encoding::UTF_8)).not_to match(/key-name/)
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
42
49
|
context "with multiple unnamed keys" do
|
43
50
|
let(:tempfile) do
|
44
51
|
file_containing('user_spec', <<-EOF)
|
45
|
-
# comment
|
52
|
+
# comment #{mixed_utf8}
|
46
53
|
ssh-rsa KEY-DATA1
|
47
54
|
ssh-rsa KEY-DATA2
|
48
55
|
EOF
|
@@ -50,7 +57,7 @@ describe Puppet::Type.type(:user), '(integration)', :unless => Puppet.features.m
|
|
50
57
|
|
51
58
|
it "should purge authorized ssh keys" do
|
52
59
|
apply_compiled_manifest(manifest)
|
53
|
-
expect(File.read(tempfile)).not_to match(/KEY-DATA/)
|
60
|
+
expect(File.read(tempfile, :encoding => Encoding::UTF_8)).not_to match(/KEY-DATA/)
|
54
61
|
end
|
55
62
|
end
|
56
63
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,13 @@ $LOAD_PATH.unshift File.join(dir, 'lib')
|
|
8
8
|
# Don't want puppet getting the command line arguments for rake or autotest
|
9
9
|
ARGV.clear
|
10
10
|
|
11
|
+
# Stub out gettext's `_` method, which attempts to load translations.
|
12
|
+
# Several of our mocks (mostly around file system interaction) are broken by
|
13
|
+
# FastGettext's implementation of this method.
|
14
|
+
def _(msg)
|
15
|
+
msg
|
16
|
+
end
|
17
|
+
|
11
18
|
begin
|
12
19
|
require 'rubygems'
|
13
20
|
rescue LoadError
|
@@ -42,6 +42,11 @@ describe Puppet::Application::Inspect do
|
|
42
42
|
Puppet::Resource::Catalog.indirection.expects(:terminus_class=).with(:yaml)
|
43
43
|
expect { @inspect.setup }.not_to raise_error
|
44
44
|
end
|
45
|
+
|
46
|
+
it "should be marked as deprecated" do
|
47
|
+
@inspect.setup
|
48
|
+
expect(@inspect.deprecated?).to be true
|
49
|
+
end
|
45
50
|
end
|
46
51
|
|
47
52
|
describe "when executing", :uses_checksums => true do
|
@@ -193,8 +198,10 @@ describe Puppet::Application::Inspect do
|
|
193
198
|
|
194
199
|
@inspect.run_command
|
195
200
|
|
196
|
-
|
197
|
-
expect(@report.logs
|
201
|
+
# First several errors are deprecation warnings, find correct log message
|
202
|
+
expect(@report.logs).to be_any { |l|
|
203
|
+
/Could not back up/.match(l.message)
|
204
|
+
}
|
198
205
|
end
|
199
206
|
end
|
200
207
|
|
@@ -90,7 +90,7 @@ describe "when using function data provider" do
|
|
90
90
|
env_loader.add_entry(:function, 'environment::data', f.new(compiler.topscope, env_loader), nil)
|
91
91
|
expect do
|
92
92
|
compiler.compile()
|
93
|
-
end.to raise_error(/Value returned from deprecated API function
|
93
|
+
end.to raise_error(/Value returned from deprecated API function 'environment::data' has wrong type/)
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'raises an error if the module data function does not return a hash' do
|
@@ -109,7 +109,7 @@ describe "when using function data provider" do
|
|
109
109
|
module_loader.add_entry(:function, 'abc::data', f.new(compiler.topscope, module_loader), nil)
|
110
110
|
expect do
|
111
111
|
compiler.compile()
|
112
|
-
end.to raise_error(/Value returned from deprecated API function
|
112
|
+
end.to raise_error(/Value returned from deprecated API function 'abc::data' has wrong type/)
|
113
113
|
end
|
114
114
|
|
115
115
|
def parent_fixture(dir_name)
|
@@ -0,0 +1,234 @@
|
|
1
|
+
require 'puppet'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
# The Ruby::Etc module is largely non-functional on Windows - many methods
|
5
|
+
# simply return nil regardless of input, the Etc::Group struct is not defined,
|
6
|
+
# and Etc::Passwd is missing fields
|
7
|
+
describe Puppet::Etc, :if => !Puppet.features.microsoft_windows? do
|
8
|
+
let(:bin) { 'bin'.force_encoding(Encoding::ISO_8859_1) }
|
9
|
+
let(:root) { 'root'.force_encoding(Encoding::ISO_8859_1) }
|
10
|
+
let(:x) { 'x'.force_encoding(Encoding::ISO_8859_1) }
|
11
|
+
let(:daemon) { 'daemon'.force_encoding(Encoding::ISO_8859_1) }
|
12
|
+
let(:root_comment) { 'i am the root user'.force_encoding(Encoding::ISO_8859_1) }
|
13
|
+
let(:user_struct_iso_8859_1) { Etc::Passwd.new(root, x, 0, 0, root_comment) }
|
14
|
+
let(:group_struct_iso_8859_1) { Etc::Group.new(bin, x, 1, [root, bin, daemon]) }
|
15
|
+
|
16
|
+
# http://www.fileformat.info/info/unicode/char/5e0c/index.htm
|
17
|
+
# 希 Han Character 'rare; hope, expect, strive for'
|
18
|
+
# In EUC_KR: \xfd \xf1 - 253 241
|
19
|
+
# Not convertible to UTF-8, likely to be read in as BINARY by Ruby unless system is in EUC_KR
|
20
|
+
let(:not_convertible) { [254, 241].pack('C*') }
|
21
|
+
|
22
|
+
# characters representing different UTF-8 widths
|
23
|
+
# 1-byte A
|
24
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
25
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
26
|
+
# 4-byte 𠜎 - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
27
|
+
#
|
28
|
+
# Should all convert cleanly to UTF-8
|
29
|
+
# Unless the system is in UTF-8, these will likely be read in as BINARY by Ruby
|
30
|
+
let(:convertible_utf8) { "A\u06FF\u16A0\u{2070E}" } # Aۿᚠ𠜎
|
31
|
+
let(:convertible_binary) { "A\u06FF\u16A0\u{2070E}".force_encoding(Encoding::BINARY) }
|
32
|
+
|
33
|
+
# For the methods described which actually expect an encoding conversion, we
|
34
|
+
# only superficially test via #force_encoding - the deeper level testing is in
|
35
|
+
# character_encoding_spec.rb which handles testing transcoding etc.
|
36
|
+
|
37
|
+
describe "getgrent" do
|
38
|
+
context "given an original system Etc Group struct with ISO-8850-1 string values" do
|
39
|
+
before { Etc.expects(:getgrent).returns(group_struct_iso_8859_1) }
|
40
|
+
let(:converted) { Puppet::Etc.getgrent }
|
41
|
+
|
42
|
+
it "should return a struct with :name and :passwd field values converted to UTF-8" do
|
43
|
+
[converted.name, converted.passwd].each do |value|
|
44
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return a struct with a :mem array with all field values converted to UTF-8" do
|
49
|
+
converted.mem.each { |elem| expect(elem.encoding).to eq(Encoding::UTF_8) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "given an original Etc::Group struct with field values that cannot be converted to UTF-8" do
|
54
|
+
let(:group) { Etc::Group.new }
|
55
|
+
before do
|
56
|
+
# group membership contains valid and invalid UTF-8
|
57
|
+
group.mem = [convertible_binary, not_convertible]
|
58
|
+
# group name contains a value that is invalid UTF-8
|
59
|
+
group.name = not_convertible
|
60
|
+
# group passwd field is valid UTF-8
|
61
|
+
group.passwd = convertible_binary
|
62
|
+
|
63
|
+
Etc.expects(:getgrent).returns(group)
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:converted) { Puppet::Etc.getgrent }
|
67
|
+
|
68
|
+
it "should convert convertible values in arrays to UTF-8" do
|
69
|
+
expect(converted.mem[0]).to eq("A\u06FF\u16A0\u{2070E}")
|
70
|
+
expect(converted.mem[0].encoding).to eq(Encoding::UTF_8) # just being explicit
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should leave the unconvertible values unmodified" do
|
74
|
+
expect(converted.name).to eq([254, 241].pack('C*'))
|
75
|
+
expect(converted.name.encoding).to eq(Encoding::BINARY) # just being explicit
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should leave unconvertible values in arrays unmodifed" do
|
79
|
+
expect(converted.mem[1]).to eq([254, 241].pack('C*'))
|
80
|
+
expect(converted.mem[1].encoding).to eq(Encoding::BINARY) # just being explicit
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should convert values that can be converted to UTf-8" do
|
84
|
+
expect(converted.passwd).to eq("A\u06FF\u16A0\u{2070E}")
|
85
|
+
expect(converted.passwd.encoding).to eq(Encoding::UTF_8) # just being explicit
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "endgrent" do
|
91
|
+
it "should call Etc.getgrent" do
|
92
|
+
Etc.expects(:getgrent)
|
93
|
+
Puppet::Etc.getgrent
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "setgrent" do
|
98
|
+
it "should call Etc.setgrent" do
|
99
|
+
Etc.expects(:setgrent)
|
100
|
+
Puppet::Etc.setgrent
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "getpwent" do
|
105
|
+
context "given an original system Etc Passwd struct with ISO-8859-1 string values" do
|
106
|
+
before { Etc.expects(:getpwent).returns(user_struct_iso_8859_1) }
|
107
|
+
let(:converted) { Puppet::Etc.getpwent }
|
108
|
+
|
109
|
+
it "should return an Etc Passwd struct with field values converted to UTF-8" do
|
110
|
+
[converted.name, converted.passwd, converted.gecos].each do |value|
|
111
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "given an original Etc::Passwd struct with field values that cannot be converted to UTF-8" do
|
117
|
+
let(:user) { Etc::Passwd.new }
|
118
|
+
before do
|
119
|
+
# user comment field cannot be converted to UTF-8
|
120
|
+
user.gecos = not_convertible
|
121
|
+
# user passwd field is valid UTF-8
|
122
|
+
user.passwd = convertible_binary
|
123
|
+
|
124
|
+
Etc.expects(:getpwent).returns(user)
|
125
|
+
end
|
126
|
+
|
127
|
+
let(:converted) { Puppet::Etc.getpwent }
|
128
|
+
|
129
|
+
it "should leave the unconvertible values unmodified" do
|
130
|
+
expect(converted.gecos).to eq([254, 241].pack('C*'))
|
131
|
+
expect(converted.gecos.encoding).to eq(Encoding::BINARY) # just being explicit
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should convert values that can be converted to UTf-8" do
|
135
|
+
expect(converted.passwd).to eq("A\u06FF\u16A0\u{2070E}")
|
136
|
+
expect(converted.passwd.encoding).to eq(Encoding::UTF_8) # just being explicit
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "endpwent" do
|
142
|
+
it "should call Etc.endpwent" do
|
143
|
+
Etc.expects(:endpwent)
|
144
|
+
Puppet::Etc.endpwent
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "setpwent" do
|
149
|
+
it "should call Etc.setpwent" do
|
150
|
+
Etc.expects(:setpwent)
|
151
|
+
Puppet::Etc.setpwent
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "getpwnam" do
|
156
|
+
context "given a username to query" do
|
157
|
+
it "should call Etc.getpwnam with that username" do
|
158
|
+
Etc.expects(:getpwnam).with('foo')
|
159
|
+
Puppet::Etc.getpwnam('foo')
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "given an original system Etc Passwd struct with ISO-8859-1 string values" do
|
164
|
+
it "should return an Etc Passwd struct with field values converted to UTF-8" do
|
165
|
+
Etc.expects(:getpwnam).with('root').returns(user_struct_iso_8859_1)
|
166
|
+
converted = Puppet::Etc.getpwnam('root')
|
167
|
+
[converted.name, converted.passwd, converted.gecos].each do |value|
|
168
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "getgrnam" do
|
175
|
+
context "given a group name to query" do
|
176
|
+
it "should call Etc.getgrnam with that group name" do
|
177
|
+
Etc.expects(:getgrnam).with('foo')
|
178
|
+
Puppet::Etc.getgrnam('foo')
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "given an original system Etc Group struct with ISO-8859-1 string values" do
|
183
|
+
it "should return an Etc Group struct with field values converted to UTF-8" do
|
184
|
+
Etc.expects(:getgrnam).with('bin').returns(group_struct_iso_8859_1)
|
185
|
+
converted = Puppet::Etc.getgrnam('bin')
|
186
|
+
[converted.name, converted.passwd].each do |value|
|
187
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
188
|
+
end
|
189
|
+
converted.mem.each { |elem| expect(elem.encoding).to eq(Encoding::UTF_8) }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "getgrgid" do
|
195
|
+
context "given a group ID to query" do
|
196
|
+
it "should call Etc.getgrgid with the id" do
|
197
|
+
Etc.expects(:getgrgid).with(0)
|
198
|
+
Puppet::Etc.getgrgid(0)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "given an original Etc Group struct with field values in ISO-8859-1" do
|
203
|
+
it "should return an Etc Group struct with field values converted to UTF-8" do
|
204
|
+
Etc.expects(:getgrgid).with(1).returns(group_struct_iso_8859_1)
|
205
|
+
converted = Puppet::Etc.getgrgid(1)
|
206
|
+
[converted.name, converted.passwd].each do |value|
|
207
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
208
|
+
end
|
209
|
+
converted.mem.each { |elem| expect(elem.encoding).to eq(Encoding::UTF_8) }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "getpwid" do
|
215
|
+
context "given a UID to query" do
|
216
|
+
it "should call Etc.getpwuid with the id" do
|
217
|
+
Etc.expects(:getpwuid).with(2)
|
218
|
+
Puppet::Etc.getpwuid(2)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context "given an orginal Etc Passwd struct with field values in ISO-8859-1" do
|
224
|
+
it "should return an Etc Passwd struct with field values converted to UTF-8" do
|
225
|
+
Etc.expects(:getpwuid).with(0).returns(user_struct_iso_8859_1)
|
226
|
+
converted = Puppet::Etc.getpwuid(0)
|
227
|
+
[converted.name, converted.passwd, converted.gecos].each do |value|
|
228
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
end
|