chef 12.5.1 → 12.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -1
  3. data/README.md +6 -4
  4. data/Rakefile +1 -4
  5. data/chef-windows.gemspec +21 -0
  6. data/chef.gemspec +58 -0
  7. data/lib/chef/api_client/registration.rb +9 -4
  8. data/lib/chef/application.rb +3 -84
  9. data/lib/chef/application/apply.rb +9 -2
  10. data/lib/chef/application/client.rb +8 -3
  11. data/lib/chef/application/solo.rb +7 -1
  12. data/lib/chef/application/windows_service.rb +21 -6
  13. data/lib/chef/application/windows_service_manager.rb +2 -3
  14. data/lib/chef/audit/runner.rb +1 -0
  15. data/lib/chef/chef_class.rb +1 -11
  16. data/lib/chef/chef_fs/chef_fs_data_store.rb +181 -2
  17. data/lib/chef/chef_fs/file_system/cookbook_subdir.rb +5 -0
  18. data/lib/chef/chef_fs/file_system/file_system_entry.rb +11 -7
  19. data/lib/chef/client.rb +28 -1
  20. data/lib/chef/cookbook/cookbook_collection.rb +14 -1
  21. data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
  22. data/lib/chef/cookbook/metadata.rb +115 -9
  23. data/lib/chef/cookbook/remote_file_vendor.rb +1 -1
  24. data/lib/chef/cookbook_version.rb +6 -2
  25. data/lib/chef/data_bag.rb +1 -1
  26. data/lib/chef/data_bag_item.rb +1 -1
  27. data/lib/chef/digester.rb +5 -1
  28. data/lib/chef/dsl/chef_provisioning.rb +57 -0
  29. data/lib/chef/dsl/cheffish.rb +64 -0
  30. data/lib/chef/dsl/declare_resource.rb +108 -0
  31. data/lib/chef/dsl/platform_introspection.rb +3 -3
  32. data/lib/chef/dsl/recipe.rb +3 -73
  33. data/lib/chef/dsl/resources.rb +27 -1
  34. data/lib/chef/event_dispatch/base.rb +3 -0
  35. data/lib/chef/event_dispatch/dispatcher.rb +5 -0
  36. data/lib/chef/event_dispatch/events_output_stream.rb +8 -0
  37. data/lib/chef/exceptions.rb +21 -1
  38. data/lib/chef/file_access_control/unix.rb +12 -12
  39. data/lib/chef/file_content_management/deploy/cp.rb +2 -2
  40. data/lib/chef/file_content_management/deploy/mv_unix.rb +4 -4
  41. data/lib/chef/file_content_management/deploy/mv_windows.rb +1 -1
  42. data/lib/chef/formatters/base.rb +7 -0
  43. data/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +2 -2
  44. data/lib/chef/formatters/indentable_output_stream.rb +5 -0
  45. data/lib/chef/http.rb +19 -3
  46. data/lib/chef/http/decompressor.rb +2 -2
  47. data/lib/chef/json_compat.rb +1 -0
  48. data/lib/chef/knife.rb +16 -2
  49. data/lib/chef/knife/bootstrap.rb +55 -10
  50. data/lib/chef/knife/cookbook_site_install.rb +5 -1
  51. data/lib/chef/knife/core/bootstrap_context.rb +2 -1
  52. data/lib/chef/knife/core/node_presenter.rb +1 -1
  53. data/lib/chef/knife/ssh.rb +30 -16
  54. data/lib/chef/knife/ssl_check.rb +4 -2
  55. data/lib/chef/knife/ssl_fetch.rb +3 -2
  56. data/lib/chef/knife/status.rb +14 -1
  57. data/lib/chef/log.rb +14 -0
  58. data/lib/chef/mixin/get_source_from_package.rb +7 -2
  59. data/lib/chef/mixin/properties.rb +302 -0
  60. data/lib/chef/mixin/proxified_socket.rb +38 -0
  61. data/lib/chef/mixin/subclass_directive.rb +37 -0
  62. data/lib/chef/node.rb +13 -5
  63. data/lib/chef/platform/query_helpers.rb +14 -3
  64. data/lib/chef/platform/service_helpers.rb +20 -38
  65. data/lib/chef/policy_builder/expand_node_object.rb +3 -0
  66. data/lib/chef/policy_builder/policyfile.rb +1 -0
  67. data/lib/chef/property.rb +51 -12
  68. data/lib/chef/provider.rb +40 -35
  69. data/lib/chef/provider/deploy.rb +1 -1
  70. data/lib/chef/provider/dsc_resource.rb +54 -20
  71. data/lib/chef/provider/execute.rb +25 -4
  72. data/lib/chef/provider/group.rb +1 -1
  73. data/lib/chef/provider/lwrp_base.rb +1 -0
  74. data/lib/chef/provider/package.rb +76 -30
  75. data/lib/chef/provider/package/dpkg.rb +152 -69
  76. data/lib/chef/provider/package/openbsd.rb +6 -8
  77. data/lib/chef/provider/package/solaris.rb +2 -0
  78. data/lib/chef/provider/package/windows.rb +95 -14
  79. data/lib/chef/provider/package/windows/exe.rb +129 -0
  80. data/lib/chef/provider/package/windows/msi.rb +37 -13
  81. data/lib/chef/provider/package/windows/registry_uninstall_entry.rb +89 -0
  82. data/lib/chef/provider/package/yum.rb +13 -3
  83. data/lib/chef/provider/powershell_script.rb +3 -0
  84. data/lib/chef/provider/remote_file/cache_control_data.rb +37 -4
  85. data/lib/chef/provider/remote_file/http.rb +1 -1
  86. data/lib/chef/provider/script.rb +1 -0
  87. data/lib/chef/provider/service.rb +13 -10
  88. data/lib/chef/provider/service/solaris.rb +43 -17
  89. data/lib/chef/provider/service/upstart.rb +3 -3
  90. data/lib/chef/provider/user.rb +1 -1
  91. data/lib/chef/provider/user/dscl.rb +111 -100
  92. data/lib/chef/provider/user/windows.rb +5 -3
  93. data/lib/chef/recipe.rb +3 -5
  94. data/lib/chef/resource.rb +77 -320
  95. data/lib/chef/resource/action_class.rb +4 -0
  96. data/lib/chef/resource/dpkg_package.rb +4 -3
  97. data/lib/chef/resource/dsc_resource.rb +40 -2
  98. data/lib/chef/resource/execute.rb +9 -1
  99. data/lib/chef/resource/ksh.rb +32 -0
  100. data/lib/chef/resource/lwrp_base.rb +6 -10
  101. data/lib/chef/resource/package.rb +8 -9
  102. data/lib/chef/resource/registry_key.rb +1 -1
  103. data/lib/chef/resource/resource_notification.rb +14 -1
  104. data/lib/chef/resource/script.rb +1 -1
  105. data/lib/chef/resource/windows_package.rb +1 -1
  106. data/lib/chef/resource_builder.rb +14 -7
  107. data/lib/chef/resource_reporter.rb +6 -0
  108. data/lib/chef/resources.rb +1 -7
  109. data/lib/chef/rest.rb +1 -1
  110. data/lib/chef/run_context.rb +45 -2
  111. data/lib/chef/run_list/run_list_expansion.rb +47 -0
  112. data/lib/chef/runner.rb +25 -0
  113. data/lib/chef/search/query.rb +16 -2
  114. data/lib/chef/util/diff.rb +2 -2
  115. data/lib/chef/util/powershell/ps_credential.rb +2 -3
  116. data/lib/chef/version.rb +1 -1
  117. data/lib/chef/win32/api/file.rb +51 -1
  118. data/lib/chef/win32/file.rb +5 -0
  119. data/lib/chef/win32/file/version_info.rb +93 -0
  120. data/lib/chef/win32/mutex.rb +1 -1
  121. data/spec/data/apt/chef-integration-test2-1.0/debian/changelog +5 -0
  122. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.debhelper.log +45 -0
  123. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.substvars +1 -0
  124. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/conffiles +1 -0
  125. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/control +10 -0
  126. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/md5sums +1 -0
  127. data/spec/data/apt/chef-integration-test2-1.0/debian/compat +1 -0
  128. data/spec/data/apt/chef-integration-test2-1.0/debian/conffiles +1 -0
  129. data/spec/data/apt/chef-integration-test2-1.0/debian/control +13 -0
  130. data/spec/data/apt/chef-integration-test2-1.0/debian/copyright +34 -0
  131. data/spec/data/apt/chef-integration-test2-1.0/debian/files +1 -0
  132. data/spec/data/apt/chef-integration-test2-1.0/debian/rules +13 -0
  133. data/spec/data/apt/chef-integration-test2-1.0/debian/source/format +1 -0
  134. data/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz +0 -0
  135. data/spec/data/apt/chef-integration-test2_1.0-1.dsc +18 -0
  136. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.build +91 -0
  137. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes +31 -0
  138. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb +0 -0
  139. data/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz +0 -0
  140. data/spec/functional/application_spec.rb +1 -1
  141. data/spec/functional/audit/runner_spec.rb +4 -0
  142. data/spec/functional/knife/ssh_spec.rb +5 -5
  143. data/spec/functional/notifications_spec.rb +74 -4
  144. data/spec/functional/resource/aix_service_spec.rb +2 -2
  145. data/spec/functional/resource/dpkg_package_spec.rb +339 -0
  146. data/spec/functional/resource/ifconfig_spec.rb +3 -1
  147. data/spec/functional/resource/mount_spec.rb +5 -2
  148. data/spec/functional/resource/package_spec.rb +1 -1
  149. data/spec/functional/resource/user/windows_spec.rb +8 -0
  150. data/spec/functional/resource/windows_package_spec.rb +177 -0
  151. data/spec/functional/win32/version_info_spec.rb +50 -0
  152. data/spec/integration/client/client_spec.rb +80 -0
  153. data/spec/integration/knife/download_spec.rb +9 -0
  154. data/spec/integration/knife/upload_spec.rb +28 -1
  155. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +93 -23
  156. data/spec/integration/recipes/resource_action_spec.rb +211 -116
  157. data/spec/integration/recipes/resource_converge_if_changed_spec.rb +72 -0
  158. data/spec/integration/solo/solo_spec.rb +34 -0
  159. data/spec/spec_helper.rb +11 -1
  160. data/spec/support/platform_helpers.rb +8 -0
  161. data/spec/support/shared/integration/integration_helper.rb +6 -0
  162. data/spec/support/shared/unit/execute_resource.rb +5 -0
  163. data/spec/support/shared/unit/platform_introspector.rb +7 -0
  164. data/spec/tiny_server.rb +6 -2
  165. data/spec/unit/api_client/registration_spec.rb +5 -4
  166. data/spec/unit/application_spec.rb +1 -181
  167. data/spec/unit/chef_fs/file_system/cookbook_subdir_spec.rb +34 -0
  168. data/spec/unit/cookbook/metadata_spec.rb +122 -2
  169. data/spec/unit/http_spec.rb +102 -0
  170. data/spec/unit/knife/bootstrap_spec.rb +55 -13
  171. data/spec/unit/knife/core/bootstrap_context_spec.rb +10 -3
  172. data/spec/unit/knife/ssl_check_spec.rb +7 -3
  173. data/spec/unit/knife/ssl_fetch_spec.rb +2 -2
  174. data/spec/unit/knife/status_spec.rb +13 -13
  175. data/spec/unit/knife_spec.rb +26 -2
  176. data/spec/unit/lwrp_spec.rb +1 -1
  177. data/spec/unit/mixin/properties_spec.rb +97 -0
  178. data/spec/unit/mixin/proxified_socket_spec.rb +94 -0
  179. data/spec/unit/mixin/subclass_directive_spec.rb +45 -0
  180. data/spec/unit/node_spec.rb +9 -1
  181. data/spec/unit/policy_builder/policyfile_spec.rb +2 -0
  182. data/spec/unit/property/validation_spec.rb +14 -12
  183. data/spec/unit/property_spec.rb +56 -0
  184. data/spec/unit/provider/deploy_spec.rb +1 -1
  185. data/spec/unit/provider/dsc_resource_spec.rb +63 -24
  186. data/spec/unit/provider/execute_spec.rb +95 -28
  187. data/spec/unit/provider/package/dpkg_spec.rb +185 -96
  188. data/spec/unit/provider/package/windows/exe_spec.rb +251 -0
  189. data/spec/unit/provider/package/windows/msi_spec.rb +94 -10
  190. data/spec/unit/provider/package/windows_spec.rb +227 -26
  191. data/spec/unit/provider/package/yum_spec.rb +6 -0
  192. data/spec/unit/provider/package_spec.rb +495 -366
  193. data/spec/unit/provider/remote_file/cache_control_data_spec.rb +62 -36
  194. data/spec/unit/provider/script_spec.rb +2 -2
  195. data/spec/unit/provider/service/solaris_smf_service_spec.rb +110 -39
  196. data/spec/unit/provider/service/upstart_service_spec.rb +19 -0
  197. data/spec/unit/provider/user/dscl_spec.rb +14 -0
  198. data/spec/unit/provider/user/windows_spec.rb +2 -2
  199. data/spec/unit/provider/user_spec.rb +9 -0
  200. data/spec/unit/provider_resolver_spec.rb +6 -30
  201. data/spec/unit/recipe_spec.rb +46 -20
  202. data/spec/unit/resource/chef_gem_spec.rb +1 -1
  203. data/spec/unit/resource/dsc_resource_spec.rb +14 -3
  204. data/spec/unit/resource/ksh_spec.rb +40 -0
  205. data/spec/unit/resource/registry_key_spec.rb +2 -2
  206. data/spec/unit/resource/resource_notification_spec.rb +44 -45
  207. data/spec/unit/resource_reporter_spec.rb +7 -0
  208. data/spec/unit/resource_spec.rb +268 -253
  209. data/spec/unit/rest_spec.rb +2 -2
  210. data/spec/unit/run_list/run_list_expansion_spec.rb +18 -3
  211. data/spec/unit/search/query_spec.rb +19 -1
  212. data/spec/unit/util/powershell/ps_credential_spec.rb +8 -1
  213. data/spec/unit/windows_service_spec.rb +83 -38
  214. data/tasks/external_tests.rb +19 -9
  215. data/tasks/rspec.rb +1 -1
  216. metadata +64 -15
  217. data/spec/support/pedant/Gemfile +0 -3
  218. data/spec/support/pedant/pedant_config.rb +0 -129
  219. data/spec/support/pedant/run_pedant.rb +0 -63
  220. data/spec/support/pedant/stickywicket.pem +0 -27
  221. data/spec/unit/provider/package_spec.rbe +0 -0
@@ -30,7 +30,7 @@ class Chef
30
30
  Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart)
31
31
  end
32
32
 
33
- UPSTART_STATE_FORMAT = /\w+ \(?(\w+)\)?[\/ ](\w+)/
33
+ UPSTART_STATE_FORMAT = /\S+ \(?(start|stop)?\)? ?[\/ ](\w+)/
34
34
 
35
35
  def self.supports?(resource, action)
36
36
  Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:upstart)
@@ -224,10 +224,10 @@ class Chef
224
224
  command = "/sbin/status #{@job}"
225
225
  status = popen4(command) do |pid, stdin, stdout, stderr|
226
226
  stdout.each_line do |line|
227
- # rsyslog stop/waiting
228
227
  # service goal/state
229
228
  # OR
230
- # rsyslog (stop) waiting
229
+ # service (instance) goal/state
230
+ # OR
231
231
  # service (goal) state
232
232
  line =~ UPSTART_STATE_FORMAT
233
233
  data = Regexp.last_match
@@ -89,7 +89,7 @@ class Chef
89
89
  end
90
90
 
91
91
  def define_resource_requirements
92
- requirements.assert(:all_actions) do |a|
92
+ requirements.assert(:create, :modify, :manage, :lock, :unlock) do |a|
93
93
  a.assertion { @group_name_resolved }
94
94
  a.failure_message Chef::Exceptions::User, "Couldn't lookup integer GID for group name #{@new_resource.gid}"
95
95
  a.whyrun "group name #{@new_resource.gid} does not exist. This will cause group assignment to fail. Assuming this group will have been created previously."
@@ -44,6 +44,10 @@ class Chef
44
44
  # This provider only supports Mac OSX versions 10.7 and above
45
45
  class Dscl < Chef::Provider::User
46
46
 
47
+ attr_accessor :user_info
48
+ attr_accessor :authentication_authority
49
+ attr_accessor :password_shadow_conversion_algorithm
50
+
47
51
  provides :user, os: "darwin"
48
52
 
49
53
  def define_resource_requirements
@@ -56,19 +60,19 @@ class Chef
56
60
 
57
61
  requirements.assert(:all_actions) do |a|
58
62
  a.assertion { ::File.exists?("/usr/bin/dscl") }
59
- a.failure_message(Chef::Exceptions::User, "Cannot find binary '/usr/bin/dscl' on the system for #{@new_resource}!")
63
+ a.failure_message(Chef::Exceptions::User, "Cannot find binary '/usr/bin/dscl' on the system for #{new_resource}!")
60
64
  end
61
65
 
62
66
  requirements.assert(:all_actions) do |a|
63
67
  a.assertion { ::File.exists?("/usr/bin/plutil") }
64
- a.failure_message(Chef::Exceptions::User, "Cannot find binary '/usr/bin/plutil' on the system for #{@new_resource}!")
68
+ a.failure_message(Chef::Exceptions::User, "Cannot find binary '/usr/bin/plutil' on the system for #{new_resource}!")
65
69
  end
66
70
 
67
71
  requirements.assert(:create, :modify, :manage) do |a|
68
72
  a.assertion do
69
- if @new_resource.password && mac_osx_version_greater_than_10_7?
73
+ if new_resource.password && mac_osx_version_greater_than_10_7?
70
74
  # SALTED-SHA512 password shadow hashes are not supported on 10.8 and above.
71
- !salted_sha512?(@new_resource.password)
75
+ !salted_sha512?(new_resource.password)
72
76
  else
73
77
  true
74
78
  end
@@ -80,10 +84,10 @@ in 'password', with the associated 'salt' and 'iterations'.")
80
84
 
81
85
  requirements.assert(:create, :modify, :manage) do |a|
82
86
  a.assertion do
83
- if @new_resource.password && mac_osx_version_greater_than_10_7? && salted_sha512_pbkdf2?(@new_resource.password)
87
+ if new_resource.password && mac_osx_version_greater_than_10_7? && salted_sha512_pbkdf2?(new_resource.password)
84
88
  # salt and iterations should be specified when
85
89
  # SALTED-SHA512-PBKDF2 password shadow hash is given
86
- !@new_resource.salt.nil? && !@new_resource.iterations.nil?
90
+ !new_resource.salt.nil? && !new_resource.iterations.nil?
87
91
  else
88
92
  true
89
93
  end
@@ -94,9 +98,9 @@ in 'password', with the associated 'salt' and 'iterations'.")
94
98
 
95
99
  requirements.assert(:create, :modify, :manage) do |a|
96
100
  a.assertion do
97
- if @new_resource.password && !mac_osx_version_greater_than_10_7?
101
+ if new_resource.password && !mac_osx_version_greater_than_10_7?
98
102
  # On 10.7 SALTED-SHA512-PBKDF2 is not supported
99
- !salted_sha512_pbkdf2?(@new_resource.password)
103
+ !salted_sha512_pbkdf2?(new_resource.password)
100
104
  else
101
105
  true
102
106
  end
@@ -109,21 +113,21 @@ user password using shadow hash.")
109
113
  end
110
114
 
111
115
  def load_current_resource
112
- @current_resource = Chef::Resource::User.new(@new_resource.username)
113
- @current_resource.username(@new_resource.username)
116
+ @current_resource = Chef::Resource::User.new(new_resource.username)
117
+ current_resource.username(new_resource.username)
114
118
 
115
119
  @user_info = read_user_info
116
- if @user_info
117
- @current_resource.uid(dscl_get(@user_info, :uid))
118
- @current_resource.gid(dscl_get(@user_info, :gid))
119
- @current_resource.home(dscl_get(@user_info, :home))
120
- @current_resource.shell(dscl_get(@user_info, :shell))
121
- @current_resource.comment(dscl_get(@user_info, :comment))
122
- @authentication_authority = dscl_get(@user_info, :auth_authority)
123
-
124
- if @new_resource.password && dscl_get(@user_info, :password) == "********"
120
+ if user_info
121
+ current_resource.uid(dscl_get(user_info, :uid))
122
+ current_resource.gid(dscl_get(user_info, :gid))
123
+ current_resource.home(dscl_get(user_info, :home))
124
+ current_resource.shell(dscl_get(user_info, :shell))
125
+ current_resource.comment(dscl_get(user_info, :comment))
126
+ @authentication_authority = dscl_get(user_info, :auth_authority)
127
+
128
+ if new_resource.password && dscl_get(user_info, :password) == "********"
125
129
  # A password is set. Let's get the password information from shadow file
126
- shadow_hash_binary = dscl_get(@user_info, :shadow_hash)
130
+ shadow_hash_binary = dscl_get(user_info, :shadow_hash)
127
131
 
128
132
  # Calling shell_out directly since we want to give an input stream
129
133
  shadow_hash_xml = convert_binary_plist_to_xml(shadow_hash_binary.string)
@@ -132,26 +136,26 @@ user password using shadow hash.")
132
136
  if shadow_hash["SALTED-SHA512"]
133
137
  # Convert the shadow value from Base64 encoding to hex before consuming them
134
138
  @password_shadow_conversion_algorithm = "SALTED-SHA512"
135
- @current_resource.password(shadow_hash["SALTED-SHA512"].string.unpack('H*').first)
139
+ current_resource.password(shadow_hash["SALTED-SHA512"].string.unpack('H*').first)
136
140
  elsif shadow_hash["SALTED-SHA512-PBKDF2"]
137
141
  @password_shadow_conversion_algorithm = "SALTED-SHA512-PBKDF2"
138
142
  # Convert the entropy from Base64 encoding to hex before consuming them
139
- @current_resource.password(shadow_hash["SALTED-SHA512-PBKDF2"]["entropy"].string.unpack('H*').first)
140
- @current_resource.iterations(shadow_hash["SALTED-SHA512-PBKDF2"]["iterations"])
143
+ current_resource.password(shadow_hash["SALTED-SHA512-PBKDF2"]["entropy"].string.unpack('H*').first)
144
+ current_resource.iterations(shadow_hash["SALTED-SHA512-PBKDF2"]["iterations"])
141
145
  # Convert the salt from Base64 encoding to hex before consuming them
142
- @current_resource.salt(shadow_hash["SALTED-SHA512-PBKDF2"]["salt"].string.unpack('H*').first)
146
+ current_resource.salt(shadow_hash["SALTED-SHA512-PBKDF2"]["salt"].string.unpack('H*').first)
143
147
  else
144
148
  raise(Chef::Exceptions::User,"Unknown shadow_hash format: #{shadow_hash.keys.join(' ')}")
145
149
  end
146
150
  end
147
151
 
148
- convert_group_name if @new_resource.gid
152
+ convert_group_name if new_resource.gid
149
153
  else
150
154
  @user_exists = false
151
- Chef::Log.debug("#{@new_resource} user does not exist")
155
+ Chef::Log.debug("#{new_resource} user does not exist")
152
156
  end
153
157
 
154
- @current_resource
158
+ current_resource
155
159
  end
156
160
 
157
161
  #
@@ -190,15 +194,16 @@ user password using shadow hash.")
190
194
  # Create a user using dscl
191
195
  #
192
196
  def dscl_create_user
193
- run_dscl("create /Users/#{@new_resource.username}")
197
+ run_dscl("create /Users/#{new_resource.username}")
194
198
  end
195
199
 
196
200
  #
197
201
  # Saves the specified Chef user `comment` into RealName attribute
198
- # of Mac user.
202
+ # of Mac user. If `comment` is not specified, it takes `username` value.
199
203
  #
200
204
  def dscl_create_comment
201
- run_dscl("create /Users/#{@new_resource.username} RealName '#{@new_resource.comment}'")
205
+ comment = new_resource.comment || new_resource.username
206
+ run_dscl("create /Users/#{new_resource.username} RealName '#{comment}'")
202
207
  end
203
208
 
204
209
  #
@@ -207,13 +212,14 @@ user password using shadow hash.")
207
212
  # from 200 if `system` is set, 500 otherwise.
208
213
  #
209
214
  def dscl_set_uid
210
- @new_resource.uid(get_free_uid) if (@new_resource.uid.nil? || @new_resource.uid == '')
215
+ # XXX: mutates the new resource
216
+ new_resource.uid(get_free_uid) if (new_resource.uid.nil? || new_resource.uid == '')
211
217
 
212
- if uid_used?(@new_resource.uid)
213
- raise(Chef::Exceptions::RequestedUIDUnavailable, "uid #{@new_resource.uid} is already in use")
218
+ if uid_used?(new_resource.uid)
219
+ raise(Chef::Exceptions::RequestedUIDUnavailable, "uid #{new_resource.uid} is already in use")
214
220
  end
215
221
 
216
- run_dscl("create /Users/#{@new_resource.username} UniqueID #{@new_resource.uid}")
222
+ run_dscl("create /Users/#{new_resource.username} UniqueID #{new_resource.uid}")
217
223
  end
218
224
 
219
225
  #
@@ -222,7 +228,7 @@ user password using shadow hash.")
222
228
  #
223
229
  def get_free_uid(search_limit=1000)
224
230
  uid = nil
225
- base_uid = @new_resource.system ? 200 : 500
231
+ base_uid = new_resource.system ? 200 : 500
226
232
  next_uid_guess = base_uid
227
233
  users_uids = run_dscl("list /Users uid")
228
234
  while(next_uid_guess < search_limit + base_uid)
@@ -248,7 +254,7 @@ user password using shadow hash.")
248
254
  tmap
249
255
  end
250
256
  if uid_map[uid.to_s]
251
- unless uid_map[uid.to_s] == @new_resource.username.to_s
257
+ unless uid_map[uid.to_s] == new_resource.username.to_s
252
258
  return true
253
259
  end
254
260
  end
@@ -257,18 +263,23 @@ user password using shadow hash.")
257
263
 
258
264
  #
259
265
  # Sets the group id for the user using dscl. Fails if a group doesn't
260
- # exist on the system with given group id.
266
+ # exist on the system with given group id. If `gid` is not specified, it
267
+ # sets a default Mac user group "staff", with id 20.
261
268
  #
262
269
  def dscl_set_gid
263
- unless @new_resource.gid && @new_resource.gid.to_s.match(/^\d+$/)
270
+ if new_resource.gid.nil?
271
+ # XXX: mutates the new resource
272
+ new_resource.gid(20)
273
+ elsif !new_resource.gid.to_s.match(/^\d+$/)
264
274
  begin
265
- possible_gid = run_dscl("read /Groups/#{@new_resource.gid} PrimaryGroupID").split(" ").last
275
+ possible_gid = run_dscl("read /Groups/#{new_resource.gid} PrimaryGroupID").split(" ").last
266
276
  rescue Chef::Exceptions::DsclCommandFailed => e
267
- raise Chef::Exceptions::GroupIDNotFound.new("Group not found for #{@new_resource.gid} when creating user #{@new_resource.username}")
277
+ raise Chef::Exceptions::GroupIDNotFound.new("Group not found for #{new_resource.gid} when creating user #{new_resource.username}")
268
278
  end
269
- @new_resource.gid(possible_gid) if possible_gid && possible_gid.match(/^\d+$/)
279
+ # XXX: mutates the new resource
280
+ new_resource.gid(possible_gid) if possible_gid && possible_gid.match(/^\d+$/)
270
281
  end
271
- run_dscl("create /Users/#{@new_resource.username} PrimaryGroupID '#{@new_resource.gid}'")
282
+ run_dscl("create /Users/#{new_resource.username} PrimaryGroupID '#{new_resource.gid}'")
272
283
  end
273
284
 
274
285
  #
@@ -276,15 +287,15 @@ user password using shadow hash.")
276
287
  # directory is managed (moved / created) for the user.
277
288
  #
278
289
  def dscl_set_home
279
- if @new_resource.home.nil? || @new_resource.home.empty?
280
- run_dscl("delete /Users/#{@new_resource.username} NFSHomeDirectory")
290
+ if new_resource.home.nil? || new_resource.home.empty?
291
+ run_dscl("delete /Users/#{new_resource.username} NFSHomeDirectory")
281
292
  return
282
293
  end
283
294
 
284
- if @new_resource.supports[:manage_home]
295
+ if new_resource.supports[:manage_home]
285
296
  validate_home_dir_specification!
286
297
 
287
- if (@current_resource.home == @new_resource.home) && !new_home_exists?
298
+ if (current_resource.home == new_resource.home) && !new_home_exists?
288
299
  ditto_home
289
300
  elsif !current_home_exists? && !new_home_exists?
290
301
  ditto_home
@@ -292,49 +303,49 @@ user password using shadow hash.")
292
303
  move_home
293
304
  end
294
305
  end
295
- run_dscl("create /Users/#{@new_resource.username} NFSHomeDirectory '#{@new_resource.home}'")
306
+ run_dscl("create /Users/#{new_resource.username} NFSHomeDirectory '#{new_resource.home}'")
296
307
  end
297
308
 
298
309
  def validate_home_dir_specification!
299
- unless @new_resource.home =~ /^\//
300
- raise(Chef::Exceptions::InvalidHomeDirectory,"invalid path spec for User: '#{@new_resource.username}', home directory: '#{@new_resource.home}'")
310
+ unless new_resource.home =~ /^\//
311
+ raise(Chef::Exceptions::InvalidHomeDirectory,"invalid path spec for User: '#{new_resource.username}', home directory: '#{new_resource.home}'")
301
312
  end
302
313
  end
303
314
 
304
315
  def current_home_exists?
305
- ::File.exist?("#{@current_resource.home}")
316
+ ::File.exist?("#{current_resource.home}")
306
317
  end
307
318
 
308
319
  def new_home_exists?
309
- ::File.exist?("#{@new_resource.home}")
320
+ ::File.exist?("#{new_resource.home}")
310
321
  end
311
322
 
312
323
  def ditto_home
313
324
  skel = "/System/Library/User Template/English.lproj"
314
325
  raise(Chef::Exceptions::User,"can't find skel at: #{skel}") unless ::File.exists?(skel)
315
- shell_out! "ditto '#{skel}' '#{@new_resource.home}'"
316
- ::FileUtils.chown_R(@new_resource.username,@new_resource.gid.to_s,@new_resource.home)
326
+ shell_out! "ditto '#{skel}' '#{new_resource.home}'"
327
+ ::FileUtils.chown_R(new_resource.username,new_resource.gid.to_s,new_resource.home)
317
328
  end
318
329
 
319
330
  def move_home
320
- Chef::Log.debug("#{@new_resource} moving #{self} home from #{@current_resource.home} to #{@new_resource.home}")
331
+ Chef::Log.debug("#{new_resource} moving #{self} home from #{current_resource.home} to #{new_resource.home}")
321
332
 
322
- src = @current_resource.home
323
- FileUtils.mkdir_p(@new_resource.home)
333
+ src = current_resource.home
334
+ FileUtils.mkdir_p(new_resource.home)
324
335
  files = ::Dir.glob("#{Chef::Util::PathHelper.escape_glob(src)}/*", ::File::FNM_DOTMATCH) - ["#{src}/.","#{src}/.."]
325
- ::FileUtils.mv(files,@new_resource.home, :force => true)
336
+ ::FileUtils.mv(files,new_resource.home, :force => true)
326
337
  ::FileUtils.rmdir(src)
327
- ::FileUtils.chown_R(@new_resource.username,@new_resource.gid.to_s,@new_resource.home)
338
+ ::FileUtils.chown_R(new_resource.username,new_resource.gid.to_s,new_resource.home)
328
339
  end
329
340
 
330
341
  #
331
342
  # Sets the shell for the user using dscl.
332
343
  #
333
344
  def dscl_set_shell
334
- if @new_resource.shell || ::File.exists?("#{@new_resource.shell}")
335
- run_dscl("create /Users/#{@new_resource.username} UserShell '#{@new_resource.shell}'")
345
+ if new_resource.shell || ::File.exists?("#{new_resource.shell}")
346
+ run_dscl("create /Users/#{new_resource.username} UserShell '#{new_resource.shell}'")
336
347
  else
337
- run_dscl("create /Users/#{@new_resource.username} UserShell '/usr/bin/false'")
348
+ run_dscl("create /Users/#{new_resource.username} UserShell '/usr/bin/false'")
338
349
  end
339
350
  end
340
351
 
@@ -345,7 +356,7 @@ user password using shadow hash.")
345
356
  #
346
357
  def set_password
347
358
  # Return if there is no password to set
348
- return if @new_resource.password.nil?
359
+ return if new_resource.password.nil?
349
360
 
350
361
  shadow_info = prepare_password_shadow_info
351
362
 
@@ -355,7 +366,7 @@ user password using shadow hash.")
355
366
  :input => shadow_info.to_plist, :live_stream => shadow_info_binary)
356
367
  command.run_command
357
368
 
358
- if @user_info.nil?
369
+ if user_info.nil?
359
370
  # User is just created. read_user_info() will read the fresh information
360
371
  # for the user with a cache flush. However with experimentation we've seen
361
372
  # that dscl cache is not immediately updated after the creation of the user
@@ -365,8 +376,8 @@ user password using shadow hash.")
365
376
  end
366
377
 
367
378
  # Replace the shadow info in user's plist
368
- dscl_set(@user_info, :shadow_hash, shadow_info_binary)
369
- save_user_info(@user_info)
379
+ dscl_set(user_info, :shadow_hash, shadow_info_binary)
380
+ save_user_info(user_info)
370
381
  end
371
382
 
372
383
  #
@@ -379,12 +390,12 @@ user password using shadow hash.")
379
390
  iterations = nil
380
391
 
381
392
  if mac_osx_version_10_7?
382
- hash_value = if salted_sha512?(@new_resource.password)
383
- @new_resource.password
393
+ hash_value = if salted_sha512?(new_resource.password)
394
+ new_resource.password
384
395
  else
385
396
  # Create a random 4 byte salt
386
397
  salt = OpenSSL::Random.random_bytes(4)
387
- encoded_password = OpenSSL::Digest::SHA512.hexdigest(salt + @new_resource.password)
398
+ encoded_password = OpenSSL::Digest::SHA512.hexdigest(salt + new_resource.password)
388
399
  hash_value = salt.unpack('H*').first + encoded_password
389
400
  end
390
401
 
@@ -392,16 +403,16 @@ user password using shadow hash.")
392
403
  shadow_info["SALTED-SHA512"].string = convert_to_binary(hash_value)
393
404
  shadow_info
394
405
  else
395
- if salted_sha512_pbkdf2?(@new_resource.password)
396
- entropy = convert_to_binary(@new_resource.password)
397
- salt = convert_to_binary(@new_resource.salt)
398
- iterations = @new_resource.iterations
406
+ if salted_sha512_pbkdf2?(new_resource.password)
407
+ entropy = convert_to_binary(new_resource.password)
408
+ salt = convert_to_binary(new_resource.salt)
409
+ iterations = new_resource.iterations
399
410
  else
400
411
  salt = OpenSSL::Random.random_bytes(32)
401
- iterations = @new_resource.iterations # Use the default if not specified by the user
412
+ iterations = new_resource.iterations # Use the default if not specified by the user
402
413
 
403
414
  entropy = OpenSSL::PKCS5::pbkdf2_hmac(
404
- @new_resource.password,
415
+ new_resource.password,
405
416
  salt,
406
417
  iterations,
407
418
  128,
@@ -427,43 +438,43 @@ user password using shadow hash.")
427
438
  # and deleting home directory if needed.
428
439
  #
429
440
  def remove_user
430
- if @new_resource.supports[:manage_home]
441
+ if new_resource.supports[:manage_home]
431
442
  # Remove home directory
432
- FileUtils.rm_rf(@current_resource.home)
443
+ FileUtils.rm_rf(current_resource.home)
433
444
  end
434
445
 
435
446
  # Remove the user from its groups
436
447
  run_dscl("list /Groups").each_line do |group|
437
448
  if member_of_group?(group.chomp)
438
- run_dscl("delete /Groups/#{group.chomp} GroupMembership '#{@new_resource.username}'")
449
+ run_dscl("delete /Groups/#{group.chomp} GroupMembership '#{new_resource.username}'")
439
450
  end
440
451
  end
441
452
 
442
453
  # Remove user account
443
- run_dscl("delete /Users/#{@new_resource.username}")
454
+ run_dscl("delete /Users/#{new_resource.username}")
444
455
  end
445
456
 
446
457
  #
447
458
  # Locks the user.
448
459
  #
449
460
  def lock_user
450
- run_dscl("append /Users/#{@new_resource.username} AuthenticationAuthority ';DisabledUser;'")
461
+ run_dscl("append /Users/#{new_resource.username} AuthenticationAuthority ';DisabledUser;'")
451
462
  end
452
463
 
453
464
  #
454
465
  # Unlocks the user
455
466
  #
456
467
  def unlock_user
457
- auth_string = @authentication_authority.gsub(/AuthenticationAuthority: /,"").gsub(/;DisabledUser;/,"").strip
458
- run_dscl("create /Users/#{@new_resource.username} AuthenticationAuthority '#{auth_string}'")
468
+ auth_string = authentication_authority.gsub(/AuthenticationAuthority: /,"").gsub(/;DisabledUser;/,"").strip
469
+ run_dscl("create /Users/#{new_resource.username} AuthenticationAuthority '#{auth_string}'")
459
470
  end
460
471
 
461
472
  #
462
473
  # Returns true if the user is locked, false otherwise.
463
474
  #
464
475
  def locked?
465
- if @authentication_authority
466
- !!(@authentication_authority =~ /DisabledUser/ )
476
+ if authentication_authority
477
+ !!(authentication_authority =~ /DisabledUser/ )
467
478
  else
468
479
  false
469
480
  end
@@ -485,11 +496,11 @@ user password using shadow hash.")
485
496
  # given attribute.
486
497
  #
487
498
  def diverged?(parameter)
488
- parameter_updated?(parameter) && (not @new_resource.send(parameter).nil?)
499
+ parameter_updated?(parameter) && (not new_resource.send(parameter).nil?)
489
500
  end
490
501
 
491
502
  def parameter_updated?(parameter)
492
- not (@new_resource.send(parameter) == @current_resource.send(parameter))
503
+ not (new_resource.send(parameter) == current_resource.send(parameter))
493
504
  end
494
505
 
495
506
  #
@@ -500,11 +511,11 @@ user password using shadow hash.")
500
511
  # type of the password specified.
501
512
  #
502
513
  def diverged_password?
503
- return false if @new_resource.password.nil?
514
+ return false if new_resource.password.nil?
504
515
 
505
516
  # Dscl provider supports both plain text passwords and shadow hashes.
506
517
  if mac_osx_version_10_7?
507
- if salted_sha512?(@new_resource.password)
518
+ if salted_sha512?(new_resource.password)
508
519
  diverged?(:password)
509
520
  else
510
521
  !salted_sha512_password_match?
@@ -514,14 +525,14 @@ user password using shadow hash.")
514
525
  # will be updated when the user logs in. So it's possible that we will have
515
526
  # SALTED-SHA512 password in the current_resource. In that case we will force
516
527
  # password to be updated.
517
- return true if salted_sha512?(@current_resource.password)
528
+ return true if salted_sha512?(current_resource.password)
518
529
 
519
530
  # Some system users don't have salts; this can happen if the system is
520
531
  # upgraded and the user hasn't logged in yet. In this case, we will force
521
532
  # the password to be updated.
522
- return true if @current_resource.salt.nil?
533
+ return true if current_resource.salt.nil?
523
534
 
524
- if salted_sha512_pbkdf2?(@new_resource.password)
535
+ if salted_sha512_pbkdf2?(new_resource.password)
525
536
  diverged?(:password) || diverged?(:salt) || diverged?(:iterations)
526
537
  else
527
538
  !salted_sha512_pbkdf2_password_match?
@@ -543,7 +554,7 @@ user password using shadow hash.")
543
554
  # GroupMembership: root admin etc
544
555
  members = membership_info.split(" ")
545
556
  members.shift # Get rid of GroupMembership: string
546
- members.include?(@new_resource.username)
557
+ members.include?(new_resource.username)
547
558
  end
548
559
 
549
560
  #
@@ -577,7 +588,7 @@ user password using shadow hash.")
577
588
  shell_out("dscacheutil '-flushcache'")
578
589
 
579
590
  begin
580
- user_plist_file = "#{USER_PLIST_DIRECTORY}/#{@new_resource.username}.plist"
591
+ user_plist_file = "#{USER_PLIST_DIRECTORY}/#{new_resource.username}.plist"
581
592
  user_plist_info = run_plutil("convert xml1 -o - #{user_plist_file}")
582
593
  user_info = Plist::parse_xml(user_plist_info)
583
594
  rescue Chef::Exceptions::PlistUtilCommandFailed
@@ -591,7 +602,7 @@ user password using shadow hash.")
591
602
  # in DSCL_PROPERTY_MAP to the disk.
592
603
  #
593
604
  def save_user_info(user_info)
594
- user_plist_file = "#{USER_PLIST_DIRECTORY}/#{@new_resource.username}.plist"
605
+ user_plist_file = "#{USER_PLIST_DIRECTORY}/#{new_resource.username}.plist"
595
606
  Plist::Emit.save_plist(user_info, user_plist_file)
596
607
  run_plutil("convert binary1 #{user_plist_file}")
597
608
  end
@@ -673,9 +684,9 @@ user password using shadow hash.")
673
684
 
674
685
  def salted_sha512_password_match?
675
686
  # Salt is included in the first 4 bytes of shadow data
676
- salt = @current_resource.password.slice(0,8)
677
- shadow = OpenSSL::Digest::SHA512.hexdigest(convert_to_binary(salt) + @new_resource.password)
678
- @current_resource.password == salt + shadow
687
+ salt = current_resource.password.slice(0,8)
688
+ shadow = OpenSSL::Digest::SHA512.hexdigest(convert_to_binary(salt) + new_resource.password)
689
+ current_resource.password == salt + shadow
679
690
  end
680
691
 
681
692
  def salted_sha512_pbkdf2?(string)
@@ -683,15 +694,15 @@ user password using shadow hash.")
683
694
  end
684
695
 
685
696
  def salted_sha512_pbkdf2_password_match?
686
- salt = convert_to_binary(@current_resource.salt)
697
+ salt = convert_to_binary(current_resource.salt)
687
698
 
688
699
  OpenSSL::PKCS5::pbkdf2_hmac(
689
- @new_resource.password,
700
+ new_resource.password,
690
701
  salt,
691
- @current_resource.iterations,
702
+ current_resource.iterations,
692
703
  128,
693
704
  OpenSSL::Digest::SHA512.new
694
- ).unpack('H*').first == @current_resource.password
705
+ ).unpack('H*').first == current_resource.password
695
706
  end
696
707
 
697
708
  end