chef 15.2.20 → 15.3.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/chef.gemspec +3 -2
  4. data/lib/chef/application.rb +1 -1
  5. data/lib/chef/application/base.rb +7 -0
  6. data/lib/chef/application/client.rb +6 -2
  7. data/lib/chef/application/solo.rb +7 -1
  8. data/lib/chef/cookbook/gem_installer.rb +7 -2
  9. data/lib/chef/exceptions.rb +12 -0
  10. data/lib/chef/knife/bootstrap.rb +8 -1
  11. data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
  12. data/lib/chef/knife/bootstrap/train_connector.rb +3 -3
  13. data/lib/chef/knife/cookbook_metadata_from_file.rb +1 -1
  14. data/lib/chef/node.rb +0 -2
  15. data/lib/chef/policy_builder/expand_node_object.rb +1 -1
  16. data/lib/chef/policy_builder/policyfile.rb +4 -3
  17. data/lib/chef/provider.rb +4 -2
  18. data/lib/chef/provider/ifconfig.rb +5 -3
  19. data/lib/chef/provider/package/chocolatey.rb +12 -22
  20. data/lib/chef/provider/user.rb +1 -1
  21. data/lib/chef/provider/user/dscl.rb +2 -2
  22. data/lib/chef/provider/user/mac.rb +628 -0
  23. data/lib/chef/providers.rb +1 -0
  24. data/lib/chef/resource.rb +28 -20
  25. data/lib/chef/resource/chocolatey_feature.rb +1 -1
  26. data/lib/chef/resource/chocolatey_package.rb +2 -2
  27. data/lib/chef/resource/cron_d.rb +1 -1
  28. data/lib/chef/resource/ohai.rb +1 -1
  29. data/lib/chef/resource/resource_notification.rb +17 -13
  30. data/lib/chef/resource/ruby_block.rb +1 -1
  31. data/lib/chef/resource/service.rb +1 -1
  32. data/lib/chef/resource/user.rb +1 -0
  33. data/lib/chef/resource/user/dscl_user.rb +1 -1
  34. data/lib/chef/resource/user/mac_user.rb +119 -0
  35. data/lib/chef/resource/windows_ad_join.rb +1 -1
  36. data/lib/chef/resource_collection.rb +6 -0
  37. data/lib/chef/resources.rb +1 -0
  38. data/lib/chef/run_context.rb +61 -27
  39. data/lib/chef/runner.rb +50 -12
  40. data/lib/chef/version.rb +1 -1
  41. data/spec/functional/resource/chocolatey_package_spec.rb +19 -1
  42. data/spec/functional/resource/user/mac_user_spec.rb +207 -0
  43. data/spec/integration/client/client_spec.rb +22 -0
  44. data/spec/integration/knife/raw_spec.rb +39 -19
  45. data/spec/integration/knife/redirection_spec.rb +22 -13
  46. data/spec/integration/knife/serve_spec.rb +1 -2
  47. data/spec/integration/recipes/unified_mode_spec.rb +876 -0
  48. data/spec/spec_helper.rb +1 -0
  49. data/spec/support/platform_helpers.rb +10 -0
  50. data/spec/support/shared/integration/integration_helper.rb +1 -2
  51. data/spec/unit/application/client_spec.rb +5 -6
  52. data/spec/unit/application/solo_spec.rb +3 -8
  53. data/spec/unit/application_spec.rb +1 -1
  54. data/spec/unit/cookbook/gem_installer_spec.rb +22 -1
  55. data/spec/unit/knife/bootstrap/train_connector_spec.rb +20 -7
  56. data/spec/unit/knife/bootstrap_spec.rb +13 -5
  57. data/spec/unit/provider/ifconfig_spec.rb +11 -0
  58. data/spec/unit/provider/package/chocolatey_spec.rb +34 -30
  59. data/spec/unit/provider/user/dscl_spec.rb +1 -0
  60. data/spec/unit/provider/user/mac_spec.rb +38 -0
  61. data/spec/unit/provider/user_spec.rb +38 -22
  62. data/tasks/docs.rb +14 -10
  63. metadata +25 -41
  64. data/lib/.DS_Store +0 -0
  65. data/lib/chef/.DS_Store +0 -0
  66. data/lib/chef/dsl/.DS_Store +0 -0
  67. data/lib/chef/knife/.DS_Store +0 -0
  68. data/lib/chef/mixin/.DS_Store +0 -0
  69. data/lib/chef/provider/.DS_Store +0 -0
  70. data/lib/chef/provider/package/.DS_Store +0 -0
  71. data/lib/chef/provider/package/freebsd/.DS_Store +0 -0
  72. data/lib/chef/resource/.DS_Store +0 -0
  73. data/lib/chef/resource/file/.DS_Store +0 -0
  74. data/spec/.DS_Store +0 -0
  75. data/spec/data/.DS_Store +0 -0
  76. data/spec/data/cookbooks/.DS_Store +0 -0
  77. data/spec/data/cookbooks/java/.DS_Store +0 -0
  78. data/spec/data/cookbooks/java/files/.DS_Store +0 -0
  79. data/spec/data/mac_users/.DS_Store +0 -0
  80. data/spec/data/nodes/Tim.local.json +0 -3
  81. data/spec/data/nodes/Tims-MBP.local.json +0 -3
  82. data/spec/data/run_context/.DS_Store +0 -0
  83. data/spec/data/run_context/cookbooks/.DS_Store +0 -0
  84. data/spec/functional/.DS_Store +0 -0
  85. data/spec/functional/resource/.DS_Store +0 -0
  86. data/spec/functional/util/.DS_Store +0 -0
  87. data/spec/integration/.DS_Store +0 -0
  88. data/spec/stress/.DS_Store +0 -0
  89. data/spec/support/.DS_Store +0 -0
  90. data/spec/support/shared/integration/app_server_support.rb +0 -39
  91. data/spec/unit/.DS_Store +0 -0
  92. data/tasks/.DS_Store +0 -0
@@ -107,6 +107,7 @@ require_relative "provider/service/aix"
107
107
  require_relative "provider/user/aix"
108
108
  require_relative "provider/user/dscl"
109
109
  require_relative "provider/user/linux"
110
+ require_relative "provider/user/mac"
110
111
  require_relative "provider/user/pw"
111
112
  require_relative "provider/user/solaris"
112
113
  require_relative "provider/user/windows"
@@ -182,7 +182,7 @@ class Chef
182
182
  { action: { kind_of: Symbol, equal_to: allowed_actions } }
183
183
  )
184
184
  # the resource effectively sends a delayed notification to itself
185
- run_context.add_delayed_action(Notification.new(self, action, self))
185
+ run_context.add_delayed_action(Notification.new(self, action, self, run_context.unified_mode))
186
186
  end
187
187
  end
188
188
 
@@ -453,7 +453,6 @@ class Chef
453
453
  #
454
454
  attr_reader :elapsed_time
455
455
 
456
- #
457
456
  # @return [Boolean] If the resource was executed by the runner
458
457
  #
459
458
  attr_accessor :executed_by_runner
@@ -985,6 +984,16 @@ class Chef
985
984
  resource_name automatic_name
986
985
  end
987
986
 
987
+ # If the resource's action should run in separated compile/converge mode.
988
+ #
989
+ # @param flag [Boolean] value to set unified_mode to
990
+ # @return [Boolean] unified_mode value
991
+ def self.unified_mode(flag = nil)
992
+ @unified_mode = Chef::Config[:resource_unified_mode_default] if @unified_mode.nil?
993
+ @unified_mode = flag unless flag.nil?
994
+ !!@unified_mode
995
+ end
996
+
988
997
  #
989
998
  # The list of allowed actions for the resource.
990
999
  #
@@ -1038,7 +1047,6 @@ class Chef
1038
1047
  default_action action_name
1039
1048
  end
1040
1049
 
1041
- #
1042
1050
  # Define an action on this resource.
1043
1051
  #
1044
1052
  # The action is defined as a *recipe* block that will be compiled and then
@@ -1076,7 +1084,6 @@ class Chef
1076
1084
  default_action action if Array(default_action) == [:nothing]
1077
1085
  end
1078
1086
 
1079
- #
1080
1087
  # Define a method to load up this resource's properties with the current
1081
1088
  # actual values.
1082
1089
  #
@@ -1087,7 +1094,6 @@ class Chef
1087
1094
  define_method(:load_current_value!, &load_block)
1088
1095
  end
1089
1096
 
1090
- #
1091
1097
  # Call this in `load_current_value` to indicate that the value does not
1092
1098
  # exist and that `current_resource` should therefore be `nil`.
1093
1099
  #
@@ -1097,7 +1103,6 @@ class Chef
1097
1103
  raise Chef::Exceptions::CurrentValueDoesNotExist
1098
1104
  end
1099
1105
 
1100
- #
1101
1106
  # Get the current actual value of this resource.
1102
1107
  #
1103
1108
  # This does not cache--a new value will be returned each time.
@@ -1154,7 +1159,6 @@ class Chef
1154
1159
  end
1155
1160
  end
1156
1161
 
1157
- #
1158
1162
  # Ensure the action class actually gets created. This is called
1159
1163
  # when the user does `action :x do ... end`.
1160
1164
  #
@@ -1211,22 +1215,27 @@ class Chef
1211
1215
  # @return [Chef::RunContext] The run context for this Resource. This is
1212
1216
  # where the context for the current Chef run is stored, including the node
1213
1217
  # and the resource collection.
1218
+ #
1214
1219
  attr_accessor :run_context
1215
1220
 
1216
1221
  # @return [Mixlib::Log::Child] The logger for this resources. This is a child
1217
1222
  # of the run context's logger, if one exists.
1223
+ #
1218
1224
  attr_reader :logger
1219
1225
 
1220
1226
  # @return [String] The cookbook this resource was declared in.
1227
+ #
1221
1228
  attr_accessor :cookbook_name
1222
1229
 
1223
1230
  # @return [String] The recipe this resource was declared in.
1231
+ #
1224
1232
  attr_accessor :recipe_name
1225
1233
 
1226
1234
  # @return [Chef::Provider] The provider this resource was declared in (if
1227
1235
  # it was declared in an LWRP). When you call methods that do not exist
1228
1236
  # on this Resource, Chef will try to call the method on the provider
1229
1237
  # as well before giving up.
1238
+ #
1230
1239
  attr_accessor :enclosing_provider
1231
1240
 
1232
1241
  # @return [String] The source line where this resource was declared.
@@ -1234,6 +1243,7 @@ class Chef
1234
1243
  # of these formats:
1235
1244
  # /some/path/to/file.rb:80:in `wombat_tears'
1236
1245
  # C:/some/path/to/file.rb:80 in 1`wombat_tears'
1246
+ #
1237
1247
  attr_accessor :source_line
1238
1248
 
1239
1249
  # @return [String] The actual name that was used to create this resource.
@@ -1242,37 +1252,40 @@ class Chef
1242
1252
  # user will expect to see the thing they wrote, not the type that was
1243
1253
  # returned. May be `nil`, in which case callers should read #resource_name.
1244
1254
  # See #declared_key.
1255
+ #
1245
1256
  attr_accessor :declared_type
1246
1257
 
1247
- #
1248
1258
  # Iterates over all immediate and delayed notifications, calling
1249
1259
  # resolve_resource_reference on each in turn, causing them to
1250
1260
  # resolve lazy/forward references.
1251
- def resolve_notification_references
1261
+ #
1262
+ def resolve_notification_references(always_raise = false)
1252
1263
  run_context.before_notifications(self).each do |n|
1253
- n.resolve_resource_reference(run_context.resource_collection)
1264
+ n.resolve_resource_reference(run_context.resource_collection, true)
1254
1265
  end
1266
+
1255
1267
  run_context.immediate_notifications(self).each do |n|
1256
- n.resolve_resource_reference(run_context.resource_collection)
1268
+ n.resolve_resource_reference(run_context.resource_collection, always_raise)
1257
1269
  end
1270
+
1258
1271
  run_context.delayed_notifications(self).each do |n|
1259
- n.resolve_resource_reference(run_context.resource_collection)
1272
+ n.resolve_resource_reference(run_context.resource_collection, always_raise)
1260
1273
  end
1261
1274
  end
1262
1275
 
1263
1276
  # Helper for #notifies
1264
1277
  def notifies_before(action, resource_spec)
1265
- run_context.notifies_before(Notification.new(resource_spec, action, self))
1278
+ run_context.notifies_before(Notification.new(resource_spec, action, self, run_context.unified_mode))
1266
1279
  end
1267
1280
 
1268
1281
  # Helper for #notifies
1269
1282
  def notifies_immediately(action, resource_spec)
1270
- run_context.notifies_immediately(Notification.new(resource_spec, action, self))
1283
+ run_context.notifies_immediately(Notification.new(resource_spec, action, self, run_context.unified_mode))
1271
1284
  end
1272
1285
 
1273
1286
  # Helper for #notifies
1274
1287
  def notifies_delayed(action, resource_spec)
1275
- run_context.notifies_delayed(Notification.new(resource_spec, action, self))
1288
+ run_context.notifies_delayed(Notification.new(resource_spec, action, self, run_context.unified_mode))
1276
1289
  end
1277
1290
 
1278
1291
  class << self
@@ -1321,7 +1334,6 @@ class Chef
1321
1334
  end
1322
1335
  end
1323
1336
 
1324
- #
1325
1337
  # This API can be used for backcompat to do:
1326
1338
  #
1327
1339
  # chef_version_for_provides "< 14.0" if defined?(:chef_version_for_provides)
@@ -1343,7 +1355,6 @@ class Chef
1343
1355
  @chef_version_for_provides = constraint
1344
1356
  end
1345
1357
 
1346
- #
1347
1358
  # Mark this resource as providing particular DSL.
1348
1359
  #
1349
1360
  # Resources have an automatic DSL based on their resource_name, equivalent to
@@ -1472,7 +1483,6 @@ class Chef
1472
1483
  @default_description
1473
1484
  end
1474
1485
 
1475
- #
1476
1486
  # The cookbook in which this Resource was defined (if any).
1477
1487
  #
1478
1488
  # @return Chef::CookbookVersion The cookbook in which this Resource was defined.
@@ -1498,7 +1508,6 @@ class Chef
1498
1508
  provider
1499
1509
  end
1500
1510
 
1501
- #
1502
1511
  # Preface an exception message with generic Resource information.
1503
1512
  #
1504
1513
  # @param e [StandardError] An exception with `e.message`
@@ -1554,7 +1563,6 @@ class Chef
1554
1563
  klass
1555
1564
  end
1556
1565
 
1557
- #
1558
1566
  # Returns the class with the given resource_name.
1559
1567
  #
1560
1568
  # NOTE: Chef::Resource.resource_matching_short_name(:package) returns
@@ -25,7 +25,7 @@ class Chef
25
25
  property :feature_name, String, name_property: true,
26
26
  description: "The name of the Chocolatey feature to enable or disable."
27
27
 
28
- property :feature_state, [TrueClass, FalseClass], default: false
28
+ property :feature_state, [TrueClass, FalseClass], default: false, skip_docs: true
29
29
 
30
30
  load_current_value do
31
31
  current_state = fetch_feature_element(feature_name)
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # Author:: Adam Jacob (<adam@chef.io>)
3
- # Copyright:: Copyright 2008-2017, Chef Software Inc.
3
+ # Copyright:: Copyright 2008-2019, Chef Software Inc.
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,7 +30,7 @@ class Chef
30
30
  allowed_actions :install, :upgrade, :remove, :purge, :reconfig
31
31
 
32
32
  # windows can't take Array options yet
33
- property :options, String,
33
+ property :options, [String, Array],
34
34
  description: "One (or more) additional options that are passed to the command."
35
35
 
36
36
  property :package_name, [String, Array],
@@ -111,7 +111,7 @@ class Chef
111
111
  }
112
112
 
113
113
  property :hour, [Integer, String],
114
- description: "The hour at which the cron entry should run (0 - 23).",
114
+ description: "The hour at which the cron entry is to run (0 - 23).",
115
115
  default: "*", callbacks: {
116
116
  "should be a valid hour spec" => ->(spec) { validate_numeric(spec, 0, 23) },
117
117
  }
@@ -29,7 +29,7 @@ class Chef
29
29
  description "Use the ohai resource to reload the Ohai configuration on a node. This allows recipes that change system attributes (like a recipe that adds a user) to refer to those attributes later on during the #{Chef::Dist::CLIENT} run."
30
30
 
31
31
  property :plugin, String,
32
- description: "The name of an Ohai plugin to be reloaded. If this property is not specified, the #{Chef::Dist::CLIENT} will reload all plugins."
32
+ description: "The name of an Ohai plugin to be reloaded. If this property is not specified, #{Chef::Dist::PRODUCT} will reload all plugins."
33
33
 
34
34
  default_action :reload
35
35
  allowed_actions :reload
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # Author:: Tyler Ball (<tball@chef.io>)
3
- # Copyright:: Copyright 2014-2016, Chef Software, Inc.
3
+ # Copyright:: Copyright 2014-2019, Chef Software Inc.
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,12 +26,13 @@ class Chef
26
26
  # @attr [Resource] notifying_resource the Chef resource performing the notification
27
27
  class Notification
28
28
 
29
- attr_accessor :resource, :action, :notifying_resource
29
+ attr_accessor :resource, :action, :notifying_resource, :unified_mode
30
30
 
31
- def initialize(resource, action, notifying_resource)
31
+ def initialize(resource, action, notifying_resource, unified_mode = false)
32
32
  @resource = resource
33
33
  @action = action&.to_sym
34
34
  @notifying_resource = notifying_resource
35
+ @unified_mode = unified_mode
35
36
  end
36
37
 
37
38
  # Is the current notification a duplicate of another notification
@@ -52,11 +53,11 @@ class Chef
52
53
  # @param [ResourceCollection] resource_collection
53
54
  #
54
55
  # @return [void]
55
- def resolve_resource_reference(resource_collection)
56
+ def resolve_resource_reference(resource_collection, always_raise = false)
56
57
  return resource if resource.is_a?(Chef::Resource) && notifying_resource.is_a?(Chef::Resource)
57
58
 
58
59
  unless resource.is_a?(Chef::Resource)
59
- fix_resource_reference(resource_collection)
60
+ fix_resource_reference(resource_collection, always_raise)
60
61
  end
61
62
 
62
63
  unless notifying_resource.is_a?(Chef::Resource)
@@ -69,7 +70,7 @@ class Chef
69
70
  # @param [ResourceCollection] resource_collection
70
71
  #
71
72
  # @return [void]
72
- def fix_resource_reference(resource_collection)
73
+ def fix_resource_reference(resource_collection, always_raise = false)
73
74
  matching_resource = resource_collection.find(resource)
74
75
  if Array(matching_resource).size > 1
75
76
  msg = "Notification #{self} from #{notifying_resource} was created with a reference to multiple resources, "\
@@ -79,13 +80,16 @@ class Chef
79
80
  self.resource = matching_resource
80
81
 
81
82
  rescue Chef::Exceptions::ResourceNotFound => e
82
- err = Chef::Exceptions::ResourceNotFound.new(<<~FAIL)
83
- resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
84
- but #{resource} cannot be found in the resource collection. #{notifying_resource} is defined in \
85
- #{notifying_resource.source_line}
86
- FAIL
87
- err.set_backtrace(e.backtrace)
88
- raise err
83
+ # in unified mode we allow lazy notifications to resources not yet declared
84
+ if !unified_mode || always_raise
85
+ err = Chef::Exceptions::ResourceNotFound.new(<<~FAIL)
86
+ resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
87
+ but #{resource} cannot be found in the resource collection. #{notifying_resource} is defined in \
88
+ #{notifying_resource.source_line}
89
+ FAIL
90
+ err.set_backtrace(e.backtrace)
91
+ raise err
92
+ end
89
93
  rescue Chef::Exceptions::InvalidResourceSpecification => e
90
94
  err = Chef::Exceptions::InvalidResourceSpecification.new(<<~F)
91
95
  Resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
@@ -26,7 +26,7 @@ class Chef
26
26
  class RubyBlock < Chef::Resource
27
27
  provides :ruby_block, target_mode: true
28
28
 
29
- description "Use the ruby_block resource to execute Ruby code during a #{Chef::Dist::CLIENT} run."\
29
+ description "Use the ruby_block resource to execute Ruby code during a #{Chef::Dist::PRODUCT} run."\
30
30
  " Ruby code in the ruby_block resource is evaluated with other resources during"\
31
31
  " convergence, whereas Ruby code outside of a ruby_block resource is evaluated"\
32
32
  " before other resources, as the recipe is compiled."
@@ -35,7 +35,7 @@ class Chef
35
35
 
36
36
  # this is a poor API please do not re-use this pattern
37
37
  property :supports, Hash, default: { restart: nil, reload: nil, status: nil },
38
- description: "A list of properties that controls how the #{Chef::Dist::CLIENT} is to attempt to manage a service: :restart, :reload, :status. For :restart, the init script or other service provider can use a restart command; if :restart is not specified, the #{Chef::Dist::CLIENT} attempts to stop and then start a service. For :reload, the init script or other service provider can use a reload command. For :status, the init script or other service provider can use a status command to determine if the service is running; if :status is not specified, the #{Chef::Dist::CLIENT} attempts to match the service_name against the process table as a regular expression, unless a pattern is specified as a parameter property. Default value: { restart: false, reload: false, status: false } for all platforms (except for the Red Hat platform family, which defaults to { restart: false, reload: false, status: true }.)",
38
+ description: "A list of properties that controls how #{Chef::Dist::PRODUCT} is to attempt to manage a service: :restart, :reload, :status. For :restart, the init script or other service provider can use a restart command; if :restart is not specified, the #{Chef::Dist::CLIENT} attempts to stop and then start a service. For :reload, the init script or other service provider can use a reload command. For :status, the init script or other service provider can use a status command to determine if the service is running; if :status is not specified, the #{Chef::Dist::CLIENT} attempts to match the service_name against the process table as a regular expression, unless a pattern is specified as a parameter property. Default value: { restart: false, reload: false, status: false } for all platforms (except for the Red Hat platform family, which defaults to { restart: false, reload: false, status: true }.)",
39
39
  coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
40
40
 
41
41
  property :service_name, String,
@@ -47,6 +47,7 @@ class Chef
47
47
 
48
48
  property :password, String,
49
49
  description: "The password shadow hash",
50
+ sensitive: true,
50
51
  desired_state: false
51
52
 
52
53
  property :non_unique, [ TrueClass, FalseClass ],
@@ -24,7 +24,7 @@ class Chef
24
24
  resource_name :dscl_user
25
25
 
26
26
  provides :dscl_user
27
- provides :user, os: "darwin"
27
+ provides :user, platform: "mac_os_x", platform_version: "< 10.14"
28
28
 
29
29
  property :iterations, Integer,
30
30
  description: "macOS platform only. The number of iterations for a password with a SALTED-SHA512-PBKDF2 shadow hash.",
@@ -0,0 +1,119 @@
1
+ #
2
+ # Author:: Ryan Cragun (<ryan@chef.io>)
3
+ # Copyright:: Copyright 2019, Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require_relative "../user"
20
+
21
+ class Chef
22
+ class Resource
23
+ class User
24
+ # Provide a user resource that is compatible with default TCC restrictions
25
+ # that were introduced in macOS 10.14.
26
+ #
27
+ # Changes:
28
+ #
29
+ # * This resource and the corresponding provider have been modified to
30
+ # work with default macOS TCC policies. Direct access to user binary
31
+ # plists are no longer permitted by default, thus we've chosen to use
32
+ # a combination of newer utilities for managing user lifecycles and older
33
+ # utilities for managing passwords.
34
+ #
35
+ # * Due to tooling changes that were necessitated by the new policy
36
+ # restrictions the mac_user resource is only suitable for use on macOS
37
+ # >= 10.14. Support for older platforms has been removed.
38
+ #
39
+ # New Features:
40
+ #
41
+ # * Primary group management is now included.
42
+ #
43
+ # * 'admin' is now a boolean property that configures a user to an admin.
44
+ #
45
+ # * 'admin_username' and 'admin_password' are new properties that define the
46
+ # admin user credentials required for toggling SecureToken for a user.
47
+ #
48
+ # The value of 'admin_username' must correspond to a system user that
49
+ # is part of the 'admin' with SecureToken enabled in order to toggle
50
+ # SecureToken.
51
+ #
52
+ # * 'secure_token' is a boolean property that sets the desired state
53
+ # for SecureToken. SecureToken token is required for FileVault full
54
+ # disk encryption.
55
+ #
56
+ # * 'secure_token_password' is the plaintext password required to enable
57
+ # or disable secure_token for a user. If no salt is specified we assume
58
+ # the 'password' property corresponds to a plaintext password and will
59
+ # attempt to use it in place of secure_token_password if it not set.
60
+ class MacUser < Chef::Resource::User
61
+ resource_name :mac_user
62
+
63
+ provides :mac_user
64
+ provides :user, platform: "mac_os_x", platform_version: ">= 10.14"
65
+
66
+ introduced "15.3"
67
+
68
+ property :iterations, Integer,
69
+ description: "The number of iterations for a password with a SALTED-SHA512-PBKDF2 shadow hash.",
70
+ default: 57803, desired_state: false
71
+
72
+ # Overload gid to set our default gid to 20, the macOS "staff" group.
73
+ # We also allow a string group name here which we'll attempt to resolve
74
+ # or create in the provider.
75
+ property :gid, [Integer, String], description: "The numeric group identifier.", default: 20, coerce: ->(gid) do
76
+ begin
77
+ Integer(gid) # Try and coerce a group id string into an integer
78
+ rescue
79
+ gid # assume we have a group name
80
+ end
81
+ end
82
+
83
+ # Overload the password so we can set a length requirements and update the
84
+ # description.
85
+ property :password, String, description: "The plain text user password", sensitive: true, coerce: ->(password) {
86
+ # It would be nice if this could be in callbacks but we need the context
87
+ # of the resource to get the salt property so we have to do it in coerce.
88
+ if salt && password !~ /^[[:xdigit:]]{256}$/
89
+ raise Chef::Exceptions::User, "Password must be a SALTED-SHA512-PBKDF2 shadow hash entropy when a shadow hash salt is given"
90
+ end
91
+
92
+ password
93
+ },
94
+ callbacks: {
95
+ "Password length must be >= 4" => ->(password) { password.size >= 4 },
96
+ }
97
+
98
+ # Overload home so we set our default.
99
+ property :home, String, description: "The user home directory", default: lazy { "/Users/#{name}" }
100
+
101
+ property :admin, [TrueClass, FalseClass], description: "Create the user as an admin", default: false
102
+
103
+ # TCC on macOS >= 10.14 requires admin credentials of an Admin user that
104
+ # has SecureToken enabled in order to toggle SecureToken.
105
+ property :admin_username, String, description: "Admin username for superuser actions"
106
+ property :admin_password, String, description: "Admin password for superuser actions", sensitive: true
107
+
108
+ property :secure_token, [TrueClass, FalseClass], description: "Enable SecureToken for the user", default: false
109
+ # In order to enable SecureToken for a user we require the plaintext password.
110
+ property :secure_token_password, String, description: "The plaintext password for enabling SecureToken", sensitive: true, default: lazy {
111
+ # In some cases the user can pass the plaintext value to "password" instead of
112
+ # SALTED-SHA512-PBKDF2 entropy. In those cases we'll default to the
113
+ # same value.
114
+ (salt.nil? && password) ? password : nil
115
+ }
116
+ end
117
+ end
118
+ end
119
+ end