puppet 2.7.6 → 2.7.8

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 (206) hide show
  1. data/CHANGELOG +168 -0
  2. data/conf/auth.conf +5 -4
  3. data/conf/redhat/puppet.spec +16 -1
  4. data/conf/solaris/pkginfo +2 -2
  5. data/conf/suse/puppet.spec +9 -3
  6. data/ext/upload_facts.rb +120 -0
  7. data/install.rb +11 -16
  8. data/lib/puppet.rb +1 -1
  9. data/lib/puppet/application/agent.rb +0 -3
  10. data/lib/puppet/application/apply.rb +0 -3
  11. data/lib/puppet/application/queue.rb +21 -1
  12. data/lib/puppet/defaults.rb +6 -4
  13. data/lib/puppet/face/file/store.rb +1 -1
  14. data/lib/puppet/feature/base.rb +2 -1
  15. data/lib/puppet/file_bucket/dipper.rb +3 -2
  16. data/lib/puppet/file_serving/content.rb +1 -1
  17. data/lib/puppet/file_serving/metadata.rb +5 -2
  18. data/lib/puppet/indirector/facts/inventory_service.rb +20 -0
  19. data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
  20. data/lib/puppet/indirector/report/processor.rb +1 -1
  21. data/lib/puppet/network/handler/filebucket.rb +2 -0
  22. data/lib/puppet/network/handler/fileserver.rb +1 -1
  23. data/lib/puppet/network/handler/master.rb +1 -0
  24. data/lib/puppet/network/handler/report.rb +2 -0
  25. data/lib/puppet/network/handler/runner.rb +1 -0
  26. data/lib/puppet/network/handler/status.rb +2 -0
  27. data/lib/puppet/network/http/mongrel/rest.rb +8 -1
  28. data/lib/puppet/network/http_server.rb +3 -0
  29. data/lib/puppet/network/http_server/mongrel.rb +129 -0
  30. data/lib/puppet/network/rest_authconfig.rb +12 -4
  31. data/lib/puppet/parameter.rb +18 -0
  32. data/lib/puppet/parser/compiler.rb +1 -1
  33. data/lib/puppet/parser/grammar.ra +1 -1
  34. data/lib/puppet/parser/parser.rb +360 -350
  35. data/lib/puppet/property.rb +3 -3
  36. data/lib/puppet/provider/augeas/augeas.rb +1 -1
  37. data/lib/puppet/provider/exec/windows.rb +6 -7
  38. data/lib/puppet/provider/file/windows.rb +9 -2
  39. data/lib/puppet/provider/group/aix.rb +8 -8
  40. data/lib/puppet/provider/group/groupadd.rb +1 -3
  41. data/lib/puppet/provider/group/ldap.rb +8 -10
  42. data/lib/puppet/provider/group/windows_adsi.rb +8 -2
  43. data/lib/puppet/provider/package/aix.rb +1 -1
  44. data/lib/puppet/provider/package/macports.rb +3 -3
  45. data/lib/puppet/provider/package/msi.rb +12 -5
  46. data/lib/puppet/provider/package/nim.rb +1 -1
  47. data/lib/puppet/provider/package/pkgdmg.rb +3 -3
  48. data/lib/puppet/provider/package/ports.rb +1 -1
  49. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +560 -0
  50. data/lib/puppet/provider/service/base.rb +2 -2
  51. data/lib/puppet/provider/service/bsd.rb +4 -3
  52. data/lib/puppet/provider/service/daemontools.rb +25 -25
  53. data/lib/puppet/provider/service/debian.rb +6 -4
  54. data/lib/puppet/provider/service/freebsd.rb +1 -1
  55. data/lib/puppet/provider/service/gentoo.rb +4 -3
  56. data/lib/puppet/provider/service/init.rb +3 -8
  57. data/lib/puppet/provider/service/launchd.rb +129 -96
  58. data/lib/puppet/provider/service/redhat.rb +2 -3
  59. data/lib/puppet/provider/service/runit.rb +20 -20
  60. data/lib/puppet/provider/service/smf.rb +8 -7
  61. data/lib/puppet/provider/service/src.rb +5 -6
  62. data/lib/puppet/provider/service/systemd.rb +1 -1
  63. data/lib/puppet/provider/service/upstart.rb +3 -5
  64. data/lib/puppet/provider/service/windows.rb +7 -7
  65. data/lib/puppet/provider/sshkey/parsed.rb +2 -3
  66. data/lib/puppet/provider/user/aix.rb +21 -21
  67. data/lib/puppet/provider/user/hpux.rb +3 -1
  68. data/lib/puppet/provider/user/ldap.rb +7 -7
  69. data/lib/puppet/provider/user/user_role_add.rb +10 -6
  70. data/lib/puppet/provider/user/useradd.rb +3 -1
  71. data/lib/puppet/provider/user/windows_adsi.rb +4 -3
  72. data/lib/puppet/rb_tree_map.rb +388 -0
  73. data/lib/puppet/reference/configuration.rb +7 -7
  74. data/lib/puppet/reference/indirection.rb +5 -6
  75. data/lib/puppet/reference/metaparameter.rb +3 -1
  76. data/lib/puppet/reference/network.rb +8 -8
  77. data/lib/puppet/reference/providers.rb +17 -21
  78. data/lib/puppet/reference/type.rb +12 -9
  79. data/lib/puppet/resource.rb +2 -5
  80. data/lib/puppet/resource/catalog.rb +1 -1
  81. data/lib/puppet/ssl/certificate_request.rb +70 -0
  82. data/lib/puppet/ssl/host.rb +6 -0
  83. data/lib/puppet/transaction.rb +158 -55
  84. data/lib/puppet/transaction/event_manager.rb +1 -1
  85. data/lib/puppet/type.rb +60 -30
  86. data/lib/puppet/type/augeas.rb +83 -49
  87. data/lib/puppet/type/computer.rb +1 -1
  88. data/lib/puppet/type/cron.rb +11 -11
  89. data/lib/puppet/type/exec.rb +28 -21
  90. data/lib/puppet/type/file.rb +17 -7
  91. data/lib/puppet/type/file/content.rb +2 -2
  92. data/lib/puppet/type/file/ensure.rb +15 -12
  93. data/lib/puppet/type/file/mode.rb +30 -5
  94. data/lib/puppet/type/file/source.rb +11 -10
  95. data/lib/puppet/type/file/target.rb +2 -2
  96. data/lib/puppet/type/filebucket.rb +1 -1
  97. data/lib/puppet/type/group.rb +4 -5
  98. data/lib/puppet/type/host.rb +1 -1
  99. data/lib/puppet/type/interface.rb +13 -10
  100. data/lib/puppet/type/k5login.rb +6 -6
  101. data/lib/puppet/type/macauthorization.rb +37 -36
  102. data/lib/puppet/type/maillist.rb +2 -2
  103. data/lib/puppet/type/mcx.rb +6 -6
  104. data/lib/puppet/type/mount.rb +3 -2
  105. data/lib/puppet/type/notify.rb +1 -1
  106. data/lib/puppet/type/package.rb +24 -23
  107. data/lib/puppet/type/router.rb +4 -1
  108. data/lib/puppet/type/schedule.rb +52 -44
  109. data/lib/puppet/type/scheduled_task.rb +222 -0
  110. data/lib/puppet/type/selmodule.rb +10 -6
  111. data/lib/puppet/type/service.rb +11 -11
  112. data/lib/puppet/type/ssh_authorized_key.rb +2 -5
  113. data/lib/puppet/type/sshkey.rb +1 -1
  114. data/lib/puppet/type/stage.rb +1 -1
  115. data/lib/puppet/type/tidy.rb +10 -8
  116. data/lib/puppet/type/user.rb +61 -53
  117. data/lib/puppet/type/vlan.rb +4 -4
  118. data/lib/puppet/type/whit.rb +6 -2
  119. data/lib/puppet/type/yumrepo.rb +33 -31
  120. data/lib/puppet/type/zfs.rb +34 -32
  121. data/lib/puppet/type/zone.rb +21 -19
  122. data/lib/puppet/type/zpool.rb +3 -3
  123. data/lib/puppet/util.rb +24 -6
  124. data/lib/puppet/util/adsi.rb +12 -7
  125. data/lib/puppet/util/checksums.rb +1 -1
  126. data/lib/puppet/util/diff.rb +1 -1
  127. data/lib/puppet/util/nagios_maker.rb +2 -2
  128. data/lib/puppet/util/reference.rb +16 -17
  129. data/lib/puppet/util/settings/file_setting.rb +14 -2
  130. data/lib/puppet/util/windows/security.rb +96 -32
  131. data/spec/integration/file_serving/terminus_helper_spec.rb +1 -1
  132. data/spec/integration/indirector/direct_file_server_spec.rb +9 -15
  133. data/spec/integration/indirector/file_content/file_server_spec.rb +1 -1
  134. data/spec/integration/indirector/file_metadata/file_server_spec.rb +1 -1
  135. data/spec/integration/provider/package_spec.rb +4 -0
  136. data/spec/integration/provider/service/init_spec.rb +8 -2
  137. data/spec/integration/reference/providers_spec.rb +1 -1
  138. data/spec/integration/ssl/certificate_request_spec.rb +1 -2
  139. data/spec/integration/ssl/certificate_revocation_list_spec.rb +1 -2
  140. data/spec/integration/ssl/host_spec.rb +1 -2
  141. data/spec/integration/transaction_spec.rb +25 -17
  142. data/spec/integration/type/exec_spec.rb +77 -0
  143. data/spec/integration/type/file_spec.rb +322 -2
  144. data/spec/integration/util/windows/security_spec.rb +393 -230
  145. data/spec/integration/util_spec.rb +16 -0
  146. data/spec/lib/puppet_spec/files.rb +3 -7
  147. data/spec/unit/application/apply_spec.rb +0 -9
  148. data/spec/unit/application/inspect_spec.rb +1 -0
  149. data/spec/unit/configurer/downloader_spec.rb +3 -3
  150. data/spec/unit/face/certificate_spec.rb +6 -2
  151. data/spec/unit/file_bucket/dipper_spec.rb +67 -10
  152. data/spec/unit/file_bucket/file_spec.rb +22 -28
  153. data/spec/unit/file_serving/content_spec.rb +1 -1
  154. data/spec/unit/file_serving/metadata_spec.rb +30 -3
  155. data/spec/unit/indirector/facts/inventory_service_spec.rb +22 -0
  156. data/spec/unit/indirector/file_bucket_file/file_spec.rb +21 -24
  157. data/spec/unit/indirector/node/store_configs_spec.rb +1 -0
  158. data/spec/unit/indirector/resource/ral_spec.rb +1 -1
  159. data/spec/unit/indirector/resource_type/parser_spec.rb +2 -2
  160. data/spec/unit/indirector/rest_spec.rb +1 -1
  161. data/spec/unit/network/handler/ca_spec.rb +1 -1
  162. data/spec/unit/network/http/mongrel/rest_spec.rb +54 -25
  163. data/spec/unit/parameter_spec.rb +36 -0
  164. data/spec/unit/parser/parser_spec.rb +4 -0
  165. data/spec/unit/property_spec.rb +2 -2
  166. data/spec/unit/provider/exec/windows_spec.rb +2 -8
  167. data/spec/unit/provider/file/posix_spec.rb +6 -0
  168. data/spec/unit/provider/file/windows_spec.rb +18 -0
  169. data/spec/unit/provider/group/windows_adsi_spec.rb +22 -6
  170. data/spec/unit/provider/mount/parsed_spec.rb +1 -1
  171. data/spec/unit/provider/package/msi_spec.rb +2 -2
  172. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +1571 -0
  173. data/spec/unit/provider/service/launchd_spec.rb +143 -130
  174. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +5 -0
  175. data/spec/unit/provider/user/user_role_add_spec.rb +39 -9
  176. data/spec/unit/provider/user/useradd_spec.rb +1 -1
  177. data/spec/unit/provider/user/windows_adsi_spec.rb +8 -1
  178. data/spec/unit/rb_tree_map_spec.rb +572 -0
  179. data/spec/unit/resource/catalog_spec.rb +1 -1
  180. data/spec/unit/simple_graph_spec.rb +9 -9
  181. data/spec/unit/ssl/host_spec.rb +60 -12
  182. data/spec/unit/transaction/report_spec.rb +3 -3
  183. data/spec/unit/transaction_spec.rb +394 -11
  184. data/spec/unit/type/exec_spec.rb +35 -15
  185. data/spec/unit/type/file/content_spec.rb +11 -10
  186. data/spec/unit/type/file/mode_spec.rb +73 -19
  187. data/spec/unit/type/file/source_spec.rb +1 -1
  188. data/spec/unit/type/file_spec.rb +15 -0
  189. data/spec/unit/type/group_spec.rb +1 -1
  190. data/spec/unit/type/mount_spec.rb +5 -5
  191. data/spec/unit/type/resources_spec.rb +3 -3
  192. data/spec/unit/type/scheduled_task_spec.rb +102 -0
  193. data/spec/unit/type/ssh_authorized_key_spec.rb +2 -3
  194. data/spec/unit/type/user_spec.rb +2 -1
  195. data/spec/unit/type_spec.rb +48 -4
  196. data/spec/unit/util/adsi_spec.rb +18 -7
  197. data/spec/unit/util/checksums_spec.rb +20 -2
  198. data/spec/unit/util/execution_stub_spec.rb +10 -5
  199. data/spec/unit/util/logging_spec.rb +6 -6
  200. data/spec/unit/util/rdoc/parser_spec.rb +1 -1
  201. data/spec/unit/util/reference_spec.rb +29 -0
  202. data/spec/unit/util/settings/file_setting_spec.rb +8 -2
  203. data/spec/unit/util_spec.rb +115 -0
  204. data/test/other/transactions.rb +5 -11
  205. data/test/ral/type/exec.rb +1 -1
  206. metadata +24 -11
@@ -26,335 +26,484 @@ describe "Puppet::Util::Windows::Security", :if => Puppet.features.microsoft_win
26
26
  let (:sids) { @sids }
27
27
  let (:winsec) { WindowsSecurityTester.new }
28
28
 
29
- shared_examples_for "a securable object" do
30
- describe "for a normal user" do
31
- before :each do
32
- Puppet.features.stubs(:root?).returns(false)
33
- end
29
+ shared_examples_for "only child owner" do
30
+ it "should allow child owner" do
31
+ check_child_owner
32
+ end
34
33
 
35
- after :each do
36
- winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
37
- end
34
+ it "should deny parent owner" do
35
+ lambda { check_parent_owner }.should raise_error(Errno::EACCES)
36
+ end
38
37
 
39
- describe "#owner=" do
40
- it "should allow setting to the current user" do
41
- winsec.set_owner(sids[:current_user], path)
42
- end
38
+ it "should deny group" do
39
+ lambda { check_group }.should raise_error(Errno::EACCES)
40
+ end
41
+
42
+ it "should deny other" do
43
+ lambda { check_other }.should raise_error(Errno::EACCES)
44
+ end
45
+ end
46
+
47
+ shared_examples_for "a securable object" do
48
+ describe "on a volume that doesn't support ACLs" do
49
+ [:owner, :group, :mode].each do |p|
50
+ it "should return nil #{p}" do
51
+ winsec.stubs(:supports_acl?).returns false
43
52
 
44
- it "should raise an exception when setting to a different user" do
45
- lambda { winsec.set_owner(sids[:guest], path) }.should raise_error(Puppet::Error, /This security ID may not be assigned as the owner of this object./)
53
+ winsec.send("get_#{p}", path).should be_nil
46
54
  end
47
55
  end
56
+ end
48
57
 
49
- describe "#owner" do
50
- it "it should not be empty" do
51
- winsec.get_owner(path).should_not be_empty
58
+ describe "on a volume that supports ACLs" do
59
+ describe "for a normal user" do
60
+ before :each do
61
+ Puppet.features.stubs(:root?).returns(false)
52
62
  end
53
63
 
54
- it "should raise an exception if an invalid path is provided" do
55
- lambda { winsec.get_owner("c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
64
+ after :each do
65
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU, parent)
66
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU, path) if File.exists?(path)
56
67
  end
57
- end
58
68
 
59
- describe "#group=" do
60
- it "should allow setting to a group the current owner is a member of" do
61
- winsec.set_group(sids[:users], path)
69
+ describe "#supports_acl?" do
70
+ %w[c:/ c:\\ c:/windows/system32 \\\\localhost\\C$ \\\\127.0.0.1\\C$\\foo].each do |path|
71
+ it "should accept #{path}" do
72
+ winsec.should be_supports_acl(path)
73
+ end
74
+ end
75
+
76
+ it "should raise an exception if it cannot get volume information" do
77
+ expect {
78
+ winsec.supports_acl?('foobar')
79
+ }.to raise_error(Puppet::Error, /Failed to get volume information/)
80
+ end
62
81
  end
63
82
 
64
- # Unlike unix, if the user has permission to WRITE_OWNER, which the file owner has by default,
65
- # then they can set the primary group to a group that the user does not belong to.
66
- it "should allow setting to a group the current owner is not a member of" do
67
- winsec.set_group(sids[:power_users], path)
83
+ describe "#owner=" do
84
+ it "should allow setting to the current user" do
85
+ winsec.set_owner(sids[:current_user], path)
86
+ end
87
+
88
+ it "should raise an exception when setting to a different user" do
89
+ lambda { winsec.set_owner(sids[:guest], path) }.should raise_error(Puppet::Error, /This security ID may not be assigned as the owner of this object./)
90
+ end
68
91
  end
69
- end
70
92
 
71
- describe "#group" do
72
- it "should not be empty" do
73
- winsec.get_group(path).should_not be_empty
93
+ describe "#owner" do
94
+ it "it should not be empty" do
95
+ winsec.get_owner(path).should_not be_empty
96
+ end
97
+
98
+ it "should raise an exception if an invalid path is provided" do
99
+ lambda { winsec.get_owner("c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
100
+ end
74
101
  end
75
102
 
76
- it "should raise an exception if an invalid path is provided" do
77
- lambda { winsec.get_group("c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
103
+ describe "#group=" do
104
+ it "should allow setting to a group the current owner is a member of" do
105
+ winsec.set_group(sids[:users], path)
106
+ end
107
+
108
+ # Unlike unix, if the user has permission to WRITE_OWNER, which the file owner has by default,
109
+ # then they can set the primary group to a group that the user does not belong to.
110
+ it "should allow setting to a group the current owner is not a member of" do
111
+ winsec.set_group(sids[:power_users], path)
112
+ end
78
113
  end
79
- end
80
114
 
81
- describe "#mode=" do
82
- [0000, 0100, 0200, 0300, 0400, 0500, 0600, 0700].each do |mode|
83
- it "should enforce mode #{mode.to_s(8)}" do
84
- winsec.set_mode(mode, path)
115
+ describe "#group" do
116
+ it "should not be empty" do
117
+ winsec.get_group(path).should_not be_empty
118
+ end
85
119
 
86
- check_access(mode, path)
120
+ it "should raise an exception if an invalid path is provided" do
121
+ lambda { winsec.get_group("c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
87
122
  end
88
123
  end
89
124
 
90
- it "should round-trip all 64 modes that do not require deny ACEs" do
91
- 0.upto(7).each do |u|
92
- 0.upto(u).each do |g|
93
- 0.upto(g).each do |o|
94
- # if user is superset of group, and group superset of other, then
95
- # no deny ace is required, and mode can be converted to win32
96
- # access mask, and back to mode without loss of information
97
- # (provided the owner and group are not the same)
98
- next if ((u & g) != g) or ((g & o) != o)
125
+ describe "#mode=" do
126
+ (0000..0700).step(0100).each do |mode|
127
+ it "should enforce mode #{mode.to_s(8)}" do
128
+ winsec.set_mode(mode, path)
129
+
130
+ check_access(mode, path)
131
+ end
132
+ end
99
133
 
100
- mode = (u << 6 | g << 3 | o << 0)
101
- winsec.set_mode(mode, path)
102
- winsec.get_mode(path).to_s(8).should == mode.to_s(8)
134
+ it "should round-trip all 128 modes that do not require deny ACEs" do
135
+ 0.upto(1).each do |s|
136
+ 0.upto(7).each do |u|
137
+ 0.upto(u).each do |g|
138
+ 0.upto(g).each do |o|
139
+ # if user is superset of group, and group superset of other, then
140
+ # no deny ace is required, and mode can be converted to win32
141
+ # access mask, and back to mode without loss of information
142
+ # (provided the owner and group are not the same)
143
+ next if ((u & g) != g) or ((g & o) != o)
144
+
145
+ mode = (s << 9 | u << 6 | g << 3 | o << 0)
146
+ winsec.set_mode(mode, path)
147
+ winsec.get_mode(path).to_s(8).should == mode.to_s(8)
148
+ end
149
+ end
103
150
  end
104
151
  end
105
152
  end
106
- end
107
153
 
108
- describe "for modes that require deny aces" do
109
- it "should map everyone to group and owner" do
110
- winsec.set_mode(0426, path)
111
- winsec.get_mode(path).to_s(8).should == "666"
154
+ describe "for modes that require deny aces" do
155
+ it "should map everyone to group and owner" do
156
+ winsec.set_mode(0426, path)
157
+ winsec.get_mode(path).to_s(8).should == "666"
158
+ end
159
+
160
+ it "should combine user and group modes when owner and group sids are equal" do
161
+ winsec.set_group(winsec.get_owner(path), path)
162
+
163
+ winsec.set_mode(0410, path)
164
+ winsec.get_mode(path).to_s(8).should == "550"
165
+ end
112
166
  end
113
167
 
114
- it "should combine user and group modes when owner and group sids are equal" do
115
- winsec.set_group(winsec.get_owner(path), path)
168
+ describe "for read-only objects" do
169
+ before :each do
170
+ winsec.add_attributes(path, WindowsSecurityTester::FILE_ATTRIBUTE_READONLY)
171
+ (winsec.get_attributes(path) & WindowsSecurityTester::FILE_ATTRIBUTE_READONLY).should be_nonzero
172
+ end
173
+
174
+ it "should make them writable if any sid has write permission" do
175
+ winsec.set_mode(WindowsSecurityTester::S_IWUSR, path)
176
+ (winsec.get_attributes(path) & WindowsSecurityTester::FILE_ATTRIBUTE_READONLY).should == 0
177
+ end
178
+
179
+ it "should leave them read-only if no sid has write permission" do
180
+ winsec.set_mode(WindowsSecurityTester::S_IRUSR | WindowsSecurityTester::S_IXGRP, path)
181
+ (winsec.get_attributes(path) & WindowsSecurityTester::FILE_ATTRIBUTE_READONLY).should be_nonzero
182
+ end
183
+ end
116
184
 
117
- winsec.set_mode(0410, path)
118
- winsec.get_mode(path).to_s(8).should == "550"
185
+ it "should raise an exception if an invalid path is provided" do
186
+ lambda { winsec.set_mode(sids[:guest], "c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
119
187
  end
120
188
  end
121
189
 
122
- describe "for read-only objects" do
123
- before :each do
124
- winsec.add_attributes(path, WindowsSecurityTester::FILE_ATTRIBUTE_READONLY)
125
- (winsec.get_attributes(path) & WindowsSecurityTester::FILE_ATTRIBUTE_READONLY).should be_nonzero
190
+ describe "#mode" do
191
+ it "should report when extra aces are encounted" do
192
+ winsec.set_acl(path, true) do |acl|
193
+ (544..547).each do |rid|
194
+ winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL, "S-1-5-32-#{rid}")
195
+ end
196
+ end
197
+ mode = winsec.get_mode(path)
198
+ (mode & WindowsSecurityTester::S_IEXTRA).should_not == 0
126
199
  end
127
200
 
128
- it "should make them writable if any sid has write permission" do
129
- winsec.set_mode(WindowsSecurityTester::S_IWUSR, path)
130
- (winsec.get_attributes(path) & WindowsSecurityTester::FILE_ATTRIBUTE_READONLY).should == 0
201
+ it "should warn if a deny ace is encountered" do
202
+ winsec.set_acl(path) do |acl|
203
+ winsec.add_access_denied_ace(acl, WindowsSecurityTester::FILE_GENERIC_WRITE, sids[:guest])
204
+ winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL | WindowsSecurityTester::SPECIFIC_RIGHTS_ALL, sids[:current_user])
205
+ end
206
+
207
+ Puppet.expects(:warning).with("Unsupported access control entry type: 0x1")
208
+
209
+ winsec.get_mode(path)
131
210
  end
132
211
 
133
- it "should leave them read-only if no sid has write permission" do
134
- winsec.set_mode(WindowsSecurityTester::S_IRUSR | WindowsSecurityTester::S_IXGRP, path)
135
- (winsec.get_attributes(path) & WindowsSecurityTester::FILE_ATTRIBUTE_READONLY).should be_nonzero
212
+ it "should skip inherit-only ace" do
213
+ winsec.set_acl(path) do |acl|
214
+ winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL | WindowsSecurityTester::SPECIFIC_RIGHTS_ALL, sids[:current_user])
215
+ winsec.add_access_allowed_ace(acl, WindowsSecurityTester::FILE_GENERIC_READ, Win32::Security::SID::Everyone, WindowsSecurityTester::INHERIT_ONLY_ACE | WindowsSecurityTester::OBJECT_INHERIT_ACE)
216
+ end
217
+
218
+ (winsec.get_mode(path) & WindowsSecurityTester::S_IRWXO).should == 0
219
+ end
220
+
221
+ it "should raise an exception if an invalid path is provided" do
222
+ lambda { winsec.get_mode("c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
136
223
  end
137
224
  end
138
225
 
139
- it "should raise an exception if an invalid path is provided" do
140
- lambda { winsec.set_mode(sids[:guest], "c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
226
+ describe "inherited access control entries" do
227
+ it "should be absent when the access control list is protected" do
228
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
229
+ (winsec.get_mode(path) & WindowsSecurityTester::S_IEXTRA).should == 0
230
+ end
231
+
232
+ it "should be present when the access control list is unprotected" do
233
+ # add a bunch of aces to the parent with permission to add children
234
+ allow = WindowsSecurityTester::STANDARD_RIGHTS_ALL | WindowsSecurityTester::SPECIFIC_RIGHTS_ALL
235
+ inherit = WindowsSecurityTester::OBJECT_INHERIT_ACE | WindowsSecurityTester::CONTAINER_INHERIT_ACE
236
+
237
+ winsec.set_acl(parent, true) do |acl|
238
+ winsec.add_access_allowed_ace(acl, allow, "S-1-1-0", inherit) # everyone
239
+
240
+ (544..547).each do |rid|
241
+ winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL, "S-1-5-32-#{rid}", inherit)
242
+ end
243
+ end
244
+
245
+ # unprotect child, it should inherit from parent
246
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU, path, false)
247
+ (winsec.get_mode(path) & WindowsSecurityTester::S_IEXTRA).should == WindowsSecurityTester::S_IEXTRA
248
+ end
141
249
  end
142
250
  end
143
251
 
144
- describe "#mode" do
145
- it "should report when extra aces are encounted" do
146
- winsec.set_acl(path, true) do |acl|
147
- [ 544, 545, 546, 547 ].each do |rid|
148
- winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL, "S-1-5-32-#{rid}")
149
- end
252
+ describe "for an administrator", :if => Puppet.features.root? do
253
+ before :each do
254
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU | WindowsSecurityTester::S_IRWXG, path)
255
+ winsec.set_group(sids[:guest], path)
256
+ winsec.set_owner(sids[:guest], path)
257
+ lambda { File.open(path, 'r') }.should raise_error(Errno::EACCES)
258
+ end
259
+
260
+ after :each do
261
+ if File.exists?(path)
262
+ winsec.set_owner(sids[:current_user], path)
263
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
150
264
  end
151
- mode = winsec.get_mode(path)
152
- (mode & WindowsSecurityTester::S_IEXTRA).should_not == 0
153
265
  end
154
266
 
155
- it "should warn if a deny ace is encountered" do
156
- winsec.set_acl(path) do |acl|
157
- winsec.add_access_denied_ace(acl, WindowsSecurityTester::FILE_GENERIC_WRITE, sids[:guest])
158
- winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL | WindowsSecurityTester::SPECIFIC_RIGHTS_ALL, sids[:current_user])
267
+ describe "#owner=" do
268
+ it "should accept a user sid" do
269
+ winsec.set_owner(sids[:admin], path)
270
+ winsec.get_owner(path).should == sids[:admin]
271
+ end
272
+
273
+ it "should accept a group sid" do
274
+ winsec.set_owner(sids[:power_users], path)
275
+ winsec.get_owner(path).should == sids[:power_users]
159
276
  end
160
277
 
161
- Puppet.expects(:warning).with("Unsupported access control entry type: 0x1")
278
+ it "should raise an exception if an invalid sid is provided" do
279
+ lambda { winsec.set_owner("foobar", path) }.should raise_error(Puppet::Error, /Failed to convert string SID/)
280
+ end
162
281
 
163
- winsec.get_mode(path)
282
+ it "should raise an exception if an invalid path is provided" do
283
+ lambda { winsec.set_owner(sids[:guest], "c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
284
+ end
164
285
  end
165
286
 
166
- it "should skip inherit-only ace" do
167
- winsec.set_acl(path) do |acl|
168
- winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL | WindowsSecurityTester::SPECIFIC_RIGHTS_ALL, sids[:current_user])
169
- winsec.add_access_allowed_ace(acl, WindowsSecurityTester::FILE_GENERIC_READ, Win32::Security::SID::Everyone, WindowsSecurityTester::INHERIT_ONLY_ACE | WindowsSecurityTester::OBJECT_INHERIT_ACE)
287
+ describe "#group=" do
288
+ it "should accept a group sid" do
289
+ winsec.set_group(sids[:power_users], path)
290
+ winsec.get_group(path).should == sids[:power_users]
291
+ end
292
+
293
+ it "should accept a user sid" do
294
+ winsec.set_group(sids[:admin], path)
295
+ winsec.get_group(path).should == sids[:admin]
170
296
  end
171
297
 
172
- (winsec.get_mode(path) & WindowsSecurityTester::S_IRWXO).should == 0
298
+ it "should allow owner and group to be the same sid" do
299
+ winsec.set_mode(0610, path)
300
+ winsec.set_owner(sids[:power_users], path)
301
+ winsec.set_group(sids[:power_users], path)
302
+
303
+ winsec.get_owner(path).should == sids[:power_users]
304
+ winsec.get_group(path).should == sids[:power_users]
305
+ # note group execute permission added to user ace, and then group rwx value
306
+ # reflected to match
307
+ winsec.get_mode(path).to_s(8).should == "770"
308
+ end
309
+
310
+ it "should raise an exception if an invalid sid is provided" do
311
+ lambda { winsec.set_group("foobar", path) }.should raise_error(Puppet::Error, /Failed to convert string SID/)
312
+ end
313
+
314
+ it "should raise an exception if an invalid path is provided" do
315
+ lambda { winsec.set_group(sids[:guest], "c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
316
+ end
173
317
  end
174
318
 
175
- it "should raise an exception if an invalid path is provided" do
176
- lambda { winsec.get_mode("c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
319
+ describe "when the sid is NULL" do
320
+ it "should retrieve an empty owner sid"
321
+ it "should retrieve an empty group sid"
177
322
  end
178
- end
179
323
 
180
- describe "inherited access control entries" do
181
- it "should be absent when the access control list is protected" do
182
- winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
183
- (winsec.get_mode(path) & WindowsSecurityTester::S_IEXTRA).should == 0
324
+ describe "when the sid refers to a deleted trustee" do
325
+ it "should retrieve the user sid" do
326
+ sid = nil
327
+ user = Puppet::Util::ADSI::User.create("delete_me_user")
328
+ user.commit
329
+ begin
330
+ sid = Sys::Admin::get_user(user.name).sid
331
+ winsec.set_owner(sid, path)
332
+ winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
333
+ ensure
334
+ Puppet::Util::ADSI::User.delete(user.name)
335
+ end
336
+
337
+ winsec.get_owner(path).should == sid
338
+ winsec.get_mode(path).should == WindowsSecurityTester::S_IRWXU
339
+ end
340
+
341
+ it "should retrieve the group sid" do
342
+ sid = nil
343
+ group = Puppet::Util::ADSI::Group.create("delete_me_group")
344
+ group.commit
345
+ begin
346
+ sid = Sys::Admin::get_group(group.name).sid
347
+ winsec.set_group(sid, path)
348
+ winsec.set_mode(WindowsSecurityTester::S_IRWXG, path)
349
+ ensure
350
+ Puppet::Util::ADSI::Group.delete(group.name)
351
+ end
352
+ winsec.get_group(path).should == sid
353
+ winsec.get_mode(path).should == WindowsSecurityTester::S_IRWXG
354
+ end
184
355
  end
185
356
 
186
- it "should be present when the access control list is unprotected" do
187
- dir = tmpdir('win_sec_parent')
357
+ describe "#mode" do
358
+ it "should deny all access when the DACL is empty" do
359
+ winsec.set_acl(path, true) { |acl| }
188
360
 
189
- # add a bunch of aces, make sure we can add to the directory
190
- allow = WindowsSecurityTester::STANDARD_RIGHTS_ALL | WindowsSecurityTester::SPECIFIC_RIGHTS_ALL
191
- inherit = WindowsSecurityTester::OBJECT_INHERIT_ACE | WindowsSecurityTester::CONTAINER_INHERIT_ACE
361
+ winsec.get_mode(path).should == 0
362
+ end
192
363
 
193
- winsec.set_acl(dir, true) do |acl|
194
- winsec.add_access_allowed_ace(acl, allow, "S-1-1-0", inherit) # everyone
364
+ # REMIND: ruby crashes when trying to set a NULL DACL
365
+ # it "should allow all when it is nil" do
366
+ # winsec.set_owner(sids[:current_user], path)
367
+ # winsec.open_file(path, WindowsSecurityTester::READ_CONTROL | WindowsSecurityTester::WRITE_DAC) do |handle|
368
+ # winsec.set_security_info(handle, WindowsSecurityTester::DACL_SECURITY_INFORMATION | WindowsSecurityTester::PROTECTED_DACL_SECURITY_INFORMATION, nil)
369
+ # end
370
+ # winsec.get_mode(path).to_s(8).should == "777"
371
+ # end
372
+ end
373
+
374
+ describe "#string_to_sid_ptr" do
375
+ it "should raise an error if an invalid SID is specified" do
376
+ expect do
377
+ winsec.string_to_sid_ptr('foobar')
378
+ end.to raise_error(Puppet::Util::Windows::Error) { |error| error.code.should == 1337 }
379
+ end
195
380
 
196
- [ 544, 545, 546, 547 ].each do |rid|
197
- winsec.add_access_allowed_ace(acl, WindowsSecurityTester::STANDARD_RIGHTS_ALL, "S-1-5-32-#{rid}", inherit)
381
+ it "should yield if a block is given" do
382
+ yielded = nil
383
+ winsec.string_to_sid_ptr('S-1-1-0') do |sid|
384
+ yielded = sid
198
385
  end
386
+ yielded.should_not be_nil
199
387
  end
200
388
 
201
- # add a file
202
- child = File.join(dir, "child")
203
- File.new(child, "w").close
204
-
205
- # unprotect child, it should inherit from parent
206
- winsec.set_mode(WindowsSecurityTester::S_IRWXU, child, false)
207
- (winsec.get_mode(child) & WindowsSecurityTester::S_IEXTRA).should == WindowsSecurityTester::S_IEXTRA
389
+ it "should allow no block to be specified" do
390
+ winsec.string_to_sid_ptr('S-1-1-0').should be_true
391
+ end
208
392
  end
209
- end
210
- end
211
393
 
212
- describe "for an administrator", :if => Puppet.features.root? do
213
- before :each do
214
- winsec.set_owner(sids[:guest], path)
215
- winsec.set_group(sids[:guest], path)
216
- winsec.set_mode(WindowsSecurityTester::S_IRWXU | WindowsSecurityTester::S_IRWXG, path)
217
- lambda { File.open(path, 'r') }.should raise_error(Errno::EACCES)
218
- end
394
+ describe "when the parent directory" do
395
+ before :each do
396
+ winsec.set_owner(sids[:current_user], parent)
397
+ winsec.set_owner(sids[:current_user], path)
398
+ winsec.set_mode(0777, path, false)
399
+ end
219
400
 
220
- after :each do
221
- winsec.set_owner(sids[:current_user], path)
222
- winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
223
- end
401
+ def check_child_owner
402
+ winsec.set_group(sids[:guest], parent)
403
+ winsec.set_owner(sids[:guest], parent)
224
404
 
225
- describe "#owner=" do
226
- it "should accept a user sid" do
227
- winsec.set_owner(sids[:admin], path)
228
- winsec.get_owner(path).should == sids[:admin]
229
- end
405
+ check_delete(path)
406
+ end
230
407
 
231
- it "should accept a group sid" do
232
- winsec.set_owner(sids[:power_users], path)
233
- winsec.get_owner(path).should == sids[:power_users]
234
- end
408
+ def check_parent_owner
409
+ winsec.set_group(sids[:guest], path)
410
+ winsec.set_owner(sids[:guest], path)
235
411
 
236
- it "should raise an exception if an invalid sid is provided" do
237
- lambda { winsec.set_owner("foobar", path) }.should raise_error(Puppet::Error, /Failed to convert string SID/)
412
+ check_delete(path)
238
413
  end
239
414
 
240
- it "should raise an exception if an invalid path is provided" do
241
- lambda { winsec.set_owner(sids[:guest], "c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
242
- end
243
- end
415
+ def check_group
416
+ winsec.set_group(sids[:current_user], path)
417
+ winsec.set_owner(sids[:guest], path)
244
418
 
245
- describe "#group=" do
246
- it "should accept a group sid" do
247
- winsec.set_group(sids[:power_users], path)
248
- winsec.get_group(path).should == sids[:power_users]
249
- end
419
+ winsec.set_owner(sids[:guest], parent)
250
420
 
251
- it "should accept a user sid" do
252
- winsec.set_group(sids[:admin], path)
253
- winsec.get_group(path).should == sids[:admin]
421
+ check_delete(path)
254
422
  end
255
423
 
256
- it "should allow owner and group to be the same sid" do
257
- winsec.set_owner(sids[:power_users], path)
258
- winsec.set_group(sids[:power_users], path)
259
- winsec.set_mode(0610, path)
424
+ def check_other
425
+ winsec.set_group(sids[:guest], path)
426
+ winsec.set_owner(sids[:guest], path)
260
427
 
261
- winsec.get_owner(path).should == sids[:power_users]
262
- winsec.get_group(path).should == sids[:power_users]
263
- # note group execute permission added to user ace, and then group rwx value
264
- # reflected to match
265
- winsec.get_mode(path).to_s(8).should == "770"
266
- end
428
+ winsec.set_owner(sids[:guest], parent)
267
429
 
268
- it "should raise an exception if an invalid sid is provided" do
269
- lambda { winsec.set_group("foobar", path) }.should raise_error(Puppet::Error, /Failed to convert string SID/)
430
+ check_delete(path)
270
431
  end
271
432
 
272
- it "should raise an exception if an invalid path is provided" do
273
- lambda { winsec.set_group(sids[:guest], "c:\\doesnotexist.txt") }.should raise_error(Puppet::Error, /The system cannot find the file specified./)
274
- end
275
- end
433
+ describe "is writable and executable" do
434
+ describe "and sticky bit is set" do
435
+ before :each do
436
+ winsec.set_mode(01777, parent)
437
+ end
276
438
 
277
- describe "when the sid is NULL" do
278
- it "should retrieve an empty owner sid"
279
- it "should retrieve an empty group sid"
280
- end
439
+ it "should allow child owner" do
440
+ check_child_owner
441
+ end
281
442
 
282
- describe "when the sid refers to a deleted trustee" do
283
- it "should retrieve the user sid" do
284
- sid = nil
285
- user = Puppet::Util::ADSI::User.create("delete_me_user")
286
- user.commit
287
- begin
288
- sid = Sys::Admin::get_user(user.name).sid
289
- winsec.set_owner(sid, path)
290
- winsec.set_mode(WindowsSecurityTester::S_IRWXU, path)
291
- ensure
292
- Puppet::Util::ADSI::User.delete(user.name)
293
- end
443
+ it "should allow parent owner" do
444
+ check_parent_owner
445
+ end
294
446
 
295
- winsec.get_owner(path).should == sid
296
- winsec.get_mode(path).should == WindowsSecurityTester::S_IRWXU
297
- end
447
+ it "should deny group" do
448
+ lambda { check_group }.should raise_error(Errno::EACCES)
449
+ end
298
450
 
299
- it "should retrieve the group sid" do
300
- sid = nil
301
- group = Puppet::Util::ADSI::Group.create("delete_me_group")
302
- group.commit
303
- begin
304
- sid = Sys::Admin::get_group(group.name).sid
305
- winsec.set_group(sid, path)
306
- winsec.set_mode(WindowsSecurityTester::S_IRWXG, path)
307
- ensure
308
- Puppet::Util::ADSI::Group.delete(group.name)
451
+ it "should deny other" do
452
+ lambda { check_other }.should raise_error(Errno::EACCES)
453
+ end
309
454
  end
310
- winsec.get_group(path).should == sid
311
- winsec.get_mode(path).should == WindowsSecurityTester::S_IRWXG
312
- end
313
- end
314
455
 
315
- describe "#mode" do
316
- it "should deny all access when the DACL is empty" do
317
- winsec.set_acl(path, true) { |acl| }
456
+ describe "and sticky bit is not set" do
457
+ before :each do
458
+ winsec.set_mode(0777, parent)
459
+ end
318
460
 
319
- winsec.get_mode(path).should == 0
320
- end
461
+ it "should allow child owner" do
462
+ check_child_owner
463
+ end
321
464
 
322
- # REMIND: ruby crashes when trying to set a NULL DACL
323
- # it "should allow all when it is nil" do
324
- # winsec.set_owner(sids[:current_user], path)
325
- # winsec.open_file(path, WindowsSecurityTester::READ_CONTROL | WindowsSecurityTester::WRITE_DAC) do |handle|
326
- # winsec.set_security_info(handle, WindowsSecurityTester::DACL_SECURITY_INFORMATION | WindowsSecurityTester::PROTECTED_DACL_SECURITY_INFORMATION, nil)
327
- # end
328
- # winsec.get_mode(path).to_s(8).should == "777"
329
- # end
330
- end
465
+ it "should allow parent owner" do
466
+ check_parent_owner
467
+ end
468
+
469
+ it "should allow group" do
470
+ check_group
471
+ end
331
472
 
332
- describe "#string_to_sid_ptr" do
333
- it "should raise an error if an invalid SID is specified" do
334
- expect do
335
- winsec.string_to_sid_ptr('foobar')
336
- end.to raise_error(Puppet::Util::Windows::Error) { |error| error.code.should == 1337 }
473
+ it "should allow other" do
474
+ check_other
475
+ end
476
+ end
337
477
  end
338
478
 
339
- it "should yield if a block is given" do
340
- yielded = nil
341
- winsec.string_to_sid_ptr('S-1-1-0') do |sid|
342
- yielded = sid
479
+ describe "is not writable" do
480
+ before :each do
481
+ winsec.set_mode(0555, parent)
343
482
  end
344
- yielded.should_not be_nil
483
+
484
+ it_behaves_like "only child owner"
345
485
  end
346
486
 
347
- it "should allow no block to be specified" do
348
- winsec.string_to_sid_ptr('S-1-1-0').should be_true
487
+ describe "is not executable" do
488
+ before :each do
489
+ winsec.set_mode(0666, parent)
490
+ end
491
+
492
+ it_behaves_like "only child owner"
349
493
  end
350
494
  end
351
495
  end
352
496
  end
497
+ end
353
498
 
354
499
  describe "file" do
355
- let :path do
356
- path = tmpfile('win_sec_test_file')
357
- File.new(path, "w").close
500
+ let (:parent) do
501
+ tmpdir('win_sec_test_file')
502
+ end
503
+
504
+ let (:path) do
505
+ path = File.join(parent, 'childfile')
506
+ File.new(path, 'w').close
358
507
  path
359
508
  end
360
509
 
@@ -390,6 +539,10 @@ describe "Puppet::Util::Windows::Security", :if => Puppet.features.microsoft_win
390
539
  def check_execute(path)
391
540
  Kernel.exec(path)
392
541
  end
542
+
543
+ def check_delete(path)
544
+ File.delete(path)
545
+ end
393
546
  end
394
547
 
395
548
  describe "locked files" do
@@ -410,10 +563,16 @@ describe "Puppet::Util::Windows::Security", :if => Puppet.features.microsoft_win
410
563
  end
411
564
 
412
565
  describe "directory" do
413
- let :path do
566
+ let (:parent) do
414
567
  tmpdir('win_sec_test_dir')
415
568
  end
416
569
 
570
+ let (:path) do
571
+ path = File.join(parent, 'childdir')
572
+ Dir.mkdir(path)
573
+ path
574
+ end
575
+
417
576
  it_behaves_like "a securable object" do
418
577
  def check_access(mode, path)
419
578
  if (mode & WindowsSecurityTester::S_IRUSR).nonzero?
@@ -444,7 +603,11 @@ describe "Puppet::Util::Windows::Security", :if => Puppet.features.microsoft_win
444
603
  end
445
604
 
446
605
  def check_execute(path)
447
- Dir.chdir(path) {|dir| }
606
+ Dir.chdir(path) {}
607
+ end
608
+
609
+ def check_delete(path)
610
+ Dir.rmdir(path)
448
611
  end
449
612
  end
450
613