ruby-jss 4.2.4 → 5.0.0b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +25 -0
- data/lib/jamf/api/classic/api_objects/computer.rb +20 -0
- data/lib/jamf/api/classic/api_objects/mdm.rb +429 -238
- data/lib/jamf/api/classic/api_objects/mdm_classic.rb +1416 -0
- data/lib/jamf/api/classic/api_objects/mobile_device.rb +20 -0
- data/lib/jamf/version.rb +1 -1
- data/lib/jamf/zeitwerk_config.rb +1 -0
- metadata +28 -7
|
@@ -0,0 +1,1416 @@
|
|
|
1
|
+
# Copyright 2025 Pixar
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
|
4
|
+
# at the root of this project.
|
|
5
|
+
###
|
|
6
|
+
###
|
|
7
|
+
|
|
8
|
+
###
|
|
9
|
+
module Jamf
|
|
10
|
+
|
|
11
|
+
# Mixin Modules
|
|
12
|
+
#####################################
|
|
13
|
+
|
|
14
|
+
# This module provides the ability to work with MDM commands for objects that
|
|
15
|
+
# can receive them.
|
|
16
|
+
#
|
|
17
|
+
# Objects mixing in this module MUST:
|
|
18
|
+
#
|
|
19
|
+
# - Define the constant MDM_COMMAND_TARGET - One of:
|
|
20
|
+
# :computers, :computergroups, :mobiledevices, :mobiledevicegroups
|
|
21
|
+
#
|
|
22
|
+
#
|
|
23
|
+
#
|
|
24
|
+
#
|
|
25
|
+
module MDM
|
|
26
|
+
|
|
27
|
+
# Constants
|
|
28
|
+
#####################################
|
|
29
|
+
|
|
30
|
+
#### target types
|
|
31
|
+
|
|
32
|
+
# These targets are computers
|
|
33
|
+
COMPUTER_TARGETS = %i[computers computergroups].freeze
|
|
34
|
+
|
|
35
|
+
# The API resource for sending computer commands
|
|
36
|
+
COMPUTER_RSRC = 'computercommands'.freeze
|
|
37
|
+
|
|
38
|
+
# These targets are mobile devices
|
|
39
|
+
DEVICE_TARGETS = %i[mobiledevices mobiledevicegroups].freeze
|
|
40
|
+
|
|
41
|
+
# the API resource for sending device commands
|
|
42
|
+
DEVICE_RSRC = 'mobiledevicecommands'.freeze
|
|
43
|
+
|
|
44
|
+
# These targets are groups, and need their member ids expanded for sending commands
|
|
45
|
+
GROUP_TARGETS = %i[computergroups mobiledevicegroups].freeze
|
|
46
|
+
|
|
47
|
+
#### The commands
|
|
48
|
+
|
|
49
|
+
# Both computers & devices
|
|
50
|
+
|
|
51
|
+
BLANK_PUSH = 'BlankPush'.freeze
|
|
52
|
+
DEVICE_LOCK = 'DeviceLock'.freeze
|
|
53
|
+
ERASE_DEVICE = 'EraseDevice'.freeze
|
|
54
|
+
UNMANGE_DEVICE = 'UnmanageDevice'.freeze
|
|
55
|
+
# UPDATE_OS = 'UpdateOS'.freeze
|
|
56
|
+
|
|
57
|
+
# computers only
|
|
58
|
+
|
|
59
|
+
DELETE_USER = 'DeleteUser'.freeze
|
|
60
|
+
UNLOCK_USER_ACCOUNT = 'UnlockUserAccount'.freeze
|
|
61
|
+
ENABLE_REMOTE_DESKTOP = 'EnableRemoteDesktop'.freeze
|
|
62
|
+
DISABLE_REMOTE_DESKTOP = 'DisableRemoteDesktop'.freeze
|
|
63
|
+
|
|
64
|
+
# devices
|
|
65
|
+
|
|
66
|
+
SETTINGS = 'Settings'.freeze
|
|
67
|
+
CLEAR_PASSCODE = 'ClearPasscode'.freeze
|
|
68
|
+
UPDATE_INVENTORY = 'UpdateInventory'.freeze
|
|
69
|
+
CLEAR_RESTRICTIONS_PASSWORD = 'ClearRestrictionsPassword'.freeze
|
|
70
|
+
ENABLE_DATA_ROAMING = 'SettingsEnableDataRoaming'.freeze
|
|
71
|
+
DISABLE_DATA_ROAMING = 'SettingsDisableDataRoaming'.freeze
|
|
72
|
+
ENABLE_VOICE_ROAMING = 'SettingsEnableVoiceRoaming'.freeze
|
|
73
|
+
DISABLE_VOICE_ROAMING = 'SettingsDisableVoiceRoaming'.freeze
|
|
74
|
+
|
|
75
|
+
# shared ipads only
|
|
76
|
+
|
|
77
|
+
PASSCODE_LOCK_GRACE_PERIOD = 'PasscodeLockGracePeriod'.freeze
|
|
78
|
+
|
|
79
|
+
# supervised devices
|
|
80
|
+
|
|
81
|
+
WALLPAPER = 'Wallpaper'.freeze
|
|
82
|
+
DEVICE_NAME = 'DeviceName'.freeze
|
|
83
|
+
SHUTDOWN_DEVICE = 'ShutDownDevice'.freeze
|
|
84
|
+
RESTART_DEVICE = 'RestartDevice'.freeze
|
|
85
|
+
ENABLE_LOST_MODE = 'EnableLostMode'.freeze
|
|
86
|
+
DISABLE_LOST_MODE = 'DisableLostMode'.freeze
|
|
87
|
+
DEVICE_LOCATION = 'DeviceLocation'.freeze
|
|
88
|
+
PLAY_LOST_MODE_SOUND = 'PlayLostModeSound'.freeze
|
|
89
|
+
ENABLE_APP_ANALYTICS = 'SettingsEnableAppAnalytics'.freeze
|
|
90
|
+
DISABLE_APP_ANALYTICS = 'SettingsDisableAppAnalytics'.freeze
|
|
91
|
+
ENABLE_DIAGNOSTIC_SUBMISSION = 'SettingsEnableDiagnosticSubmission'.freeze
|
|
92
|
+
DISABLE_DIAGNOSTIC_SUBMISSION = 'SettingsDisableDiagnosticSubmission'.freeze
|
|
93
|
+
|
|
94
|
+
#### Groupings of commands
|
|
95
|
+
|
|
96
|
+
# The MDM commands applicable to computers
|
|
97
|
+
COMPUTER_COMMANDS = [
|
|
98
|
+
BLANK_PUSH,
|
|
99
|
+
DEVICE_LOCK,
|
|
100
|
+
ERASE_DEVICE,
|
|
101
|
+
UNMANGE_DEVICE,
|
|
102
|
+
DELETE_USER,
|
|
103
|
+
UNLOCK_USER_ACCOUNT,
|
|
104
|
+
ENABLE_REMOTE_DESKTOP,
|
|
105
|
+
DISABLE_REMOTE_DESKTOP
|
|
106
|
+
].freeze
|
|
107
|
+
|
|
108
|
+
# The MDM commands applicable to all mobile devices
|
|
109
|
+
ALL_DEVICE_COMMANDS = [
|
|
110
|
+
BLANK_PUSH,
|
|
111
|
+
DEVICE_LOCK,
|
|
112
|
+
ERASE_DEVICE,
|
|
113
|
+
UNMANGE_DEVICE,
|
|
114
|
+
SETTINGS,
|
|
115
|
+
CLEAR_PASSCODE,
|
|
116
|
+
UPDATE_INVENTORY,
|
|
117
|
+
ENABLE_DATA_ROAMING,
|
|
118
|
+
DISABLE_DATA_ROAMING,
|
|
119
|
+
ENABLE_VOICE_ROAMING,
|
|
120
|
+
DISABLE_VOICE_ROAMING,
|
|
121
|
+
PASSCODE_LOCK_GRACE_PERIOD
|
|
122
|
+
].freeze
|
|
123
|
+
|
|
124
|
+
# The MDM commands applicable to supervised mobile devices
|
|
125
|
+
SUPERVISED_DEVICE_COMMANDS = [
|
|
126
|
+
WALLPAPER,
|
|
127
|
+
DEVICE_NAME,
|
|
128
|
+
SHUTDOWN_DEVICE,
|
|
129
|
+
RESTART_DEVICE,
|
|
130
|
+
CLEAR_RESTRICTIONS_PASSWORD,
|
|
131
|
+
ENABLE_LOST_MODE,
|
|
132
|
+
DISABLE_LOST_MODE,
|
|
133
|
+
DEVICE_LOCATION,
|
|
134
|
+
PLAY_LOST_MODE_SOUND,
|
|
135
|
+
ENABLE_APP_ANALYTICS,
|
|
136
|
+
DISABLE_APP_ANALYTICS,
|
|
137
|
+
ENABLE_DIAGNOSTIC_SUBMISSION,
|
|
138
|
+
DISABLE_DIAGNOSTIC_SUBMISSION
|
|
139
|
+
].freeze
|
|
140
|
+
|
|
141
|
+
# The MDM commands applicable to mobile devices
|
|
142
|
+
DEVICE_COMMANDS = ALL_DEVICE_COMMANDS + SUPERVISED_DEVICE_COMMANDS
|
|
143
|
+
|
|
144
|
+
# Symbols that can be used to represent the commands to the
|
|
145
|
+
# {.send_mdm_command} Class method.
|
|
146
|
+
# Alternates are provided to match both the actual API command,
|
|
147
|
+
# and the command label in the JSS web UI, as well as common
|
|
148
|
+
# variants.
|
|
149
|
+
# e.g. the DeviceLock command in the API, is recognized as:
|
|
150
|
+
# :device_lock and :lock_device, and just :lock
|
|
151
|
+
#
|
|
152
|
+
COMMANDS = {
|
|
153
|
+
|
|
154
|
+
# all objects
|
|
155
|
+
blank_push: BLANK_PUSH,
|
|
156
|
+
send_blank_push: BLANK_PUSH,
|
|
157
|
+
noop: BLANK_PUSH,
|
|
158
|
+
|
|
159
|
+
device_lock: DEVICE_LOCK,
|
|
160
|
+
lock_device: DEVICE_LOCK,
|
|
161
|
+
lock: DEVICE_LOCK,
|
|
162
|
+
|
|
163
|
+
erase_device: ERASE_DEVICE,
|
|
164
|
+
wipe_device: ERASE_DEVICE,
|
|
165
|
+
wipe_computer: ERASE_DEVICE,
|
|
166
|
+
wipe: ERASE_DEVICE,
|
|
167
|
+
erase: ERASE_DEVICE,
|
|
168
|
+
|
|
169
|
+
unmanage_device: UNMANGE_DEVICE,
|
|
170
|
+
remove_mdm_profile: UNMANGE_DEVICE,
|
|
171
|
+
|
|
172
|
+
# computers only
|
|
173
|
+
unlock_user_account: UNLOCK_USER_ACCOUNT,
|
|
174
|
+
|
|
175
|
+
delete_user: DELETE_USER,
|
|
176
|
+
|
|
177
|
+
enable_remote_desktop: ENABLE_REMOTE_DESKTOP,
|
|
178
|
+
disable_remote_desktop: DISABLE_REMOTE_DESKTOP,
|
|
179
|
+
|
|
180
|
+
# mobile devices only
|
|
181
|
+
settings: SETTINGS, # not yet implemented as its own method
|
|
182
|
+
|
|
183
|
+
update_inventory: UPDATE_INVENTORY,
|
|
184
|
+
recon: UPDATE_INVENTORY,
|
|
185
|
+
|
|
186
|
+
clear_passcode: CLEAR_PASSCODE,
|
|
187
|
+
|
|
188
|
+
clear_restrictions_password: CLEAR_RESTRICTIONS_PASSWORD,
|
|
189
|
+
|
|
190
|
+
enable_data_roaming: ENABLE_DATA_ROAMING,
|
|
191
|
+
disable_data_roaming: DISABLE_DATA_ROAMING,
|
|
192
|
+
|
|
193
|
+
enable_voice_roaming: ENABLE_VOICE_ROAMING,
|
|
194
|
+
disable_voice_roaming: DISABLE_VOICE_ROAMING,
|
|
195
|
+
|
|
196
|
+
# supervized mobile devices only
|
|
197
|
+
device_name: DEVICE_NAME, # implemented as part of MobileDevice.name=
|
|
198
|
+
|
|
199
|
+
wallpaper: WALLPAPER,
|
|
200
|
+
set_wallpaper: WALLPAPER,
|
|
201
|
+
|
|
202
|
+
passcode_lock_grace_period: PASSCODE_LOCK_GRACE_PERIOD,
|
|
203
|
+
|
|
204
|
+
shut_down_device: SHUTDOWN_DEVICE,
|
|
205
|
+
shutdown_device: SHUTDOWN_DEVICE,
|
|
206
|
+
shut_down: SHUTDOWN_DEVICE,
|
|
207
|
+
shutdown: SHUTDOWN_DEVICE,
|
|
208
|
+
|
|
209
|
+
restart_device: RESTART_DEVICE,
|
|
210
|
+
restart: RESTART_DEVICE,
|
|
211
|
+
|
|
212
|
+
enable_app_analytics: ENABLE_APP_ANALYTICS,
|
|
213
|
+
disable_app_analytics: DISABLE_APP_ANALYTICS,
|
|
214
|
+
|
|
215
|
+
enable_diagnostic_submission: ENABLE_DIAGNOSTIC_SUBMISSION,
|
|
216
|
+
disable_diagnostic_submission: DISABLE_DIAGNOSTIC_SUBMISSION,
|
|
217
|
+
|
|
218
|
+
enable_lost_mode: ENABLE_LOST_MODE,
|
|
219
|
+
disable_lost_mode: DISABLE_LOST_MODE,
|
|
220
|
+
|
|
221
|
+
device_location: DEVICE_LOCATION, # not yet implemented as its own method
|
|
222
|
+
|
|
223
|
+
play_lost_mode_sound: PLAY_LOST_MODE_SOUND
|
|
224
|
+
}.freeze
|
|
225
|
+
|
|
226
|
+
### Command Data
|
|
227
|
+
|
|
228
|
+
COMMAND_DATA = {
|
|
229
|
+
DEVICE_LOCK => :passcode, # 6 char passcode
|
|
230
|
+
ERASE_DEVICE => String, # 6 char passcode
|
|
231
|
+
DELETE_USER => String, # username
|
|
232
|
+
UNLOCK_USER_ACCOUNT => String # username
|
|
233
|
+
}.freeze
|
|
234
|
+
|
|
235
|
+
WALLPAPER_LOCATIONS = {
|
|
236
|
+
lock_screen: 1,
|
|
237
|
+
home_screen: 2,
|
|
238
|
+
lock_and_home_screen: 3
|
|
239
|
+
}.freeze
|
|
240
|
+
|
|
241
|
+
### Status
|
|
242
|
+
|
|
243
|
+
# the status to flush for 'pending'
|
|
244
|
+
PENDING_STATUS = 'Pending'.freeze
|
|
245
|
+
|
|
246
|
+
# the status to flush for 'failed'
|
|
247
|
+
FAILED_STATUS = 'Failed'.freeze
|
|
248
|
+
|
|
249
|
+
# the status to flush for both pending and failed
|
|
250
|
+
PENDINGFAILED_STATUS = 'Pending+Failed'.freeze
|
|
251
|
+
|
|
252
|
+
FLUSHABLE_STATUSES = {
|
|
253
|
+
pending: PENDING_STATUS,
|
|
254
|
+
failed: FAILED_STATUS,
|
|
255
|
+
pending_failed: PENDINGFAILED_STATUS
|
|
256
|
+
}.freeze
|
|
257
|
+
|
|
258
|
+
BLANK_PUSH_RESULT = 'Command sent'.freeze
|
|
259
|
+
|
|
260
|
+
# xml elements
|
|
261
|
+
|
|
262
|
+
GENERAL_ELEMENT = 'general'.freeze
|
|
263
|
+
COMMAND_ELEMENT = 'command'.freeze
|
|
264
|
+
TARGET_ID_ELEMENT = 'id'.freeze
|
|
265
|
+
|
|
266
|
+
COMPUTER_COMMAND_ELEMENT = 'computer_command'.freeze
|
|
267
|
+
COMPUTER_ID_ELEMENT = 'computer_id'.freeze
|
|
268
|
+
COMPUTER_COMMAND_UDID_ELEMENT = 'command_uuid'.freeze
|
|
269
|
+
|
|
270
|
+
DEVICE_COMMAND_ELEMENT = 'mobile_device_command'.freeze
|
|
271
|
+
DEVICE_LIST_ELEMENT = 'mobile_devices'.freeze
|
|
272
|
+
DEVICE_ID_ELEMENT = 'id'.freeze
|
|
273
|
+
DEVICE_COMMAND_STATUS_ELEMENT = 'status'.freeze
|
|
274
|
+
|
|
275
|
+
# Mixin Class Methods
|
|
276
|
+
###########################
|
|
277
|
+
|
|
278
|
+
# See
|
|
279
|
+
# https://codereview.stackexchange.com/questions/23637/mixin-both-instance-and-class-methods-in-ruby
|
|
280
|
+
# for discussion of this technique for mixing in both
|
|
281
|
+
# Class and Instance methods when including a module.
|
|
282
|
+
#
|
|
283
|
+
module ClassMethods
|
|
284
|
+
|
|
285
|
+
# Send an MDM command to one or more targets without instantiating them.
|
|
286
|
+
#
|
|
287
|
+
# This general class method, and all the specific ones that all it, have
|
|
288
|
+
# matching instance methods. Use the class method when you don't have, or
|
|
289
|
+
# don't want to retrieve, instances of all the targets.
|
|
290
|
+
#
|
|
291
|
+
# If you do have an instance or a target, call the matching instance method
|
|
292
|
+
# to send commands to that specific target.
|
|
293
|
+
#
|
|
294
|
+
# @example send a blank push to mobiledevice id 12 without instantiating:
|
|
295
|
+
#
|
|
296
|
+
# Jamf::MobileDevice.send_blank_push 12
|
|
297
|
+
#
|
|
298
|
+
# @example send a blank push to mobiledevice id 12 with instantiating:
|
|
299
|
+
#
|
|
300
|
+
# device = Jamf::MobileDevice.fetch id: 12
|
|
301
|
+
# device.send_blank_push
|
|
302
|
+
#
|
|
303
|
+
# @example send a blank push to computers in computer groups
|
|
304
|
+
# 'SpecialMacs' and 'FooBarGroup'
|
|
305
|
+
#
|
|
306
|
+
# Jamf::ComputerGroup.send_blank_push ['SpecialMacs', 'FooBarGroup']
|
|
307
|
+
#
|
|
308
|
+
# @param targets[String,Integer,Array<String,Integer>]
|
|
309
|
+
# the name or id of the device(s), or devicegroup(s) to receive the
|
|
310
|
+
# command, or an array of such names or ids. NOTE: when calling this on a
|
|
311
|
+
# Group class, the targets are the groups themselves, not the individual
|
|
312
|
+
# members - the membership will be expanded.
|
|
313
|
+
#
|
|
314
|
+
# @param command[Symbol] the command to send, one of the keys
|
|
315
|
+
# of COMMANDS
|
|
316
|
+
#
|
|
317
|
+
# @param opts[Hash] Some commands require extra data, e.g. a device name.
|
|
318
|
+
# Put it here
|
|
319
|
+
#
|
|
320
|
+
# @param cnx [Jamf::Connection] the API connection to use. Defaults to the
|
|
321
|
+
# currently active API, see {Jamf::Connection}
|
|
322
|
+
#
|
|
323
|
+
# @return [Hash{Integer=>String}] Keys are the target device ids.
|
|
324
|
+
# Values depend on the kind of target:
|
|
325
|
+
# - Computers will have the udid of the command sent to that computer.
|
|
326
|
+
# The udid can be used to later retrieve info about the command.
|
|
327
|
+
# - Mobile Devices seem to only have one command udid returned - for the
|
|
328
|
+
# last device to have the command sent to it. (even in the Database,
|
|
329
|
+
# not just in the API). So instead, the Hash value is the status of
|
|
330
|
+
# the command for that device, most often 'Command sent'
|
|
331
|
+
# Blank pushes do not generate return values, so Hash values are
|
|
332
|
+
# always 'Command sent' (an error will be raised if there are problems
|
|
333
|
+
# sending)
|
|
334
|
+
#
|
|
335
|
+
def send_mdm_command(targets, command, opts: {}, api: nil, cnx: Jamf.cnx)
|
|
336
|
+
cnx = api if api
|
|
337
|
+
|
|
338
|
+
command = validate_command(command)
|
|
339
|
+
|
|
340
|
+
rsrc = "#{send_command_rsrc}/command/#{command}"
|
|
341
|
+
|
|
342
|
+
targets = raw_targets_to_ids targets, cnx: cnx
|
|
343
|
+
|
|
344
|
+
cmd_xml = mdm_command_xml(command, opts, targets)
|
|
345
|
+
|
|
346
|
+
if JSS.devmode?
|
|
347
|
+
puts "Sending XML:\n"
|
|
348
|
+
REXML::Document.new(cmd_xml).write STDOUT, 2
|
|
349
|
+
puts "\n\nTo rsrc: #{rsrc}"
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
result = cnx.c_post rsrc, cmd_xml
|
|
353
|
+
|
|
354
|
+
if command == BLANK_PUSH
|
|
355
|
+
hash = {}
|
|
356
|
+
targets.each { |t| hash[t] = BLANK_PUSH_RESULT }
|
|
357
|
+
elsif COMPUTER_TARGETS.include? self::MDM_COMMAND_TARGET
|
|
358
|
+
hash = process_computer_xml_result(result)
|
|
359
|
+
elsif DEVICE_TARGETS.include? self::MDM_COMMAND_TARGET
|
|
360
|
+
hash = process_mobiledevice_xml_result(result)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
hash
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Convert the result of senting a computer MDM command into
|
|
367
|
+
# the appropriate hash
|
|
368
|
+
#
|
|
369
|
+
# @param result [String] The raw XML from POSTing a computer command
|
|
370
|
+
#
|
|
371
|
+
# @return (see #send_mdm_command)
|
|
372
|
+
#
|
|
373
|
+
def process_computer_xml_result(result)
|
|
374
|
+
hash = {}
|
|
375
|
+
REXML::Document.new(result).elements[COMPUTER_COMMAND_ELEMENT].each_element do |cmd|
|
|
376
|
+
compid = cmd.elements[COMPUTER_ID_ELEMENT].text.to_i
|
|
377
|
+
udid = cmd.elements[COMPUTER_COMMAND_UDID_ELEMENT].text
|
|
378
|
+
hash[compid] = udid
|
|
379
|
+
end
|
|
380
|
+
hash
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# Convert the result of senting a device MDM command into
|
|
384
|
+
# the appropriate hash
|
|
385
|
+
#
|
|
386
|
+
# @param result [String] The raw XML from POSTing a device command
|
|
387
|
+
#
|
|
388
|
+
# @return (see #send_mdm_command)
|
|
389
|
+
#
|
|
390
|
+
def process_mobiledevice_xml_result(result)
|
|
391
|
+
hash = {}
|
|
392
|
+
mds = REXML::Document.new(result).elements[DEVICE_COMMAND_ELEMENT].elements[DEVICE_LIST_ELEMENT]
|
|
393
|
+
mds.each_element do |md|
|
|
394
|
+
id = md.elements[DEVICE_ID_ELEMENT].text.to_i
|
|
395
|
+
status = md.elements[DEVICE_COMMAND_STATUS_ELEMENT].text
|
|
396
|
+
hash[id] = status
|
|
397
|
+
end
|
|
398
|
+
hash
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
# The API rsrc for sending MDM commands to this kind of target
|
|
402
|
+
#
|
|
403
|
+
# @return [String] The API rsrc.
|
|
404
|
+
#
|
|
405
|
+
def send_command_rsrc
|
|
406
|
+
case self::MDM_COMMAND_TARGET
|
|
407
|
+
when *COMPUTER_TARGETS
|
|
408
|
+
COMPUTER_RSRC
|
|
409
|
+
when *DEVICE_TARGETS
|
|
410
|
+
DEVICE_RSRC
|
|
411
|
+
else
|
|
412
|
+
raise Jamf::InvalidDataError, "Unknown MDM command target: #{self::MDM_COMMAND_TARGET}"
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
# Convert the targets provided for sending a command into
|
|
417
|
+
# the final list of computers or mobile devices.
|
|
418
|
+
#
|
|
419
|
+
# @param targets[String,Integer,Array] See {#send_mdm_command}
|
|
420
|
+
#
|
|
421
|
+
# @param expand_groups[Boolean] Should groups be expanded into member ids?
|
|
422
|
+
#
|
|
423
|
+
# @param cnx [Jamf::Connection] an API connection to use.
|
|
424
|
+
#
|
|
425
|
+
# @return [Array<Integer>] The ids of the target devices for a command
|
|
426
|
+
#
|
|
427
|
+
def raw_targets_to_ids(targets, expand_groups: true, unmanaged_ok: false, api: nil, cnx: Jamf.cnx)
|
|
428
|
+
cnx = api if api
|
|
429
|
+
|
|
430
|
+
targets = targets.is_a?(Array) ? targets : [targets]
|
|
431
|
+
|
|
432
|
+
# flush caches before checking ids and managment
|
|
433
|
+
cnx.flushcache self::RSRC_LIST_KEY
|
|
434
|
+
|
|
435
|
+
# make sure its an array of ids
|
|
436
|
+
targets.map! do |md|
|
|
437
|
+
id = valid_id md, cnx: cnx
|
|
438
|
+
raise Jamf::NoSuchItemError, "No #{self} matches identifier: #{md}" unless id
|
|
439
|
+
|
|
440
|
+
id
|
|
441
|
+
end # map!
|
|
442
|
+
|
|
443
|
+
# expand group members if needed
|
|
444
|
+
if expand_groups && GROUP_TARGETS.include?(self::MDM_COMMAND_TARGET)
|
|
445
|
+
target_ids = []
|
|
446
|
+
targets.each { |group_id| target_ids += fetch(id: group_id).member_ids }
|
|
447
|
+
targets = target_ids
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
# make sure all of them are managed, or else the API will raise a 400
|
|
451
|
+
# 'Bad Request' when sending the command to an unmanaged target.
|
|
452
|
+
# Some actions, like flushing MDM commands (see .flush_mdm_commands)
|
|
453
|
+
# are OK on unmanaged machines, so they will specify 'unmanaged_ok'
|
|
454
|
+
unless unmanaged_ok
|
|
455
|
+
all_mgd = map_all_ids_to(:managed, cnx: cnx).select { |_id, mgd| mgd }.keys
|
|
456
|
+
|
|
457
|
+
targets.each do |target_id|
|
|
458
|
+
raise Jamf::UnmanagedError, "#{self} with id #{target_id} is not managed. Cannot send command." unless all_mgd.include? target_id
|
|
459
|
+
end
|
|
460
|
+
end # unles
|
|
461
|
+
|
|
462
|
+
targets
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# Generate the XML to send to the API, sending the MDM command to the targets
|
|
466
|
+
#
|
|
467
|
+
# @param command [Symbol] the command to be sent, a key from COMMANDS
|
|
468
|
+
#
|
|
469
|
+
# @param options [Hash] different commands require different options,
|
|
470
|
+
# see each command method
|
|
471
|
+
#
|
|
472
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
473
|
+
#
|
|
474
|
+
# @return [String] The XML content to send to the API
|
|
475
|
+
#
|
|
476
|
+
def mdm_command_xml(command, options, targets)
|
|
477
|
+
raise Jamf::MissingDataError, 'Targets cannot be empty' if targets.empty?
|
|
478
|
+
|
|
479
|
+
case self::MDM_COMMAND_TARGET
|
|
480
|
+
when *COMPUTER_TARGETS
|
|
481
|
+
command_elem = COMPUTER_COMMAND_ELEMENT
|
|
482
|
+
target_list_elem = Jamf::Computer::RSRC_LIST_KEY.to_s
|
|
483
|
+
target_elem = Jamf::Computer::RSRC_OBJECT_KEY.to_s
|
|
484
|
+
when *DEVICE_TARGETS
|
|
485
|
+
command_elem = DEVICE_COMMAND_ELEMENT
|
|
486
|
+
target_list_elem = Jamf::MobileDevice::RSRC_LIST_KEY.to_s
|
|
487
|
+
target_elem = Jamf::MobileDevice::RSRC_OBJECT_KEY.to_s
|
|
488
|
+
else
|
|
489
|
+
raise Jamf::NoSuchItemError, "Unknonwn MDM command target: #{self::MDM_COMMAND_TARGET}"
|
|
490
|
+
end # case
|
|
491
|
+
|
|
492
|
+
xml = REXML::Document.new Jamf::Connection::XML_HEADER
|
|
493
|
+
xml.root.name = command_elem
|
|
494
|
+
cmd_xml = xml.root
|
|
495
|
+
|
|
496
|
+
general = cmd_xml.add_element GENERAL_ELEMENT
|
|
497
|
+
general.add_element(COMMAND_ELEMENT).text = command
|
|
498
|
+
options.each do |opt, val|
|
|
499
|
+
general.add_element(opt.to_s).text = val.to_s
|
|
500
|
+
end # do opt val
|
|
501
|
+
|
|
502
|
+
tgt_list = cmd_xml.add_element target_list_elem
|
|
503
|
+
targets.each do |tgt_id|
|
|
504
|
+
tgt = tgt_list.add_element(target_elem)
|
|
505
|
+
tgt.add_element(TARGET_ID_ELEMENT).text = tgt_id.to_s
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
xml.to_s
|
|
509
|
+
end # self.mdm_command_xml(command, options)
|
|
510
|
+
|
|
511
|
+
# Validate that this command is known and can be sent to this kind of
|
|
512
|
+
# object, raising an error if not.
|
|
513
|
+
#
|
|
514
|
+
# @param command[Symbol] One of the symbolic commands as keys in COMMANDS
|
|
515
|
+
#
|
|
516
|
+
# @return [String] the matching value for the command symbol given
|
|
517
|
+
#
|
|
518
|
+
def validate_command(command)
|
|
519
|
+
raise Jamf::NoSuchItemError, "Unknown command '#{command}'" unless COMMANDS.keys.include? command
|
|
520
|
+
|
|
521
|
+
command = COMMANDS[command]
|
|
522
|
+
|
|
523
|
+
case self::MDM_COMMAND_TARGET
|
|
524
|
+
when *COMPUTER_TARGETS
|
|
525
|
+
return command if COMPUTER_COMMANDS.include? command
|
|
526
|
+
|
|
527
|
+
raise Jamf::UnsupportedError, "'#{command}' cannot be sent to computers or computer groups"
|
|
528
|
+
when *DEVICE_TARGETS
|
|
529
|
+
return command if DEVICE_COMMANDS.include? command
|
|
530
|
+
|
|
531
|
+
raise Jamf::UnsupportedError, "'#{command}' cannot be sent to mobile devices or mobile device groups"
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
raise Jamf::NoSuchItemError, "'#{command}' is known, but not available for computers or mobile devices. This is a bug. Please report it."
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
###### The individual commands
|
|
538
|
+
|
|
539
|
+
# NOTE: not implementing Settings and Location until I know more what they do
|
|
540
|
+
|
|
541
|
+
# Commands for both computers and devices
|
|
542
|
+
################################
|
|
543
|
+
|
|
544
|
+
# Send a blank push to one or more targets
|
|
545
|
+
#
|
|
546
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
547
|
+
#
|
|
548
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
549
|
+
#
|
|
550
|
+
# @return (see .send_mdm_command)]
|
|
551
|
+
#
|
|
552
|
+
def blank_push(targets, api: nil, cnx: Jamf.cnx)
|
|
553
|
+
cnx = api if api
|
|
554
|
+
|
|
555
|
+
send_mdm_command targets, :blank_push, cnx: cnx
|
|
556
|
+
end
|
|
557
|
+
alias send_blank_push blank_push
|
|
558
|
+
alias noop blank_push
|
|
559
|
+
|
|
560
|
+
# Send a Device Lock to one or more targets
|
|
561
|
+
#
|
|
562
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
563
|
+
#
|
|
564
|
+
# @param passcode[String] a six-char passcode, required for computers & computergroups
|
|
565
|
+
#
|
|
566
|
+
# @param message[String] An optional message to display on mobiledevices & mobiledevicegroups
|
|
567
|
+
#
|
|
568
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
569
|
+
#
|
|
570
|
+
# @return (see .send_mdm_command)
|
|
571
|
+
#
|
|
572
|
+
def device_lock(targets, passcode: '', message: nil, api: nil, cnx: Jamf.cnx)
|
|
573
|
+
cnx = api if api
|
|
574
|
+
|
|
575
|
+
case self::MDM_COMMAND_TARGET
|
|
576
|
+
when *COMPUTER_TARGETS
|
|
577
|
+
raise Jamf::InvalidDataError, 'Locking computers requires a 6-character String passcode' unless passcode.size == 6
|
|
578
|
+
|
|
579
|
+
opts = { passcode: passcode }
|
|
580
|
+
when *DEVICE_TARGETS
|
|
581
|
+
opts = {}
|
|
582
|
+
opts[:lock_message] = message if message
|
|
583
|
+
end # case
|
|
584
|
+
send_mdm_command targets, :device_lock, opts: opts, cnx: cnx
|
|
585
|
+
end
|
|
586
|
+
alias lock_device device_lock
|
|
587
|
+
alias lock device_lock
|
|
588
|
+
|
|
589
|
+
# Send an Erase Device command to one or more targets
|
|
590
|
+
#
|
|
591
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
592
|
+
#
|
|
593
|
+
# @param passcode[String] a six-char passcode, required for computers & computergroups
|
|
594
|
+
#
|
|
595
|
+
# @param preserve_data_plan[Boolean] Should the data plan of the mobile device be preserved?
|
|
596
|
+
#
|
|
597
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
598
|
+
#
|
|
599
|
+
# @return (see .send_mdm_command)
|
|
600
|
+
#
|
|
601
|
+
def erase_device(targets, passcode: '', preserve_data_plan: false, api: nil, cnx: Jamf.cnx)
|
|
602
|
+
cnx = api if api
|
|
603
|
+
|
|
604
|
+
case self::MDM_COMMAND_TARGET
|
|
605
|
+
when *COMPUTER_TARGETS
|
|
606
|
+
raise Jamf::InvalidDataError, 'Erasing computers requires a 6-character String passcode' unless passcode.size == 6
|
|
607
|
+
|
|
608
|
+
opts = { passcode: passcode }
|
|
609
|
+
when *DEVICE_TARGETS
|
|
610
|
+
opts = {}
|
|
611
|
+
opts[:preserve_data_plan] = 'true' if preserve_data_plan
|
|
612
|
+
end # case
|
|
613
|
+
send_mdm_command targets, :erase_device, opts: opts, cnx: cnx
|
|
614
|
+
end
|
|
615
|
+
alias wipe erase_device
|
|
616
|
+
alias wipe_device erase_device
|
|
617
|
+
alias erase erase_device
|
|
618
|
+
alias wipe_computer erase_device
|
|
619
|
+
|
|
620
|
+
# Send an Unmanage Device command to one or more targets
|
|
621
|
+
#
|
|
622
|
+
# NOTE: when used with computers, the mdm profile will probably
|
|
623
|
+
# be re-installed immediately unless the computer is also no longer
|
|
624
|
+
# managed by Jamf Pro itself. To fully unmanage a computer, use
|
|
625
|
+
# the {Jamf::Computer#make_unmanaged} instance method.
|
|
626
|
+
#
|
|
627
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
628
|
+
#
|
|
629
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
630
|
+
#
|
|
631
|
+
# @return (see .send_mdm_command)
|
|
632
|
+
#
|
|
633
|
+
def unmanage_device(targets, api: nil, cnx: Jamf.cnx)
|
|
634
|
+
cnx = api if api
|
|
635
|
+
|
|
636
|
+
send_mdm_command targets, :unmanage_device, cnx: cnx
|
|
637
|
+
end
|
|
638
|
+
alias remove_mdm_profile unmanage_device
|
|
639
|
+
|
|
640
|
+
# Commands for computers only
|
|
641
|
+
################################
|
|
642
|
+
|
|
643
|
+
# Send an unlock_user_account command to one or more targets
|
|
644
|
+
#
|
|
645
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
646
|
+
#
|
|
647
|
+
# @param user[String] the username of the acct to unlock
|
|
648
|
+
#
|
|
649
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
650
|
+
#
|
|
651
|
+
# @return (see .send_mdm_command)
|
|
652
|
+
#
|
|
653
|
+
def unlock_user_account(targets, user, api: nil, cnx: Jamf.cnx)
|
|
654
|
+
cnx = api if api
|
|
655
|
+
|
|
656
|
+
send_mdm_command targets, :unlock_user_account, opts: { user_name: user }, cnx: cnx
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
# Send a delete_user command to one or more targets
|
|
660
|
+
#
|
|
661
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
662
|
+
#
|
|
663
|
+
# @param user[String] the username of the acct to delete
|
|
664
|
+
#
|
|
665
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
666
|
+
#
|
|
667
|
+
# @return (see .send_mdm_command)
|
|
668
|
+
#
|
|
669
|
+
def delete_user(targets, user, api: nil, cnx: Jamf.cnx)
|
|
670
|
+
cnx = api if api
|
|
671
|
+
|
|
672
|
+
send_mdm_command targets, :delete_user, opts: { user_name: user }, cnx: cnx
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
# Send an enable_remote_desktop command to one or more targets
|
|
676
|
+
#
|
|
677
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
678
|
+
#
|
|
679
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
680
|
+
#
|
|
681
|
+
# @return (see .send_mdm_command)
|
|
682
|
+
#
|
|
683
|
+
def enable_remote_desktop(targets, api: nil, cnx: Jamf.cnx)
|
|
684
|
+
cnx = api if api
|
|
685
|
+
|
|
686
|
+
send_mdm_command targets, :enable_remote_desktop, cnx: cnx
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
# Send a disable_remote_desktop command to one or more targets
|
|
690
|
+
#
|
|
691
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
692
|
+
#
|
|
693
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
694
|
+
#
|
|
695
|
+
# @return (see .send_mdm_command)
|
|
696
|
+
#
|
|
697
|
+
def disable_remote_desktop(targets, api: nil, cnx: Jamf.cnx)
|
|
698
|
+
cnx = api if api
|
|
699
|
+
|
|
700
|
+
send_mdm_command targets, :disable_remote_desktop, cnx: cnx
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
# Commands for mobile devices only
|
|
704
|
+
################################
|
|
705
|
+
|
|
706
|
+
# Send an update_inventory command to one or more targets
|
|
707
|
+
#
|
|
708
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
709
|
+
#
|
|
710
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
711
|
+
#
|
|
712
|
+
# @return (see .send_mdm_command)
|
|
713
|
+
#
|
|
714
|
+
def update_inventory(targets, api: nil, cnx: Jamf.cnx)
|
|
715
|
+
cnx = api if api
|
|
716
|
+
|
|
717
|
+
send_mdm_command targets, :update_inventory, cnx: cnx
|
|
718
|
+
end
|
|
719
|
+
alias recon update_inventory
|
|
720
|
+
|
|
721
|
+
# Send an clear_passcode command to one or more targets
|
|
722
|
+
#
|
|
723
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
724
|
+
#
|
|
725
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
726
|
+
#
|
|
727
|
+
# @return (see .send_mdm_command)
|
|
728
|
+
#
|
|
729
|
+
def clear_passcode(targets, api: nil, cnx: Jamf.cnx)
|
|
730
|
+
cnx = api if api
|
|
731
|
+
|
|
732
|
+
send_mdm_command targets, :clear_passcode, cnx: cnx
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
# Send an clear_restrictions_password command to one or more targets
|
|
736
|
+
#
|
|
737
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
738
|
+
#
|
|
739
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
740
|
+
#
|
|
741
|
+
# @return (see .send_mdm_command)
|
|
742
|
+
#
|
|
743
|
+
def clear_restrictions_password(targets, api: nil, cnx: Jamf.cnx)
|
|
744
|
+
cnx = api if api
|
|
745
|
+
|
|
746
|
+
send_mdm_command targets, :clear_restrictions_password, cnx: cnx
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
# Send an enable_data_roaming command to one or more targets
|
|
750
|
+
#
|
|
751
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
752
|
+
#
|
|
753
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
754
|
+
#
|
|
755
|
+
# @return (see .send_mdm_command)
|
|
756
|
+
#
|
|
757
|
+
def enable_data_roaming(targets, api: nil, cnx: Jamf.cnx)
|
|
758
|
+
cnx = api if api
|
|
759
|
+
|
|
760
|
+
send_mdm_command targets, :enable_data_roaming, cnx: cnx
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
# Send andisable_data_roaming command to one or more targets
|
|
764
|
+
#
|
|
765
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
766
|
+
#
|
|
767
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
768
|
+
#
|
|
769
|
+
# @return (see .send_mdm_command)
|
|
770
|
+
#
|
|
771
|
+
def disable_data_roaming(targets, api: nil, cnx: Jamf.cnx)
|
|
772
|
+
cnx = api if api
|
|
773
|
+
|
|
774
|
+
send_mdm_command targets, :disable_data_roaming, cnx: cnx
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
# Send an enable_voice_roaming command to one or more targets
|
|
778
|
+
#
|
|
779
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
780
|
+
#
|
|
781
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
782
|
+
#
|
|
783
|
+
# @return (see .send_mdm_command)
|
|
784
|
+
#
|
|
785
|
+
def enable_voice_roaming(targets, api: nil, cnx: Jamf.cnx)
|
|
786
|
+
cnx = api if api
|
|
787
|
+
|
|
788
|
+
send_mdm_command targets, :enable_voice_roaming, cnx: cnx
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
# Send a disable_voice_roaming command to one or more targets
|
|
792
|
+
#
|
|
793
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
794
|
+
#
|
|
795
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
796
|
+
#
|
|
797
|
+
# @return (see .send_mdm_command)
|
|
798
|
+
#
|
|
799
|
+
def disable_voice_roaming(targets, api: nil, cnx: Jamf.cnx)
|
|
800
|
+
cnx = api if api
|
|
801
|
+
|
|
802
|
+
send_mdm_command targets, :disable_voice_roaming, cnx: cnx
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
# Commands for supervized mobile devices only
|
|
806
|
+
################################
|
|
807
|
+
|
|
808
|
+
# Send a device_name command to one or more targets
|
|
809
|
+
#
|
|
810
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
811
|
+
#
|
|
812
|
+
# @param name[String] The new name
|
|
813
|
+
#
|
|
814
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
815
|
+
#
|
|
816
|
+
# @return (see .send_mdm_command)
|
|
817
|
+
#
|
|
818
|
+
def device_name(targets, name, api: nil, cnx: Jamf.cnx)
|
|
819
|
+
cnx = api if api
|
|
820
|
+
|
|
821
|
+
send_mdm_command targets, :device_name, opts: { device_name: name }, cnx: cnx
|
|
822
|
+
end
|
|
823
|
+
alias set_name device_name
|
|
824
|
+
alias set_device_name device_name
|
|
825
|
+
|
|
826
|
+
# Send a wallpaper command to one or more targets
|
|
827
|
+
#
|
|
828
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
829
|
+
#
|
|
830
|
+
# @param wallpaper_setting[Symbol] :lock_screen, :home_screen, or :lock_and_home_screen
|
|
831
|
+
#
|
|
832
|
+
# @param wallpaper_content[String,Pathname] The local path to a .png or .jpg to use
|
|
833
|
+
# as the walpaper image, required if no wallpaper_id
|
|
834
|
+
#
|
|
835
|
+
# @param wallpaper_id[Symbol] The id of an Icon in Jamf Pro to use as the wallpaper image,
|
|
836
|
+
# required if no wallpaper_content
|
|
837
|
+
#
|
|
838
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
839
|
+
#
|
|
840
|
+
# @return (see .send_mdm_command)
|
|
841
|
+
#
|
|
842
|
+
def wallpaper(targets, wallpaper_setting: nil, wallpaper_content: nil, wallpaper_id: nil, api: nil, cnx: Jamf.cnx)
|
|
843
|
+
cnx = api if api
|
|
844
|
+
|
|
845
|
+
unless WALLPAPER_LOCATIONS.keys.include? wallpaper_setting
|
|
846
|
+
raise ArgumentError,
|
|
847
|
+
"wallpaper_setting must be one of: :#{WALLPAPER_LOCATIONS.keys.join ', :'}"
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
opts = { wallpaper_setting: WALLPAPER_LOCATIONS[wallpaper_setting] }
|
|
851
|
+
|
|
852
|
+
if wallpaper_content
|
|
853
|
+
file = Pathname.new wallpaper_content
|
|
854
|
+
raise Jamf::NoSuchItemError, "Not a file: #{file}" unless file.file?
|
|
855
|
+
|
|
856
|
+
opts[:wallpaper_content] = Base64.encode64 file.read
|
|
857
|
+
elsif wallpaper_id
|
|
858
|
+
opts[:wallpaper_id] = wallpaper_id
|
|
859
|
+
else
|
|
860
|
+
raise ArgumentError, 'Either wallpaper_id: or wallpaper_content must be provided'
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
send_mdm_command targets, :wallpaper, opts: opts, cnx: cnx
|
|
864
|
+
end
|
|
865
|
+
alias set_wallpaper wallpaper
|
|
866
|
+
|
|
867
|
+
# Send a passcode_lock_grace_period command to one or more targets
|
|
868
|
+
#
|
|
869
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
870
|
+
#
|
|
871
|
+
# @param secs[Integer] The numer of seconds for the grace period
|
|
872
|
+
#
|
|
873
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
874
|
+
#
|
|
875
|
+
# @return (see .send_mdm_command)
|
|
876
|
+
#
|
|
877
|
+
def passcode_lock_grace_period(targets, secs, api: nil, cnx: Jamf.cnx)
|
|
878
|
+
cnx = api if api
|
|
879
|
+
|
|
880
|
+
send_mdm_command targets, :passcode_lock_grace_period, opts: { passcode_lock_grace_period: secs }, cnx: cnx
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
# Send a shut_down_device command to one or more targets
|
|
884
|
+
#
|
|
885
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
886
|
+
#
|
|
887
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
888
|
+
#
|
|
889
|
+
# @return (see .send_mdm_command)
|
|
890
|
+
#
|
|
891
|
+
def shut_down_device(targets, api: nil, cnx: Jamf.cnx)
|
|
892
|
+
cnx = api if api
|
|
893
|
+
|
|
894
|
+
send_mdm_command targets, :shut_down_device, cnx: cnx
|
|
895
|
+
end
|
|
896
|
+
alias shutdown_device shut_down_device
|
|
897
|
+
alias shut_down shut_down_device
|
|
898
|
+
alias shutdown shut_down_device
|
|
899
|
+
|
|
900
|
+
# Send a restart_device command to one or more targets
|
|
901
|
+
#
|
|
902
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
903
|
+
#
|
|
904
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
905
|
+
#
|
|
906
|
+
# @return (see .send_mdm_command)
|
|
907
|
+
#
|
|
908
|
+
def restart_device(targets, api: nil, cnx: Jamf.cnx)
|
|
909
|
+
cnx = api if api
|
|
910
|
+
|
|
911
|
+
send_mdm_command targets, :restart_device, cnx: cnx
|
|
912
|
+
end
|
|
913
|
+
alias restart restart_device
|
|
914
|
+
|
|
915
|
+
# Send an enable_app_analytics command to one or more targets
|
|
916
|
+
#
|
|
917
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
918
|
+
#
|
|
919
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
920
|
+
#
|
|
921
|
+
# @return (see .send_mdm_command)
|
|
922
|
+
#
|
|
923
|
+
def enable_app_analytics(targets, api: nil, cnx: Jamf.cnx)
|
|
924
|
+
cnx = api if api
|
|
925
|
+
|
|
926
|
+
send_mdm_command targets, :enable_app_analytics, cnx: cnx
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
# Send a disable_app_analytics command to one or more targets
|
|
930
|
+
#
|
|
931
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
932
|
+
#
|
|
933
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
934
|
+
#
|
|
935
|
+
# @return (see .send_mdm_command)
|
|
936
|
+
#
|
|
937
|
+
def disable_app_analytics(targets, api: nil, cnx: Jamf.cnx)
|
|
938
|
+
cnx = api if api
|
|
939
|
+
|
|
940
|
+
send_mdm_command targets, :disable_app_analytics, cnx: cnx
|
|
941
|
+
end
|
|
942
|
+
|
|
943
|
+
# Send an enable_diagnostic_submission command to one or more targets
|
|
944
|
+
#
|
|
945
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
946
|
+
#
|
|
947
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
948
|
+
#
|
|
949
|
+
# @return (see .send_mdm_command)
|
|
950
|
+
#
|
|
951
|
+
def enable_diagnostic_submission(targets, api: nil, cnx: Jamf.cnx)
|
|
952
|
+
cnx = api if api
|
|
953
|
+
|
|
954
|
+
send_mdm_command targets, :enable_diagnostic_submission, cnx: cnx
|
|
955
|
+
end
|
|
956
|
+
|
|
957
|
+
# Send a disable_diagnostic_submission command to one or more targets
|
|
958
|
+
#
|
|
959
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
960
|
+
#
|
|
961
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
962
|
+
#
|
|
963
|
+
# @return (see .send_mdm_command)
|
|
964
|
+
#
|
|
965
|
+
def disable_diagnostic_submission(targets, api: nil, cnx: Jamf.cnx)
|
|
966
|
+
cnx = api if api
|
|
967
|
+
|
|
968
|
+
send_mdm_command targets, :disable_diagnostic_submission, cnx: cnx
|
|
969
|
+
end
|
|
970
|
+
|
|
971
|
+
# Send a enable_lost_mode command to one or more targets
|
|
972
|
+
#
|
|
973
|
+
# Either or both of message and phone number must be provided
|
|
974
|
+
#
|
|
975
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
976
|
+
#
|
|
977
|
+
# @param message[String] The message to display on the lock screen
|
|
978
|
+
#
|
|
979
|
+
# @param phone[String] The phone number to display on the lock screen
|
|
980
|
+
#
|
|
981
|
+
# @param footnote[String] Optional footnote to display on the lock screen
|
|
982
|
+
#
|
|
983
|
+
# @param play_sound[Boolean] Play a sound when entering lost mode
|
|
984
|
+
#
|
|
985
|
+
# @param enforce_lost_mode[Boolean] Re-enable lost mode when re-enrolled after wipe. Default is false
|
|
986
|
+
#
|
|
987
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
988
|
+
#
|
|
989
|
+
# @return (see .send_mdm_command)
|
|
990
|
+
#
|
|
991
|
+
def enable_lost_mode(
|
|
992
|
+
targets,
|
|
993
|
+
message: nil,
|
|
994
|
+
phone: nil,
|
|
995
|
+
footnote: nil,
|
|
996
|
+
play_sound: false,
|
|
997
|
+
enforce_lost_mode: false,
|
|
998
|
+
api: nil,
|
|
999
|
+
cnx: Jamf.cnx
|
|
1000
|
+
)
|
|
1001
|
+
cnx = api if api
|
|
1002
|
+
|
|
1003
|
+
raise ArgumentError, 'Either message: or phone_number: must be provided' unless message || phone
|
|
1004
|
+
|
|
1005
|
+
opts = { always_enforce_lost_mode: enforce_lost_mode }
|
|
1006
|
+
opts[:lost_mode_message] = message if message
|
|
1007
|
+
opts[:lost_mode_phone] = phone if phone
|
|
1008
|
+
opts[:lost_mode_footnote] = footnote if footnote
|
|
1009
|
+
opts[:lost_mode_with_sound] = 'true' if play_sound
|
|
1010
|
+
|
|
1011
|
+
send_mdm_command targets, :enable_lost_mode, opts: opts, cnx: cnx
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
# Send a play_lost_mode_sound command to one or more targets
|
|
1015
|
+
#
|
|
1016
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
1017
|
+
#
|
|
1018
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
1019
|
+
#
|
|
1020
|
+
# @return (see .send_mdm_command)
|
|
1021
|
+
#
|
|
1022
|
+
def play_lost_mode_sound(targets, api: nil, cnx: Jamf.cnx)
|
|
1023
|
+
cnx = api if api
|
|
1024
|
+
|
|
1025
|
+
send_mdm_command targets, :play_lost_mode_sound, cnx: cnx
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
# Send a disable_lost_mode command to one or more targets
|
|
1029
|
+
#
|
|
1030
|
+
# @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
|
|
1031
|
+
#
|
|
1032
|
+
# @param cnx [Jamf::Connection] the API thru which to send the command
|
|
1033
|
+
#
|
|
1034
|
+
# @return (see .send_mdm_command)
|
|
1035
|
+
#
|
|
1036
|
+
def disable_lost_mode(targets, api: nil, cnx: Jamf.cnx)
|
|
1037
|
+
cnx = api if api
|
|
1038
|
+
|
|
1039
|
+
send_mdm_command targets, :disable_lost_mode, cnx: cnx
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
# Flushing Commands
|
|
1043
|
+
###############################
|
|
1044
|
+
|
|
1045
|
+
# Flush pending or failed commands on devices or groups
|
|
1046
|
+
#
|
|
1047
|
+
# @param targets[String,Integer,Array<String,Integer>]
|
|
1048
|
+
# the name or id of the device or group to flush commands, or
|
|
1049
|
+
# an array of such names or ids, or a comma-separated string
|
|
1050
|
+
# of them. NOTE: when calling this on a Group class, the targets
|
|
1051
|
+
# are the groups themselves, not the individual members.
|
|
1052
|
+
#
|
|
1053
|
+
# @param status[String] a key from {Jamf::Commandable::FLUSHABLE_STATUSES}
|
|
1054
|
+
#
|
|
1055
|
+
# @param cnx [Jamf::Connection] an API connection to use.
|
|
1056
|
+
# Defaults to the corrently active API. See {Jamf::Connection}
|
|
1057
|
+
#
|
|
1058
|
+
# @return [void]
|
|
1059
|
+
#
|
|
1060
|
+
def flush_mdm_commands(targets, status: nil, api: nil, cnx: Jamf.cnx)
|
|
1061
|
+
cnx = api if api
|
|
1062
|
+
|
|
1063
|
+
raise Jamf::InvalidDataError, "Status must be one of :#{FLUSHABLE_STATUSES.keys.join ', :'}" unless FLUSHABLE_STATUSES.keys.include? status
|
|
1064
|
+
|
|
1065
|
+
status = FLUSHABLE_STATUSES[status]
|
|
1066
|
+
|
|
1067
|
+
# TODO: add 'unmanaged_ok:' param to raw_targets_to_ids method, so that we can
|
|
1068
|
+
# use this to flush commands for unmanaged machines.
|
|
1069
|
+
target_ids = raw_targets_to_ids targets, cnx: cnx, expand_groups: false, unmanaged_ok: true
|
|
1070
|
+
|
|
1071
|
+
command_flush_rsrc = "commandflush/#{self::MDM_COMMAND_TARGET}/id"
|
|
1072
|
+
|
|
1073
|
+
flush_rsrc = "#{command_flush_rsrc}/#{target_ids.join ','}/status/#{status}"
|
|
1074
|
+
|
|
1075
|
+
puts "Sending API DELETE: #{flush_rsrc}" if JSS.devmode?
|
|
1076
|
+
|
|
1077
|
+
cnx.c_delete flush_rsrc
|
|
1078
|
+
end
|
|
1079
|
+
|
|
1080
|
+
end # module ClassMethods
|
|
1081
|
+
|
|
1082
|
+
# Extend ourself when included
|
|
1083
|
+
# @see {Jamf::MDM::ClassMethods}
|
|
1084
|
+
def self.included(klass)
|
|
1085
|
+
klass.extend Jamf::MDM::ClassMethods
|
|
1086
|
+
end
|
|
1087
|
+
|
|
1088
|
+
# Mixin Instance Methods
|
|
1089
|
+
###########################
|
|
1090
|
+
# See https://codereview.stackexchange.com/questions/23637/mixin-both-instance-and-class-methods-in-ruby
|
|
1091
|
+
# for discussion of this technique for mixing in both
|
|
1092
|
+
# Class and Instance methods when including a module.
|
|
1093
|
+
|
|
1094
|
+
# Commands for both computers and devices
|
|
1095
|
+
################################
|
|
1096
|
+
|
|
1097
|
+
# Send a blank push to this object
|
|
1098
|
+
#
|
|
1099
|
+
# @return [void]
|
|
1100
|
+
#
|
|
1101
|
+
def blank_push
|
|
1102
|
+
self.class.send_blank_push @id, cnx: @cnx
|
|
1103
|
+
end
|
|
1104
|
+
alias send_blank_push blank_push
|
|
1105
|
+
alias noop blank_push
|
|
1106
|
+
|
|
1107
|
+
# Send a dev lock to this object
|
|
1108
|
+
#
|
|
1109
|
+
# @param passcode_or_message[String] a six-char passcode, required for computers & computergroups
|
|
1110
|
+
# Or an optional message to display on mobiledevices & mobiledevicegroups
|
|
1111
|
+
#
|
|
1112
|
+
# @return (see .send_mdm_command)
|
|
1113
|
+
#
|
|
1114
|
+
def device_lock(passcode_or_message = '')
|
|
1115
|
+
self.class.device_lock @id, passcode: passcode_or_message, message: passcode_or_message, cnx: @cnx
|
|
1116
|
+
end
|
|
1117
|
+
alias lock device_lock
|
|
1118
|
+
alias lock_device device_lock
|
|
1119
|
+
|
|
1120
|
+
# Send an erase device command to this object
|
|
1121
|
+
#
|
|
1122
|
+
# @param passcode[String] a six-char passcode, required for computers & computergroups
|
|
1123
|
+
#
|
|
1124
|
+
# @return (see .send_mdm_command)
|
|
1125
|
+
#
|
|
1126
|
+
def erase_device(passcode = '', preserve_data_plan: false)
|
|
1127
|
+
self.class.erase_device @id, passcode: passcode, preserve_data_plan: preserve_data_plan, cnx: @cnx
|
|
1128
|
+
end
|
|
1129
|
+
alias wipe_device erase_device
|
|
1130
|
+
alias wipe_computer erase_device
|
|
1131
|
+
alias wipe erase_device
|
|
1132
|
+
alias erase erase_device
|
|
1133
|
+
|
|
1134
|
+
# Send an unmanage device command to this object
|
|
1135
|
+
#
|
|
1136
|
+
# NOTE: when used with computers, the mdm profile will probably
|
|
1137
|
+
# be re-installed immediately unless the computer is also no longer
|
|
1138
|
+
# managed by Jamf Pro itself. To fully unmanage a computer, use
|
|
1139
|
+
# the {Jamf::Computer#make_unmanaged} instance method.
|
|
1140
|
+
#
|
|
1141
|
+
# @return (see .send_mdm_command)
|
|
1142
|
+
#
|
|
1143
|
+
def unmanage_device
|
|
1144
|
+
self.class.unmanage_device @id, cnx: @cnx
|
|
1145
|
+
end
|
|
1146
|
+
alias remove_mdm_profile unmanage_device
|
|
1147
|
+
|
|
1148
|
+
# Commands for computers only
|
|
1149
|
+
################################
|
|
1150
|
+
|
|
1151
|
+
# Send an unlock_user_account command to this computer or group
|
|
1152
|
+
#
|
|
1153
|
+
# @param user[String] the username of the acct to unlock
|
|
1154
|
+
#
|
|
1155
|
+
# @return (see .send_mdm_command)
|
|
1156
|
+
#
|
|
1157
|
+
def unlock_user_account(user)
|
|
1158
|
+
self.class.unlock_user_account @id, user, cnx: @cnx
|
|
1159
|
+
end
|
|
1160
|
+
|
|
1161
|
+
# Send a delete_user command to this computer or group
|
|
1162
|
+
#
|
|
1163
|
+
# @param user[String] the username of the acct to delete
|
|
1164
|
+
#
|
|
1165
|
+
# @return (see .send_mdm_command)
|
|
1166
|
+
#
|
|
1167
|
+
def delete_user(user)
|
|
1168
|
+
self.class.delete_user @id, user, cnx: @cnx
|
|
1169
|
+
end
|
|
1170
|
+
|
|
1171
|
+
# Send an enable_remote_desktop command to this computer or group
|
|
1172
|
+
#
|
|
1173
|
+
# @return (see .send_mdm_command)
|
|
1174
|
+
#
|
|
1175
|
+
def enable_remote_desktop
|
|
1176
|
+
self.class.enable_remote_desktop @id, cnx: @cnx
|
|
1177
|
+
end
|
|
1178
|
+
|
|
1179
|
+
# Send a disable_remote_desktop command to this computer or group
|
|
1180
|
+
#
|
|
1181
|
+
# @return (see .send_mdm_command)
|
|
1182
|
+
#
|
|
1183
|
+
def disable_remote_desktop
|
|
1184
|
+
self.class.disable_remote_desktop @id, cnx: @cnx
|
|
1185
|
+
end
|
|
1186
|
+
|
|
1187
|
+
# Commands for mobile devices only
|
|
1188
|
+
################################
|
|
1189
|
+
# mobile devices only
|
|
1190
|
+
# settings: SETTINGS,
|
|
1191
|
+
|
|
1192
|
+
# Send an update_inventory command to this object
|
|
1193
|
+
#
|
|
1194
|
+
# @return (see .send_mdm_command)
|
|
1195
|
+
#
|
|
1196
|
+
def update_inventory
|
|
1197
|
+
self.class.update_inventory @id, cnx: @cnx
|
|
1198
|
+
end
|
|
1199
|
+
alias recon update_inventory
|
|
1200
|
+
|
|
1201
|
+
# Send an clear_passcode command to this object
|
|
1202
|
+
#
|
|
1203
|
+
# @return (see .send_mdm_command)
|
|
1204
|
+
#
|
|
1205
|
+
def clear_passcode
|
|
1206
|
+
self.class.clear_passcode @id, cnx: @cnx
|
|
1207
|
+
end
|
|
1208
|
+
|
|
1209
|
+
# Send an clear_restrictions_password command to this object
|
|
1210
|
+
#
|
|
1211
|
+
# @return (see .send_mdm_command)
|
|
1212
|
+
#
|
|
1213
|
+
def clear_restrictions_password
|
|
1214
|
+
self.class.clear_restrictions_password @id, cnx: @cnx
|
|
1215
|
+
end
|
|
1216
|
+
|
|
1217
|
+
# Send an enable_data_roaming command to this object
|
|
1218
|
+
#
|
|
1219
|
+
# @return (see .send_mdm_command)
|
|
1220
|
+
#
|
|
1221
|
+
def enable_data_roaming
|
|
1222
|
+
self.class.enable_data_roaming @id, cnx: @cnx
|
|
1223
|
+
end
|
|
1224
|
+
|
|
1225
|
+
# Send a disable_data_roaming command to this object
|
|
1226
|
+
#
|
|
1227
|
+
# @return (see .send_mdm_command)
|
|
1228
|
+
#
|
|
1229
|
+
def disable_data_roaming
|
|
1230
|
+
self.class.disable_data_roaming @id, cnx: @cnx
|
|
1231
|
+
end
|
|
1232
|
+
|
|
1233
|
+
# Send an enable_voice_roaming command to this object
|
|
1234
|
+
#
|
|
1235
|
+
# @return (see .send_mdm_command)
|
|
1236
|
+
#
|
|
1237
|
+
def enable_voice_roaming
|
|
1238
|
+
self.class.enable_voice_roaming @id, cnx: @cnx
|
|
1239
|
+
end
|
|
1240
|
+
|
|
1241
|
+
# Send a disable_voice_roaming command to this object
|
|
1242
|
+
#
|
|
1243
|
+
# @return (see .send_mdm_command)
|
|
1244
|
+
#
|
|
1245
|
+
def disable_voice_roaming
|
|
1246
|
+
self.class.disable_voice_roaming @id, cnx: @cnx
|
|
1247
|
+
end
|
|
1248
|
+
|
|
1249
|
+
# Commands for supervized mobile devices only
|
|
1250
|
+
#
|
|
1251
|
+
# NOTE: DeviceName is sent to supervised devices when
|
|
1252
|
+
# their name is changed with #name= and they are then
|
|
1253
|
+
# updated in the JSS with #update/#save
|
|
1254
|
+
################################
|
|
1255
|
+
|
|
1256
|
+
# Send a device_name command to this object
|
|
1257
|
+
#
|
|
1258
|
+
# @param name[String] The new name
|
|
1259
|
+
#
|
|
1260
|
+
# @return (see .send_mdm_command)
|
|
1261
|
+
#
|
|
1262
|
+
def device_name(name)
|
|
1263
|
+
self.class.device_name @id, name, cnx: @cnx
|
|
1264
|
+
end
|
|
1265
|
+
alias set_name device_name
|
|
1266
|
+
alias set_device_name device_name
|
|
1267
|
+
|
|
1268
|
+
# Send a wallpaper command to this object
|
|
1269
|
+
#
|
|
1270
|
+
# @param wallpaper_setting[Symbol] :lock_screen, :home_screen, or :lock_and_home_screen
|
|
1271
|
+
#
|
|
1272
|
+
# @param wallpaper_content[String,Pathname] The local path to a .png or .jpg to use
|
|
1273
|
+
# as the walpaper image, required if no wallpaper_id
|
|
1274
|
+
#
|
|
1275
|
+
# @param wallpaper_id[Symbol] The id of an Icon in Jamf Pro to use as the wallpaper image,
|
|
1276
|
+
# required if no wallpaper_content
|
|
1277
|
+
#
|
|
1278
|
+
# @return (see .send_mdm_command)
|
|
1279
|
+
#
|
|
1280
|
+
def wallpaper(wallpaper_setting: nil, wallpaper_content: nil, wallpaper_id: nil)
|
|
1281
|
+
self.class.wallpaper(
|
|
1282
|
+
@id,
|
|
1283
|
+
wallpaper_setting: wallpaper_setting,
|
|
1284
|
+
wallpaper_content: wallpaper_content,
|
|
1285
|
+
wallpaper_id: wallpaper_id, cnx: @cnx
|
|
1286
|
+
)
|
|
1287
|
+
end
|
|
1288
|
+
alias set_wallpaper wallpaper
|
|
1289
|
+
|
|
1290
|
+
# Send a passcode_lock_grace_period command to this object
|
|
1291
|
+
#
|
|
1292
|
+
# @param secs[Integer] The numer of seconds for the grace period
|
|
1293
|
+
#
|
|
1294
|
+
# @return (see .send_mdm_command)
|
|
1295
|
+
#
|
|
1296
|
+
def passcode_lock_grace_period(secs)
|
|
1297
|
+
self.class.passcode_lock_grace_period @id, secs, cnx: @cnx
|
|
1298
|
+
end
|
|
1299
|
+
|
|
1300
|
+
# Send a shut_down_device command to this object
|
|
1301
|
+
#
|
|
1302
|
+
# @return (see .send_mdm_command)
|
|
1303
|
+
#
|
|
1304
|
+
def shut_down_device
|
|
1305
|
+
self.class.shut_down_device @id, cnx: @cnx
|
|
1306
|
+
end
|
|
1307
|
+
alias shutdown_device shut_down_device
|
|
1308
|
+
alias shut_down shut_down_device
|
|
1309
|
+
alias shutdown shut_down_device
|
|
1310
|
+
|
|
1311
|
+
# Send a restart_device command to this object
|
|
1312
|
+
#
|
|
1313
|
+
# @return (see .send_mdm_command)
|
|
1314
|
+
#
|
|
1315
|
+
def restart_device
|
|
1316
|
+
self.class.restart_device @id, cnx: @cnx
|
|
1317
|
+
end
|
|
1318
|
+
alias restart restart_device
|
|
1319
|
+
|
|
1320
|
+
# Send an enable_app_analytics command to this object
|
|
1321
|
+
#
|
|
1322
|
+
# @return (see .send_mdm_command)
|
|
1323
|
+
#
|
|
1324
|
+
def enable_app_analytics
|
|
1325
|
+
self.class.enable_app_analytics @id, cnx: @cnx
|
|
1326
|
+
end
|
|
1327
|
+
|
|
1328
|
+
# Send a disable_app_analytics command to this object
|
|
1329
|
+
#
|
|
1330
|
+
# @return (see .send_mdm_command)
|
|
1331
|
+
#
|
|
1332
|
+
def disable_app_analytics
|
|
1333
|
+
self.class.disable_app_analytics @id, cnx: @cnx
|
|
1334
|
+
end
|
|
1335
|
+
|
|
1336
|
+
# Send an enable_diagnostic_submission command to this object
|
|
1337
|
+
#
|
|
1338
|
+
# @return (see .send_mdm_command)
|
|
1339
|
+
#
|
|
1340
|
+
def enable_diagnostic_submission
|
|
1341
|
+
self.class.enable_diagnostic_submission @id, cnx: @cnx
|
|
1342
|
+
end
|
|
1343
|
+
|
|
1344
|
+
# Send a disable_diagnostic_submission command to this object
|
|
1345
|
+
#
|
|
1346
|
+
# @return (see .send_mdm_command)
|
|
1347
|
+
#
|
|
1348
|
+
def disable_diagnostic_submission
|
|
1349
|
+
self.class.disable_diagnostic_submission @id, cnx: @cnx
|
|
1350
|
+
end
|
|
1351
|
+
|
|
1352
|
+
# Send a enable_lost_mode command to one or more targets
|
|
1353
|
+
#
|
|
1354
|
+
# Either or both of message and phone number must be provided
|
|
1355
|
+
#
|
|
1356
|
+
# @param message[String] The message to display on the lock screen
|
|
1357
|
+
#
|
|
1358
|
+
# @param phone_number[String] The phone number to display on the lock screen
|
|
1359
|
+
#
|
|
1360
|
+
# @param footnote[String] Optional footnote to display on the lock screen
|
|
1361
|
+
#
|
|
1362
|
+
# @param play_sound[Boolean] Play a sound when entering lost mode
|
|
1363
|
+
#
|
|
1364
|
+
# @param enforce_lost_mode[Boolean] Re-enable lost mode when re-enrolled after wipe. Default is false
|
|
1365
|
+
#
|
|
1366
|
+
# @return (see .send_mdm_command)
|
|
1367
|
+
#
|
|
1368
|
+
def enable_lost_mode(
|
|
1369
|
+
message: nil,
|
|
1370
|
+
phone: nil,
|
|
1371
|
+
footnote: nil,
|
|
1372
|
+
enforce_lost_mode: false,
|
|
1373
|
+
play_sound: false
|
|
1374
|
+
)
|
|
1375
|
+
self.class.enable_lost_mode(
|
|
1376
|
+
@id,
|
|
1377
|
+
message: message,
|
|
1378
|
+
phone: phone,
|
|
1379
|
+
footnote: footnote,
|
|
1380
|
+
play_sound: play_sound,
|
|
1381
|
+
enforce_lost_mode: enforce_lost_mode, cnx: @cnx
|
|
1382
|
+
)
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
# Send a play_lost_mode_sound command to this object
|
|
1386
|
+
#
|
|
1387
|
+
# @return (see .send_mdm_command)
|
|
1388
|
+
#
|
|
1389
|
+
def play_lost_mode_sound
|
|
1390
|
+
self.class.play_lost_mode_sound @id, cnx: @cnx
|
|
1391
|
+
end
|
|
1392
|
+
|
|
1393
|
+
# Send a disable_lost_mode command to this object
|
|
1394
|
+
#
|
|
1395
|
+
# @return (see .send_mdm_command)
|
|
1396
|
+
#
|
|
1397
|
+
def disable_lost_mode
|
|
1398
|
+
self.class.disable_lost_mode @id, cnx: @cnx
|
|
1399
|
+
end
|
|
1400
|
+
|
|
1401
|
+
# Flushing Commands
|
|
1402
|
+
###############################
|
|
1403
|
+
|
|
1404
|
+
# flush pending and/or failed MDM commands for this object
|
|
1405
|
+
#
|
|
1406
|
+
# @param status[String] a key from {Jamf::Commandable::FLUSHABLE_STATUSES}
|
|
1407
|
+
#
|
|
1408
|
+
# @return [void]
|
|
1409
|
+
#
|
|
1410
|
+
def flush_mdm_commands(status)
|
|
1411
|
+
self.class.flush_mdm_commands @id, status: status, cnx: @cnx
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
end # module MDM
|
|
1415
|
+
|
|
1416
|
+
end # module
|