puppet 7.0.0-x64-mingw32 → 7.5.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.

Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +2 -16
  3. data/Gemfile +2 -3
  4. data/Gemfile.lock +45 -33
  5. data/ext/build_defaults.yaml +0 -1
  6. data/ext/project_data.yaml +1 -0
  7. data/lib/puppet/application.rb +10 -6
  8. data/lib/puppet/application/agent.rb +1 -0
  9. data/lib/puppet/application/apply.rb +3 -2
  10. data/lib/puppet/application/device.rb +1 -0
  11. data/lib/puppet/application/script.rb +1 -0
  12. data/lib/puppet/application/ssl.rb +11 -0
  13. data/lib/puppet/application_support.rb +7 -0
  14. data/lib/puppet/configurer.rb +16 -3
  15. data/lib/puppet/defaults.rb +14 -41
  16. data/lib/puppet/environments.rb +54 -55
  17. data/lib/puppet/face/facts.rb +26 -2
  18. data/lib/puppet/face/node/clean.rb +8 -0
  19. data/lib/puppet/ffi/posix.rb +10 -0
  20. data/lib/puppet/ffi/posix/constants.rb +14 -0
  21. data/lib/puppet/ffi/posix/functions.rb +24 -0
  22. data/lib/puppet/ffi/windows/api_types.rb +1 -1
  23. data/lib/puppet/ffi/windows/constants.rb +1 -1
  24. data/lib/puppet/file_serving/configuration/parser.rb +5 -2
  25. data/lib/puppet/file_system/memory_file.rb +8 -1
  26. data/lib/puppet/file_system/windows.rb +2 -0
  27. data/lib/puppet/http/factory.rb +4 -0
  28. data/lib/puppet/indirector/facts/facter.rb +1 -0
  29. data/lib/puppet/module_tool/applications/installer.rb +48 -2
  30. data/lib/puppet/module_tool/errors/shared.rb +17 -2
  31. data/lib/puppet/network/formats.rb +67 -0
  32. data/lib/puppet/network/http.rb +5 -2
  33. data/lib/puppet/network/http/api.rb +10 -6
  34. data/lib/puppet/network/http/api/master.rb +3 -2
  35. data/lib/puppet/network/http/api/master/v3.rb +2 -25
  36. data/lib/puppet/network/http/api/master/v3/environments.rb +2 -33
  37. data/lib/puppet/network/http/api/server.rb +10 -0
  38. data/lib/puppet/network/http/api/server/v3.rb +39 -0
  39. data/lib/puppet/network/http/api/server/v3/environments.rb +48 -0
  40. data/lib/puppet/parser/ast/leaf.rb +3 -2
  41. data/lib/puppet/parser/templatewrapper.rb +1 -1
  42. data/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  43. data/lib/puppet/pops/model/ast_transformer.rb +1 -1
  44. data/lib/puppet/pops/parser/lexer2.rb +0 -4
  45. data/lib/puppet/pops/validation/checker4_0.rb +0 -1
  46. data/lib/puppet/property/list.rb +1 -1
  47. data/lib/puppet/provider/group/groupadd.rb +13 -8
  48. data/lib/puppet/provider/package/apt.rb +34 -2
  49. data/lib/puppet/provider/package/aptitude.rb +6 -0
  50. data/lib/puppet/provider/service/debian.rb +2 -0
  51. data/lib/puppet/provider/user/aix.rb +2 -2
  52. data/lib/puppet/provider/user/useradd.rb +62 -8
  53. data/lib/puppet/reference/configuration.rb +6 -5
  54. data/lib/puppet/settings.rb +33 -28
  55. data/lib/puppet/settings/alias_setting.rb +37 -0
  56. data/lib/puppet/settings/environment_conf.rb +1 -0
  57. data/lib/puppet/type/package.rb +3 -3
  58. data/lib/puppet/type/user.rb +1 -1
  59. data/lib/puppet/util/autoload.rb +1 -8
  60. data/lib/puppet/util/monkey_patches.rb +7 -0
  61. data/lib/puppet/util/posix.rb +54 -5
  62. data/lib/puppet/util/windows/adsi.rb +46 -0
  63. data/lib/puppet/util/windows/principal.rb +9 -2
  64. data/lib/puppet/util/windows/sid.rb +4 -2
  65. data/lib/puppet/version.rb +1 -1
  66. data/locales/puppet.pot +166 -146
  67. data/man/man5/puppet.conf.5 +14 -6
  68. data/man/man8/puppet-agent.8 +2 -2
  69. data/man/man8/puppet-apply.8 +2 -2
  70. data/man/man8/puppet-catalog.8 +1 -1
  71. data/man/man8/puppet-config.8 +1 -1
  72. data/man/man8/puppet-describe.8 +1 -1
  73. data/man/man8/puppet-device.8 +2 -2
  74. data/man/man8/puppet-doc.8 +1 -1
  75. data/man/man8/puppet-epp.8 +1 -1
  76. data/man/man8/puppet-facts.8 +8 -2
  77. data/man/man8/puppet-filebucket.8 +1 -1
  78. data/man/man8/puppet-generate.8 +1 -1
  79. data/man/man8/puppet-help.8 +1 -1
  80. data/man/man8/puppet-lookup.8 +1 -1
  81. data/man/man8/puppet-module.8 +1 -1
  82. data/man/man8/puppet-node.8 +1 -1
  83. data/man/man8/puppet-parser.8 +1 -1
  84. data/man/man8/puppet-plugin.8 +1 -1
  85. data/man/man8/puppet-report.8 +1 -1
  86. data/man/man8/puppet-resource.8 +1 -1
  87. data/man/man8/puppet-script.8 +2 -2
  88. data/man/man8/puppet-ssl.8 +5 -1
  89. data/man/man8/puppet.8 +2 -2
  90. data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +91 -0
  91. data/spec/fixtures/unit/provider/user/aix/aix_passwd_file.out +4 -0
  92. data/spec/integration/application/agent_spec.rb +160 -3
  93. data/spec/integration/application/apply_spec.rb +19 -0
  94. data/spec/integration/application/plugin_spec.rb +1 -1
  95. data/spec/integration/defaults_spec.rb +0 -7
  96. data/spec/integration/http/client_spec.rb +12 -0
  97. data/spec/integration/indirector/direct_file_server_spec.rb +1 -3
  98. data/spec/integration/indirector/file_content/file_server_spec.rb +0 -2
  99. data/spec/integration/indirector/file_metadata/file_server_spec.rb +0 -2
  100. data/spec/integration/parser/collection_spec.rb +10 -0
  101. data/spec/integration/resource/type_collection_spec.rb +2 -6
  102. data/spec/integration/transaction_spec.rb +4 -9
  103. data/spec/integration/util/windows/adsi_spec.rb +21 -1
  104. data/spec/integration/util/windows/principal_spec.rb +21 -0
  105. data/spec/integration/util/windows/registry_spec.rb +6 -10
  106. data/spec/spec_helper.rb +1 -4
  107. data/spec/unit/agent_spec.rb +8 -6
  108. data/spec/unit/application/agent_spec.rb +0 -1
  109. data/spec/unit/application/facts_spec.rb +58 -7
  110. data/spec/unit/application/filebucket_spec.rb +0 -2
  111. data/spec/unit/application/ssl_spec.rb +23 -0
  112. data/spec/unit/application_spec.rb +51 -9
  113. data/spec/unit/confine/feature_spec.rb +1 -1
  114. data/spec/unit/confine_spec.rb +8 -2
  115. data/spec/unit/defaults_spec.rb +1 -56
  116. data/spec/unit/environments_spec.rb +221 -68
  117. data/spec/unit/face/node_spec.rb +14 -13
  118. data/spec/unit/file_serving/configuration/parser_spec.rb +8 -1
  119. data/spec/unit/file_serving/metadata_spec.rb +3 -3
  120. data/spec/unit/file_serving/terminus_helper_spec.rb +11 -4
  121. data/spec/unit/file_system_spec.rb +9 -0
  122. data/spec/unit/forge/module_release_spec.rb +2 -7
  123. data/spec/unit/http/factory_spec.rb +19 -0
  124. data/spec/unit/indirector/face_spec.rb +0 -1
  125. data/spec/unit/indirector/facts/facter_spec.rb +20 -5
  126. data/spec/unit/indirector/file_bucket_file/selector_spec.rb +26 -8
  127. data/spec/unit/indirector/indirection_spec.rb +8 -12
  128. data/spec/unit/indirector_spec.rb +2 -2
  129. data/spec/unit/module_tool/applications/installer_spec.rb +66 -0
  130. data/spec/unit/network/formats_spec.rb +41 -0
  131. data/spec/unit/network/http/api/indirected_routes_spec.rb +0 -4
  132. data/spec/unit/network/http/api/master_spec.rb +38 -0
  133. data/spec/unit/network/http/api/{master → server}/v3/environments_spec.rb +2 -2
  134. data/spec/unit/network/http/api/{master → server}/v3_spec.rb +19 -19
  135. data/spec/unit/network/http/api_spec.rb +11 -11
  136. data/spec/unit/parser/compiler_spec.rb +3 -19
  137. data/spec/unit/parser/resource_spec.rb +14 -8
  138. data/spec/unit/parser/templatewrapper_spec.rb +4 -3
  139. data/spec/unit/pops/evaluator/deferred_resolver_spec.rb +20 -0
  140. data/spec/unit/pops/parser/lexer2_spec.rb +0 -4
  141. data/spec/unit/pops/validator/validator_spec.rb +20 -43
  142. data/spec/unit/property_spec.rb +1 -0
  143. data/spec/unit/provider/group/groupadd_spec.rb +5 -2
  144. data/spec/unit/provider/nameservice_spec.rb +66 -65
  145. data/spec/unit/provider/package/apt_spec.rb +28 -23
  146. data/spec/unit/provider/package/aptitude_spec.rb +1 -1
  147. data/spec/unit/provider/package/base_spec.rb +6 -5
  148. data/spec/unit/provider/package/pacman_spec.rb +18 -12
  149. data/spec/unit/provider/package/pip_spec.rb +6 -11
  150. data/spec/unit/provider/package/pkgdmg_spec.rb +0 -4
  151. data/spec/unit/provider/user/aix_spec.rb +5 -0
  152. data/spec/unit/provider/user/hpux_spec.rb +1 -1
  153. data/spec/unit/provider/user/pw_spec.rb +2 -0
  154. data/spec/unit/provider/user/useradd_spec.rb +56 -3
  155. data/spec/unit/provider_spec.rb +6 -8
  156. data/spec/unit/resource/type_spec.rb +1 -1
  157. data/spec/unit/resource_spec.rb +11 -10
  158. data/spec/unit/settings_spec.rb +13 -6
  159. data/spec/unit/ssl/base_spec.rb +0 -1
  160. data/spec/unit/ssl/certificate_request_spec.rb +4 -10
  161. data/spec/unit/ssl/ssl_provider_spec.rb +5 -2
  162. data/spec/unit/transaction/additional_resource_generator_spec.rb +3 -7
  163. data/spec/unit/transaction/event_manager_spec.rb +14 -11
  164. data/spec/unit/transaction_spec.rb +13 -4
  165. data/spec/unit/type/file/content_spec.rb +0 -1
  166. data/spec/unit/type/file/selinux_spec.rb +0 -2
  167. data/spec/unit/type/file_spec.rb +0 -6
  168. data/spec/unit/type/group_spec.rb +13 -6
  169. data/spec/unit/type/resources_spec.rb +7 -7
  170. data/spec/unit/type/service_spec.rb +1 -1
  171. data/spec/unit/type/tidy_spec.rb +0 -1
  172. data/spec/unit/type_spec.rb +2 -2
  173. data/spec/unit/util/at_fork_spec.rb +2 -2
  174. data/spec/unit/util/autoload_spec.rb +5 -1
  175. data/spec/unit/util/backups_spec.rb +1 -2
  176. data/spec/unit/util/execution_spec.rb +15 -11
  177. data/spec/unit/util/inifile_spec.rb +6 -14
  178. data/spec/unit/util/log_spec.rb +8 -7
  179. data/spec/unit/util/logging_spec.rb +3 -3
  180. data/spec/unit/util/posix_spec.rb +363 -15
  181. data/spec/unit/util/selinux_spec.rb +76 -52
  182. data/spec/unit/util/storage_spec.rb +3 -1
  183. data/spec/unit/util/suidmanager_spec.rb +44 -41
  184. data/spec/unit/util/windows/sid_spec.rb +6 -0
  185. data/spec/unit/util_spec.rb +13 -6
  186. metadata +33 -16
  187. data/spec/lib/matchers/include.rb +0 -27
  188. data/spec/lib/matchers/include_spec.rb +0 -32
  189. data/spec/unit/pops/parser/parse_application_spec.rb +0 -13
  190. data/spec/unit/pops/parser/parse_capabilities_spec.rb +0 -23
  191. data/spec/unit/pops/parser/parse_site_spec.rb +0 -43
@@ -552,7 +552,7 @@ original
552
552
 
553
553
  describe 'does support debugging' do
554
554
  before :each do
555
- allow(Facter).to receive(:respond_to?).with(:debugging).and_return(true)
555
+ allow(Facter).to receive(:respond_to?).with(:debugging, any_args).and_return(true)
556
556
  end
557
557
 
558
558
  it 'enables Facter debugging when debug level' do
@@ -568,7 +568,7 @@ original
568
568
 
569
569
  describe 'does support trace' do
570
570
  before :each do
571
- allow(Facter).to receive(:respond_to?).with(:trace).and_return(true)
571
+ allow(Facter).to receive(:respond_to?).with(:trace, any_args).and_return(true)
572
572
  end
573
573
 
574
574
  it 'enables Facter trace when enabled' do
@@ -584,7 +584,7 @@ original
584
584
 
585
585
  describe 'does support on_message' do
586
586
  before :each do
587
- allow(Facter).to receive(:respond_to?).with(:on_message).and_return(true)
587
+ allow(Facter).to receive(:respond_to?).with(:on_message, any_args).and_return(true)
588
588
  end
589
589
 
590
590
  def setup(level, message)
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'puppet/ffi/posix'
3
4
  require 'puppet/util/posix'
4
5
 
5
6
  class PosixTest
@@ -11,35 +12,344 @@ describe Puppet::Util::POSIX do
11
12
  @posix = PosixTest.new
12
13
  end
13
14
 
14
- describe '.groups_of' do
15
+ describe '.groups_of' do
16
+ let(:mock_user_data) { double(user, :gid => 1000) }
17
+
18
+ let(:ngroups_ptr) { double('FFI::MemoryPointer', :address => 0x0001, :size => 4) }
19
+ let(:groups_ptr) { double('FFI::MemoryPointer', :address => 0x0002, :size => Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS) }
20
+
15
21
  let(:mock_groups) do
16
22
  [
17
- ['group1', ['user1', 'user2']],
18
- ['group2', ['user2']],
19
- ['group1', ['user1', 'user2']],
20
- ['group3', ['user1']],
21
- ['group4', ['user2']]
22
- ].map do |(name, members)|
23
+ ['root', ['root'], 0],
24
+ ['nomembers', [], 5 ],
25
+ ['group1', ['user1', 'user2'], 1001],
26
+ ['group2', ['user2'], 2002],
27
+ ['group1', ['user1', 'user2'], 1001],
28
+ ['group3', ['user1'], 3003],
29
+ ['group4', ['user2'], 4004],
30
+ ['user1', [], 1111],
31
+ ['user2', [], 2222]
32
+ ].map do |(name, members, gid)|
23
33
  group_struct = double("Group #{name}")
24
34
  allow(group_struct).to receive(:name).and_return(name)
25
35
  allow(group_struct).to receive(:mem).and_return(members)
36
+ allow(group_struct).to receive(:gid).and_return(gid)
26
37
 
27
38
  group_struct
28
39
  end
29
40
  end
30
41
 
42
+ def prepare_user_and_groups_env(user, groups)
43
+ groups_gids = []
44
+ groups_and_user = []
45
+ groups_and_user.replace(groups)
46
+ groups_and_user.push(user)
47
+
48
+ groups_and_user.each do |group|
49
+ mock_group = mock_groups.find { |m| m.name == group }
50
+ groups_gids.push(mock_group.gid)
51
+
52
+ allow(Puppet::Etc).to receive(:getgrgid).with(mock_group.gid).and_return(mock_group)
53
+ end
54
+
55
+ if groups_and_user.size > Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS
56
+ allow(ngroups_ptr).to receive(:read_int).and_return(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS, groups_and_user.size)
57
+ else
58
+ allow(ngroups_ptr).to receive(:read_int).and_return(groups_and_user.size)
59
+ end
60
+
61
+ allow(groups_ptr).to receive(:get_array_of_uint).with(0, groups_and_user.size).and_return(groups_gids)
62
+ allow(Puppet::Etc).to receive(:getpwnam).with(user).and_return(mock_user_data)
63
+ end
64
+
31
65
  before(:each) do
32
- etc_stub = receive(:group)
33
- mock_groups.each do |mock_group|
34
- etc_stub = etc_stub.and_yield(mock_group)
66
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
67
+ end
68
+
69
+ describe 'when it uses FFI function getgrouplist' do
70
+ before(:each) do
71
+ allow(FFI::MemoryPointer).to receive(:new).with(:int).and_yield(ngroups_ptr)
72
+ allow(FFI::MemoryPointer).to receive(:new).with(:uint, Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_yield(groups_ptr)
73
+ allow(ngroups_ptr).to receive(:write_int).with(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_return(ngroups_ptr)
74
+ end
75
+
76
+ describe 'when there are groups' do
77
+ context 'for user1' do
78
+ let(:user) { 'user1' }
79
+ let(:expected_groups) { ['group1', 'group3'] }
80
+
81
+ before(:each) do
82
+ prepare_user_and_groups_env(user, expected_groups)
83
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
84
+ end
85
+
86
+ it "should return the groups for given user" do
87
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
88
+ end
89
+
90
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
91
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
92
+ Puppet::Util::POSIX.groups_of(user)
93
+ end
94
+ end
95
+
96
+ context 'for user2' do
97
+ let(:user) { 'user2' }
98
+ let(:expected_groups) { ['group1', 'group2', 'group4'] }
99
+
100
+ before(:each) do
101
+ prepare_user_and_groups_env(user, expected_groups)
102
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
103
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
104
+ end
105
+
106
+ it "should return the groups for given user" do
107
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
108
+ end
109
+
110
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
111
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
112
+ Puppet::Util::POSIX.groups_of(user)
113
+ end
114
+ end
115
+ end
116
+
117
+ describe 'when there are no groups' do
118
+ let(:user) { 'nomembers' }
119
+ let(:expected_groups) { [] }
120
+
121
+ before(:each) do
122
+ prepare_user_and_groups_env(user, expected_groups)
123
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
124
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
125
+ end
126
+
127
+ it "should return no groups for given user" do
128
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
129
+ end
130
+
131
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
132
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
133
+ Puppet::Util::POSIX.groups_of(user)
134
+ end
135
+ end
136
+
137
+ describe 'when primary group explicitly contains user' do
138
+ let(:user) { 'root' }
139
+ let(:expected_groups) { ['root'] }
140
+
141
+ before(:each) do
142
+ prepare_user_and_groups_env(user, expected_groups)
143
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
144
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
145
+ end
146
+
147
+ it "should return the groups, including primary group, for given user" do
148
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
149
+ end
150
+
151
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
152
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
153
+ Puppet::Util::POSIX.groups_of(user)
154
+ end
155
+ end
156
+
157
+ describe 'when primary group does not explicitly contain user' do
158
+ let(:user) { 'user1' }
159
+ let(:expected_groups) { ['group1', 'group3'] }
160
+
161
+ before(:each) do
162
+ prepare_user_and_groups_env(user, expected_groups)
163
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
164
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
165
+ end
166
+
167
+ it "should not return primary group for given user" do
168
+ expect(Puppet::Util::POSIX.groups_of(user)).not_to include(user)
169
+ end
170
+
171
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
172
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
173
+ Puppet::Util::POSIX.groups_of(user)
174
+ end
175
+ end
176
+
177
+ context 'number of groups' do
178
+ before(:each) do
179
+ stub_const("Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS", 2)
180
+ prepare_user_and_groups_env(user, expected_groups)
181
+
182
+ allow(FFI::MemoryPointer).to receive(:new).with(:uint, Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_yield(groups_ptr)
183
+ allow(ngroups_ptr).to receive(:write_int).with(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_return(ngroups_ptr)
184
+ end
185
+
186
+ describe 'when there are less than maximum expected number of groups' do
187
+ let(:user) { 'root' }
188
+ let(:expected_groups) { ['root'] }
189
+
190
+ before(:each) do
191
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
192
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
193
+ end
194
+
195
+ it "should return the groups for given user, after one 'getgrouplist' call" do
196
+ expect(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).once
197
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
198
+ end
199
+
200
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
201
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
202
+ Puppet::Util::POSIX.groups_of(user)
203
+ end
204
+ end
205
+
206
+ describe 'when there are more than maximum expected number of groups' do
207
+ let(:user) { 'user1' }
208
+ let(:expected_groups) { ['group1', 'group3'] }
209
+
210
+ before(:each) do
211
+ allow(FFI::MemoryPointer).to receive(:new).with(:uint, Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS * 2).and_yield(groups_ptr)
212
+ allow(ngroups_ptr).to receive(:write_int).with(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS * 2).and_return(ngroups_ptr)
213
+
214
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(true)
215
+ allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(-1, 1)
216
+ end
217
+
218
+ it "should return the groups for given user, after two 'getgrouplist' calls" do
219
+ expect(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).twice
220
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
221
+ end
222
+
223
+ it 'should not print any debug message about falling back to Puppet::Etc.group' do
224
+ expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
225
+ Puppet::Util::POSIX.groups_of(user)
226
+ end
227
+ end
35
228
  end
36
- allow(Puppet::Etc).to etc_stub
37
229
  end
38
230
 
39
- it 'returns the groups of the given user' do
40
- expect(Puppet::Util::POSIX.groups_of('user1')).to eql(
41
- ['group1', 'group3']
42
- )
231
+ describe 'when it falls back to Puppet::Etc.group method' do
232
+ before(:each) do
233
+ etc_stub = receive(:group)
234
+ mock_groups.each do |mock_group|
235
+ etc_stub = etc_stub.and_yield(mock_group)
236
+ end
237
+ allow(Puppet::Etc).to etc_stub
238
+
239
+ allow(Puppet::Etc).to receive(:getpwnam).with(user).and_raise(ArgumentError, "can't find user for #{user}")
240
+ allow(Puppet).to receive(:debug)
241
+
242
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist, any_args).and_return(false)
243
+ end
244
+
245
+ describe 'when there are groups' do
246
+ context 'for user1' do
247
+ let(:user) { 'user1' }
248
+ let(:expected_groups) { ['group1', 'group3'] }
249
+
250
+ it "should return the groups for given user" do
251
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
252
+ end
253
+
254
+ it 'logs a debug message' do
255
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
256
+ Puppet::Util::POSIX.groups_of(user)
257
+ end
258
+ end
259
+
260
+ context 'for user2' do
261
+ let(:user) { 'user2' }
262
+ let(:expected_groups) { ['group1', 'group2', 'group4'] }
263
+
264
+ it "should return the groups for given user" do
265
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
266
+ end
267
+
268
+ it 'logs a debug message' do
269
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
270
+ Puppet::Util::POSIX.groups_of(user)
271
+ end
272
+ end
273
+ end
274
+
275
+ describe 'when there are no groups' do
276
+ let(:user) { 'nomembers' }
277
+ let(:expected_groups) { [] }
278
+
279
+ it "should return no groups for given user" do
280
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
281
+ end
282
+
283
+ it 'logs a debug message' do
284
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
285
+ Puppet::Util::POSIX.groups_of(user)
286
+ end
287
+ end
288
+
289
+ describe 'when primary group explicitly contains user' do
290
+ let(:user) { 'root' }
291
+ let(:expected_groups) { ['root'] }
292
+
293
+ it "should return the groups, including primary group, for given user" do
294
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
295
+ end
296
+
297
+ it 'logs a debug message' do
298
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
299
+ Puppet::Util::POSIX.groups_of(user)
300
+ end
301
+ end
302
+
303
+ describe 'when primary group does not explicitly contain user' do
304
+ let(:user) { 'user1' }
305
+ let(:expected_groups) { ['group1', 'group3'] }
306
+
307
+ it "should not return primary group for given user" do
308
+ expect(Puppet::Util::POSIX.groups_of(user)).not_to include(user)
309
+ end
310
+
311
+ it 'logs a debug message' do
312
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
313
+ Puppet::Util::POSIX.groups_of(user)
314
+ end
315
+ end
316
+
317
+ describe "when the 'getgrouplist' method is not available" do
318
+ let(:user) { 'user1' }
319
+ let(:expected_groups) { ['group1', 'group3'] }
320
+
321
+ before(:each) do
322
+ allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist).and_return(false)
323
+ end
324
+
325
+ it "should return the groups" do
326
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
327
+ end
328
+
329
+ it 'logs a debug message' do
330
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
331
+ Puppet::Util::POSIX.groups_of(user)
332
+ end
333
+ end
334
+
335
+
336
+ describe "when ffi is not available on the machine" do
337
+ let(:user) { 'user1' }
338
+ let(:expected_groups) { ['group1', 'group3'] }
339
+
340
+ before(:each) do
341
+ allow(Puppet::Util::POSIX).to receive(:require).with('puppet/ffi/posix').and_raise(LoadError, 'cannot load such file -- ffi')
342
+ end
343
+
344
+ it "should return the groups" do
345
+ expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
346
+ end
347
+
348
+ it 'logs a debug message' do
349
+ expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: cannot load such file -- ffi")
350
+ Puppet::Util::POSIX.groups_of(user)
351
+ end
352
+ end
43
353
  end
44
354
  end
45
355
 
@@ -189,6 +499,25 @@ describe Puppet::Util::POSIX do
189
499
  expect(@posix.gid("asdf")).to eq(100)
190
500
  end
191
501
 
502
+ it "returns the id without full groups query if multiple groups have the same id" do
503
+ expect(@posix).to receive(:get_posix_field).with(:group, :gid, "asdf").and_return(100)
504
+ expect(@posix).to receive(:get_posix_field).with(:group, :name, 100).and_return("boo")
505
+ expect(@posix).to receive(:get_posix_field).with(:group, :gid, "boo").and_return(100)
506
+
507
+ expect(@posix).not_to receive(:search_posix_field)
508
+ expect(@posix.gid("asdf")).to eq(100)
509
+ end
510
+
511
+ it "returns the id with full groups query if name is nil" do
512
+ expect(@posix).to receive(:get_posix_field).with(:group, :gid, "asdf").and_return(100)
513
+ expect(@posix).to receive(:get_posix_field).with(:group, :name, 100).and_return(nil)
514
+ expect(@posix).not_to receive(:get_posix_field).with(:group, :gid, nil)
515
+
516
+
517
+ expect(@posix).to receive(:search_posix_field).with(:group, :gid, "asdf").and_return(100)
518
+ expect(@posix.gid("asdf")).to eq(100)
519
+ end
520
+
192
521
  it "should use :search_posix_field if the discovered name does not match the passed-in name" do
193
522
  expect(@posix).to receive(:get_posix_field).with(:group, :gid, "asdf").and_return(100)
194
523
  expect(@posix).to receive(:get_posix_field).with(:group, :name, 100).and_return("boo")
@@ -265,6 +594,25 @@ describe Puppet::Util::POSIX do
265
594
  expect(@posix.uid("asdf")).to eq(100)
266
595
  end
267
596
 
597
+ it "returns the id without full users query if multiple users have the same id" do
598
+ expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "asdf").and_return(100)
599
+ expect(@posix).to receive(:get_posix_field).with(:passwd, :name, 100).and_return("boo")
600
+ expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "boo").and_return(100)
601
+
602
+ expect(@posix).not_to receive(:search_posix_field)
603
+ expect(@posix.uid("asdf")).to eq(100)
604
+ end
605
+
606
+ it "returns the id with full users query if name is nil" do
607
+ expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "asdf").and_return(100)
608
+ expect(@posix).to receive(:get_posix_field).with(:passwd, :name, 100).and_return(nil)
609
+ expect(@posix).not_to receive(:get_posix_field).with(:passwd, :uid, nil)
610
+
611
+
612
+ expect(@posix).to receive(:search_posix_field).with(:passwd, :uid, "asdf").and_return(100)
613
+ expect(@posix.uid("asdf")).to eq(100)
614
+ end
615
+
268
616
  it "should use :search_posix_field if the discovered name does not match the passed-in name" do
269
617
  expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "asdf").and_return(100)
270
618
  expect(@posix).to receive(:get_posix_field).with(:passwd, :name, 100).and_return("boo")
@@ -111,15 +111,19 @@ describe Puppet::Util::SELinux do
111
111
  end
112
112
 
113
113
  it "should return a context" do
114
- expect(self).to receive(:selinux_support?).and_return(true)
115
- expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:role_r:type_t:s0"])
116
- expect(get_selinux_current_context("/foo")).to eq("user_u:role_r:type_t:s0")
114
+ without_partial_double_verification do
115
+ expect(self).to receive(:selinux_support?).and_return(true)
116
+ expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:role_r:type_t:s0"])
117
+ expect(get_selinux_current_context("/foo")).to eq("user_u:role_r:type_t:s0")
118
+ end
117
119
  end
118
120
 
119
121
  it "should return nil if lgetfilecon fails" do
120
- expect(self).to receive(:selinux_support?).and_return(true)
121
- expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return(-1)
122
- expect(get_selinux_current_context("/foo")).to be_nil
122
+ without_partial_double_verification do
123
+ expect(self).to receive(:selinux_support?).and_return(true)
124
+ expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return(-1)
125
+ expect(get_selinux_current_context("/foo")).to be_nil
126
+ end
123
127
  end
124
128
  end
125
129
 
@@ -130,47 +134,57 @@ describe Puppet::Util::SELinux do
130
134
  end
131
135
 
132
136
  it "should return a context if a default context exists" do
133
- expect(self).to receive(:selinux_support?).and_return(true)
134
- fstat = double('File::Stat', :mode => 0)
135
- expect(Puppet::FileSystem).to receive(:lstat).with('/foo').and_return(fstat)
136
- expect(self).to receive(:find_fs).with("/foo").and_return("ext3")
137
- expect(Selinux).to receive(:matchpathcon).with("/foo", 0).and_return([0, "user_u:role_r:type_t:s0"])
138
-
139
- expect(get_selinux_default_context("/foo")).to eq("user_u:role_r:type_t:s0")
137
+ without_partial_double_verification do
138
+ expect(self).to receive(:selinux_support?).and_return(true)
139
+ fstat = double('File::Stat', :mode => 0)
140
+ expect(Puppet::FileSystem).to receive(:lstat).with('/foo').and_return(fstat)
141
+ expect(self).to receive(:find_fs).with("/foo").and_return("ext3")
142
+ expect(Selinux).to receive(:matchpathcon).with("/foo", 0).and_return([0, "user_u:role_r:type_t:s0"])
143
+
144
+ expect(get_selinux_default_context("/foo")).to eq("user_u:role_r:type_t:s0")
145
+ end
140
146
  end
141
147
 
142
148
  it "handles permission denied errors by issuing a warning" do
143
- allow(self).to receive(:selinux_support?).and_return(true)
144
- allow(self).to receive(:selinux_label_support?).and_return(true)
145
- allow(Selinux).to receive(:matchpathcon).with("/root/chuj", 0).and_return(-1)
146
- allow(self).to receive(:file_lstat).with("/root/chuj").and_raise(Errno::EACCES, "/root/chuj")
149
+ without_partial_double_verification do
150
+ allow(self).to receive(:selinux_support?).and_return(true)
151
+ allow(self).to receive(:selinux_label_support?).and_return(true)
152
+ allow(Selinux).to receive(:matchpathcon).with("/root/chuj", 0).and_return(-1)
153
+ allow(self).to receive(:file_lstat).with("/root/chuj").and_raise(Errno::EACCES, "/root/chuj")
147
154
 
148
- expect(get_selinux_default_context("/root/chuj")).to be_nil
155
+ expect(get_selinux_default_context("/root/chuj")).to be_nil
156
+ end
149
157
  end
150
158
 
151
159
  it "handles no such file or directory errors by issuing a warning" do
152
- allow(self).to receive(:selinux_support?).and_return(true)
153
- allow(self).to receive(:selinux_label_support?).and_return(true)
154
- allow(Selinux).to receive(:matchpathcon).with("/root/chuj", 0).and_return(-1)
155
- allow(self).to receive(:file_lstat).with("/root/chuj").and_raise(Errno::ENOENT, "/root/chuj")
160
+ without_partial_double_verification do
161
+ allow(self).to receive(:selinux_support?).and_return(true)
162
+ allow(self).to receive(:selinux_label_support?).and_return(true)
163
+ allow(Selinux).to receive(:matchpathcon).with("/root/chuj", 0).and_return(-1)
164
+ allow(self).to receive(:file_lstat).with("/root/chuj").and_raise(Errno::ENOENT, "/root/chuj")
156
165
 
157
- expect(get_selinux_default_context("/root/chuj")).to be_nil
166
+ expect(get_selinux_default_context("/root/chuj")).to be_nil
167
+ end
158
168
  end
159
169
 
160
170
  it "should return nil if matchpathcon returns failure" do
161
- expect(self).to receive(:selinux_support?).and_return(true)
162
- fstat = double('File::Stat', :mode => 0)
163
- expect(Puppet::FileSystem).to receive(:lstat).with('/foo').and_return(fstat)
164
- expect(self).to receive(:find_fs).with("/foo").and_return("ext3")
165
- expect(Selinux).to receive(:matchpathcon).with("/foo", 0).and_return(-1)
166
-
167
- expect(get_selinux_default_context("/foo")).to be_nil
171
+ without_partial_double_verification do
172
+ expect(self).to receive(:selinux_support?).and_return(true)
173
+ fstat = double('File::Stat', :mode => 0)
174
+ expect(Puppet::FileSystem).to receive(:lstat).with('/foo').and_return(fstat)
175
+ expect(self).to receive(:find_fs).with("/foo").and_return("ext3")
176
+ expect(Selinux).to receive(:matchpathcon).with("/foo", 0).and_return(-1)
177
+
178
+ expect(get_selinux_default_context("/foo")).to be_nil
179
+ end
168
180
  end
169
181
 
170
182
  it "should return nil if selinux_label_support returns false" do
171
- expect(self).to receive(:selinux_support?).and_return(true)
172
- expect(self).to receive(:find_fs).with("/foo").and_return("nfs")
173
- expect(get_selinux_default_context("/foo")).to be_nil
183
+ without_partial_double_verification do
184
+ expect(self).to receive(:selinux_support?).and_return(true)
185
+ expect(self).to receive(:find_fs).with("/foo").and_return("nfs")
186
+ expect(get_selinux_default_context("/foo")).to be_nil
187
+ end
174
188
  end
175
189
  end
176
190
 
@@ -261,37 +275,47 @@ describe Puppet::Util::SELinux do
261
275
  end
262
276
 
263
277
  it "should use lsetfilecon to set a context" do
264
- expect(self).to receive(:selinux_support?).and_return(true)
265
- expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
266
- expect(set_selinux_context("/foo", "user_u:role_r:type_t:s0")).to be_truthy
278
+ without_partial_double_verification do
279
+ expect(self).to receive(:selinux_support?).and_return(true)
280
+ expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
281
+ expect(set_selinux_context("/foo", "user_u:role_r:type_t:s0")).to be_truthy
282
+ end
267
283
  end
268
284
 
269
285
  it "should use lsetfilecon to set user_u user context" do
270
- expect(self).to receive(:selinux_support?).and_return(true)
271
- expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "foo:role_r:type_t:s0"])
272
- expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
273
- expect(set_selinux_context("/foo", "user_u", :seluser)).to be_truthy
286
+ without_partial_double_verification do
287
+ expect(self).to receive(:selinux_support?).and_return(true)
288
+ expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "foo:role_r:type_t:s0"])
289
+ expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
290
+ expect(set_selinux_context("/foo", "user_u", :seluser)).to be_truthy
291
+ end
274
292
  end
275
293
 
276
294
  it "should use lsetfilecon to set role_r role context" do
277
- expect(self).to receive(:selinux_support?).and_return(true)
278
- expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:foo:type_t:s0"])
279
- expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
280
- expect(set_selinux_context("/foo", "role_r", :selrole)).to be_truthy
295
+ without_partial_double_verification do
296
+ expect(self).to receive(:selinux_support?).and_return(true)
297
+ expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:foo:type_t:s0"])
298
+ expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
299
+ expect(set_selinux_context("/foo", "role_r", :selrole)).to be_truthy
300
+ end
281
301
  end
282
302
 
283
303
  it "should use lsetfilecon to set type_t type context" do
284
- expect(self).to receive(:selinux_support?).and_return(true)
285
- expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:role_r:foo:s0"])
286
- expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
287
- expect(set_selinux_context("/foo", "type_t", :seltype)).to be_truthy
304
+ without_partial_double_verification do
305
+ expect(self).to receive(:selinux_support?).and_return(true)
306
+ expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:role_r:foo:s0"])
307
+ expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").and_return(0)
308
+ expect(set_selinux_context("/foo", "type_t", :seltype)).to be_truthy
309
+ end
288
310
  end
289
311
 
290
312
  it "should use lsetfilecon to set s0:c3,c5 range context" do
291
- expect(self).to receive(:selinux_support?).and_return(true)
292
- expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:role_r:type_t:s0"])
293
- expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0:c3,c5").and_return(0)
294
- expect(set_selinux_context("/foo", "s0:c3,c5", :selrange)).to be_truthy
313
+ without_partial_double_verification do
314
+ expect(self).to receive(:selinux_support?).and_return(true)
315
+ expect(Selinux).to receive(:lgetfilecon).with("/foo").and_return([0, "user_u:role_r:type_t:s0"])
316
+ expect(Selinux).to receive(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0:c3,c5").and_return(0)
317
+ expect(set_selinux_context("/foo", "s0:c3,c5", :selrange)).to be_truthy
318
+ end
295
319
  end
296
320
  end
297
321