ruby-jss 2.1.0 → 3.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 +27 -0
- data/lib/jamf/api/classic/api_objects/computer.rb +20 -6
- data/lib/jamf/api/classic/api_objects/distribution_point.rb +17 -41
- data/lib/jamf/api/classic/api_objects/mdm.rb +9 -9
- data/lib/jamf/api/classic/api_objects/mobile_device_application.rb +1 -0
- data/lib/jamf/api/classic/api_objects/policy.rb +173 -92
- data/lib/jamf/api/classic/api_objects/scopable/scope.rb +5 -2
- data/lib/jamf/api/jamf_pro/mixins/macos_managed_updates.rb +47 -37
- data/lib/jamf/validate.rb +3 -1
- data/lib/jamf/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7af617b6ac8bb27cbc7d5c790a2de9fa788fb3d426ae062581654fbc9f77c5f
|
4
|
+
data.tar.gz: f5dfabfdde6c466951862fdc458321ad4f9384293e1fe773fb78a0ca80e51283
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85fd8c1218206a35545cc034058996a5b03183f29ac443cf65735c547975afcedaf406f74099f610380a1b72272db5240c2427ab4e87201ef5d9ec7ceffd2f29
|
7
|
+
data.tar.gz: a04b06cbcb9858b06dfe738ced2943e37b6a12088da394599b6ccfae66ac0a9c1bc82a264dac02c0379308141d4cc9795594c19639f473e5684cdd62e48db368
|
data/CHANGES.md
CHANGED
@@ -14,6 +14,33 @@ __Please update all installations of ruby-jss to at least v1.6.0.__
|
|
14
14
|
|
15
15
|
Many many thanks to actae0n of Blacksun Hackers Club for reporting this issue and providing examples of how it could be exploited.
|
16
16
|
|
17
|
+
--------
|
18
|
+
|
19
|
+
## \[UNRELEASED]
|
20
|
+
|
21
|
+
### Added
|
22
|
+
- Jamf::Policy.flush_logs_for_computers: formerly private class method, now public and used for flushing policy logs for specific computers.
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
- Fix bug in MDM enable_lost_mode instance method, and make the default behavior match the API
|
26
|
+
- Specify the connection instance when validating ids in MacOSManagedUpdates
|
27
|
+
- Send mandatory field 'name' with a MobileDeviceApplication request (Thanks @yanniks!)
|
28
|
+
- Policy Log Flushing now reflects API limitation: You can flush logs for a policy for all computers, or for a computer for all policies, but not specific policies for specific computers. See Jamf::Policy.flush_logs and Jamf::Policy.flush_logs_for_computers
|
29
|
+
- A validation method wasn't passing cnx param correctly.
|
30
|
+
|
31
|
+
### Changed
|
32
|
+
- MacOSManagedUpdates.send_managed_os_update takes symbols as the updateAction
|
33
|
+
|
34
|
+
## \[2.1.1] - 2022-11-07
|
35
|
+
|
36
|
+
### Fixed & Deprecated
|
37
|
+
|
38
|
+
- The classic API no longer includes SHA256 hashes of various passwords - the data value is there, but only contains a string of asterisks. As such, ruby-jss can no longer use those to validate some passwords before trying to use them. The methods doing so are still present, but only return `true`. If an incorrect password is given, the underlying process that uses it will fail on its own.
|
39
|
+
These methods will be removed in a future version of ruby-jss:
|
40
|
+
- `Jamf::DistributionPoint#check_pw` Used mostly by the `Jamf::DistributionPoint#mount` method
|
41
|
+
- `Jamf::Policy.verify_management_password`
|
42
|
+
|
43
|
+
|
17
44
|
## \[2.1.0] - 2022-10-10
|
18
45
|
|
19
46
|
### Added
|
@@ -1158,15 +1158,29 @@ module Jamf
|
|
1158
1158
|
@need_to_update = true
|
1159
1159
|
end
|
1160
1160
|
|
1161
|
-
#
|
1162
|
-
# @see Jamf::Policy.flush_logs
|
1161
|
+
# Flush all policy logs for this computer older than a given time period.
|
1163
1162
|
#
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1163
|
+
# IMPORTANT: from the Jamf Developer Site:
|
1164
|
+
# The ability to flush logs is currently only supported for flushing all logs
|
1165
|
+
# for a given policy or all logs for a given computer. There is no support for
|
1166
|
+
# flushing logs for a given policy and computer combination.
|
1167
|
+
#
|
1168
|
+
# With no parameters, will flush all logs for the computer
|
1169
|
+
#
|
1170
|
+
# NOTE: Currently the API doesn't have a way to flush only failed policies.
|
1171
|
+
#
|
1172
|
+
# @param older_than[Integer] 0, 1, 2, 3, or 6
|
1173
|
+
#
|
1174
|
+
# @param period[Symbol] :days, :weeks, :months, or :years
|
1175
|
+
#
|
1176
|
+
# @see Jamf::Policy.flush_logs_for_computers
|
1177
|
+
#
|
1178
|
+
def flush_policy_logs(older_than: 0, period: :days)
|
1179
|
+
Jamf::Policy.flush_logs_for_computers(
|
1180
|
+
[@id],
|
1167
1181
|
older_than: older_than,
|
1168
1182
|
period: period,
|
1169
|
-
|
1183
|
+
cnx: @cnx
|
1170
1184
|
)
|
1171
1185
|
end
|
1172
1186
|
|
@@ -259,8 +259,8 @@ module Jamf
|
|
259
259
|
attr_reader :ssh_password_sha256
|
260
260
|
|
261
261
|
def initialize(**args)
|
262
|
-
super
|
263
|
-
|
262
|
+
super
|
263
|
+
|
264
264
|
@ip_address = @init_data[:ip_address]
|
265
265
|
@local_path = @init_data[:local_path]
|
266
266
|
@enable_load_balancing = @init_data[:enable_load_balancing]
|
@@ -294,44 +294,28 @@ module Jamf
|
|
294
294
|
|
295
295
|
@port = @init_data[:ssh_password]
|
296
296
|
|
297
|
-
# Note, as of Casper 9.3:
|
298
|
-
# :management_password_md5=>"xxxxx"
|
299
|
-
# and
|
300
|
-
# :management_password_sha256=> "xxxxxxxxxx"
|
301
|
-
# Are the read/write password
|
302
|
-
#
|
303
|
-
# An empty passwd is
|
304
|
-
# MD5 = d41d8cd98f00b204e9800998ecf8427e
|
305
|
-
# SHA256 = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
306
|
-
#
|
307
|
-
# Seemms the read-only pw isn't available in the API
|
308
|
-
|
309
297
|
# if we mount for fileservice, where's the mountpoint?
|
310
298
|
@mountpoint = DEFAULT_MOUNTPOINT_DIR + "#{DEFAULT_MOUNTPOINT_PREFIX}#{@id}"
|
311
299
|
end # init
|
312
300
|
|
313
|
-
#
|
301
|
+
# @deprecated The API no longer sends SHA256 hashed password data, and instead
|
302
|
+
# only has a string of asterisks, meaning we can no longer use it to validate
|
303
|
+
# passwords before attempting to use them. Instead, the processes that use
|
304
|
+
# them, e.g. mounting a Dist. Point, will fail on their own if the pw is not
|
305
|
+
# valid.
|
314
306
|
#
|
315
|
-
#
|
307
|
+
# This method remains defined for backward-compatibility with any existing
|
308
|
+
# code that calls it. but it will always return true. It will be removed in
|
309
|
+
# a future version
|
316
310
|
#
|
317
|
-
# @param
|
311
|
+
# @param user[Symbol] ignored
|
318
312
|
#
|
319
|
-
# @
|
320
|
-
# nil is returned if there is no password set in the JSS.
|
313
|
+
# @param pw[String] ignored
|
321
314
|
#
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
when :rw then @read_write_password_sha256
|
327
|
-
when :ro then @read_only_password_sha256
|
328
|
-
when :http then @http_password_sha256
|
329
|
-
when :ssh then @ssh_password_sha256
|
330
|
-
end # case
|
331
|
-
|
332
|
-
return nil if sha256 == EMPTY_PW_256
|
333
|
-
|
334
|
-
sha256 == Digest::SHA2.new(256).update(pw).to_s
|
315
|
+
# @return [TrueClass] Allow the process calling this to continue.
|
316
|
+
#
|
317
|
+
def check_pw(_user = nil, _pw = nil)
|
318
|
+
true
|
335
319
|
end
|
336
320
|
|
337
321
|
# Check to see if this dist point is reachable for downloads (read-only)
|
@@ -350,7 +334,6 @@ module Jamf
|
|
350
334
|
def reachable_for_download?(pw = '', check_http = true)
|
351
335
|
return :http if check_http && http_reachable?(pw)
|
352
336
|
return :mountable if mounted?
|
353
|
-
return false unless check_pw :ro, pw
|
354
337
|
|
355
338
|
begin
|
356
339
|
mount pw, :ro
|
@@ -371,7 +354,6 @@ module Jamf
|
|
371
354
|
#
|
372
355
|
def reachable_for_upload?(pw)
|
373
356
|
return :mountable if mounted?
|
374
|
-
return false unless check_pw :rw, pw
|
375
357
|
|
376
358
|
begin
|
377
359
|
mount pw, :rw
|
@@ -413,12 +395,6 @@ module Jamf
|
|
413
395
|
pw
|
414
396
|
end
|
415
397
|
|
416
|
-
pwok = check_pw(access, password)
|
417
|
-
unless pwok
|
418
|
-
msg = pwok.nil? ? "No #{access} password set in the JSS" : "Incorrect password for #{access} account"
|
419
|
-
raise Jamf::InvalidDataError, msg
|
420
|
-
end
|
421
|
-
|
422
398
|
username = access == :ro ? @read_only_username : @read_write_username
|
423
399
|
|
424
400
|
safe_pw = CGI.escape password.to_s
|
@@ -481,7 +457,7 @@ module Jamf
|
|
481
457
|
private
|
482
458
|
|
483
459
|
# can the dp be reached for http downloads?
|
484
|
-
def http_reachable?(pw)
|
460
|
+
def http_reachable?(pw = nil)
|
485
461
|
return false unless http_downloads_enabled
|
486
462
|
|
487
463
|
url =
|
@@ -476,7 +476,7 @@ module Jamf
|
|
476
476
|
raise Jamf::UnmanagedError, "#{self} with id #{target_id} is not managed. Cannot send command." unless all_mgd.include? target_id
|
477
477
|
end
|
478
478
|
end # unles
|
479
|
-
|
479
|
+
|
480
480
|
targets
|
481
481
|
end
|
482
482
|
|
@@ -860,7 +860,7 @@ module Jamf
|
|
860
860
|
cnx = api if api
|
861
861
|
|
862
862
|
unless WALLPAPER_LOCATIONS.keys.include? wallpaper_setting
|
863
|
-
raise ArgumentError,
|
863
|
+
raise ArgumentError,
|
864
864
|
"wallpaper_setting must be one of: :#{WALLPAPER_LOCATIONS.keys.join ', :'}"
|
865
865
|
end
|
866
866
|
|
@@ -999,7 +999,7 @@ module Jamf
|
|
999
999
|
#
|
1000
1000
|
# @param play_sound[Boolean] Play a sound when entering lost mode
|
1001
1001
|
#
|
1002
|
-
# @param enforce_lost_mode[Boolean] Re-
|
1002
|
+
# @param enforce_lost_mode[Boolean] Re-enable lost mode when re-enrolled after wipe. Default is false
|
1003
1003
|
#
|
1004
1004
|
# @param cnx [Jamf::Connection] the API thru which to send the command
|
1005
1005
|
#
|
@@ -1011,7 +1011,7 @@ module Jamf
|
|
1011
1011
|
phone: nil,
|
1012
1012
|
footnote: nil,
|
1013
1013
|
play_sound: false,
|
1014
|
-
enforce_lost_mode:
|
1014
|
+
enforce_lost_mode: false,
|
1015
1015
|
api: nil,
|
1016
1016
|
cnx: Jamf.cnx
|
1017
1017
|
)
|
@@ -1081,7 +1081,7 @@ module Jamf
|
|
1081
1081
|
|
1082
1082
|
status = FLUSHABLE_STATUSES[status]
|
1083
1083
|
|
1084
|
-
# TODO: add 'unmanaged_ok:' param to raw_targets_to_ids method, so that we can
|
1084
|
+
# TODO: add 'unmanaged_ok:' param to raw_targets_to_ids method, so that we can
|
1085
1085
|
# use this to flush commands for unmanaged machines.
|
1086
1086
|
target_ids = raw_targets_to_ids targets, cnx: cnx, expand_groups: false, unmanaged_ok: true
|
1087
1087
|
|
@@ -1378,21 +1378,21 @@ module Jamf
|
|
1378
1378
|
#
|
1379
1379
|
# @param play_sound[Boolean] Play a sound when entering lost mode
|
1380
1380
|
#
|
1381
|
-
# @param enforce_lost_mode[Boolean] Re-
|
1381
|
+
# @param enforce_lost_mode[Boolean] Re-enable lost mode when re-enrolled after wipe. Default is false
|
1382
1382
|
#
|
1383
1383
|
# @return (see .send_mdm_command)
|
1384
1384
|
#
|
1385
1385
|
def enable_lost_mode(
|
1386
1386
|
message: nil,
|
1387
|
-
|
1387
|
+
phone: nil,
|
1388
1388
|
footnote: nil,
|
1389
|
-
enforce_lost_mode:
|
1389
|
+
enforce_lost_mode: false,
|
1390
1390
|
play_sound: false
|
1391
1391
|
)
|
1392
1392
|
self.class.enable_lost_mode(
|
1393
1393
|
@id,
|
1394
1394
|
message: message,
|
1395
|
-
|
1395
|
+
phone: phone,
|
1396
1396
|
footnote: footnote,
|
1397
1397
|
play_sound: play_sound,
|
1398
1398
|
enforce_lost_mode: enforce_lost_mode, cnx: @cnx
|
@@ -544,6 +544,7 @@ module Jamf
|
|
544
544
|
doc = REXML::Document.new Jamf::Connection::XML_HEADER
|
545
545
|
obj = doc.add_element self.class::RSRC_OBJECT_KEY.to_s
|
546
546
|
gen = obj.add_element 'general'
|
547
|
+
gen.add_element('name').text = @display_name
|
547
548
|
gen.add_element('display_name').text = @display_name
|
548
549
|
gen.add_element('description').text = @description
|
549
550
|
gen.add_element('os_type').text = @os_type
|
@@ -166,7 +166,7 @@ module Jamf
|
|
166
166
|
selected: 'Currently Selected Startup Disk (No Bless)',
|
167
167
|
netboot: 'NetBoot',
|
168
168
|
os_installer: 'inPlaceOSUpgradeDirectory'
|
169
|
-
}.freeze #
|
169
|
+
}.freeze # NOTE: any other value in :specify_startup is a path to some other drive to boot from, e.g. /Volumes/Foo
|
170
170
|
|
171
171
|
ACCOUNT_ACTIONS = {
|
172
172
|
create: 'Create',
|
@@ -200,9 +200,9 @@ module Jamf
|
|
200
200
|
}.freeze
|
201
201
|
|
202
202
|
DISK_ENCRYPTION_ACTIONS = {
|
203
|
-
apply:
|
204
|
-
remediate:
|
205
|
-
none:
|
203
|
+
apply: 'apply',
|
204
|
+
remediate: 'remediate',
|
205
|
+
none: 'none'
|
206
206
|
}
|
207
207
|
|
208
208
|
PRINTER_ACTIONS = {
|
@@ -293,10 +293,19 @@ module Jamf
|
|
293
293
|
# Class Methods
|
294
294
|
######################
|
295
295
|
|
296
|
-
# Flush logs for a given policy older than
|
297
|
-
#
|
296
|
+
# Flush logs for a given policy older than a given time period.
|
297
|
+
# This flushes the logs of the given policy for all computers.
|
298
298
|
#
|
299
|
-
#
|
299
|
+
# IMPORTANT: from the Jamf Developer Site:
|
300
|
+
# The ability to flush logs is currently only supported for flushing all logs
|
301
|
+
# for a given policy or all logs for a given computer. There is no support for
|
302
|
+
# flushing logs for a given policy and computer combination.
|
303
|
+
#
|
304
|
+
# (See .flush_logs_for_computers to to flush all logs for given computers)
|
305
|
+
#
|
306
|
+
# With no parameters, flushes all logs for the policy.
|
307
|
+
#
|
308
|
+
# Without older_than: and period:, will flush all logs for the policy
|
300
309
|
#
|
301
310
|
# NOTE: Currently the API doesn't have a way to flush only failed policies.
|
302
311
|
#
|
@@ -306,52 +315,74 @@ module Jamf
|
|
306
315
|
#
|
307
316
|
# @param policy[Integer,String] The id or name of the policy to flush
|
308
317
|
#
|
309
|
-
# @param older_than[Integer] 0, 1, 2, 3, or 6
|
318
|
+
# @param older_than[Integer] 0, 1, 2, 3, or 6, defaults to 0
|
310
319
|
#
|
311
|
-
# @param period[Symbol] :days, :weeks, :months, or :years
|
312
|
-
#
|
313
|
-
# @param computers[Array<Integer,String>] Identifiers of the target computers
|
314
|
-
# either ids, names, SNs, macaddrs, or UDIDs. If omitted, flushes logs for
|
315
|
-
# all computers
|
320
|
+
# @param period[Symbol] :days, :weeks, :months, or :years, defaults to :days
|
316
321
|
#
|
317
322
|
# @param cnx [Jamf::Connection] the API connection to use.
|
318
323
|
#
|
319
324
|
# @return [void]
|
320
325
|
#
|
321
|
-
def self.flush_logs(policy, older_than: 0, period: :days,
|
326
|
+
def self.flush_logs(policy, older_than: 0, period: :days, api: nil, cnx: Jamf.cnx)
|
322
327
|
cnx = api if api
|
323
328
|
|
324
|
-
orig_timeout = cnx.timeout
|
325
329
|
pol_id = valid_id policy, cnx: cnx
|
326
330
|
raise Jamf::NoSuchItemError, "No Policy identified by '#{policy}'." unless pol_id
|
327
331
|
|
328
|
-
older_than =
|
329
|
-
raise Jamf::InvalidDataError, "older_than must be one of these integers: #{LOG_FLUSH_INTERVAL_INTEGERS.keys.join ', '}" unless older_than
|
330
|
-
|
331
|
-
period = LOG_FLUSH_INTERVAL_PERIODS[period]
|
332
|
-
raise Jamf::InvalidDataError, "period must be one of these symbols: :#{LOG_FLUSH_INTERVAL_PERIODS.keys.join ', :'}" unless period
|
333
|
-
|
334
|
-
computers = [computers] unless computers.is_a? Array
|
332
|
+
older_than, period = validate_log_flush_params(older_than, period)
|
335
333
|
|
336
334
|
# log flushes can be really slow
|
335
|
+
orig_timeout = cnx.timeout
|
337
336
|
cnx.timeout = 1800 unless orig_timeout && orig_timeout > 1800
|
338
337
|
|
339
|
-
|
340
|
-
|
341
|
-
flush_logs_for_specific_computers pol_id, older_than, period, computers, cnx
|
338
|
+
cnx.c_delete "#{LOG_FLUSH_RSRC}/policy/id/#{pol_id}/interval/#{older_than}+#{period}"
|
342
339
|
ensure
|
343
340
|
cnx.timeout = orig_timeout
|
344
341
|
end
|
345
342
|
|
346
|
-
#
|
347
|
-
#
|
348
|
-
|
343
|
+
# Flush policy logs for specific computers older than a given time period.
|
344
|
+
# This flushes the logs for all policies for these computers.
|
345
|
+
#
|
346
|
+
# IMPORTANT: from the Jamf Developer Site:
|
347
|
+
# The ability to flush logs is currently only supported for flushing all logs
|
348
|
+
# for a given policy or all logs for a given computer. There is no support for
|
349
|
+
# flushing logs for a given policy and computer combination.
|
350
|
+
#
|
351
|
+
# (See .flush_logs to to flush all logs for a given policy)
|
352
|
+
#
|
353
|
+
# Without older_than: and period:, will flush all logs for the computers
|
354
|
+
#
|
355
|
+
# NOTE: Currently the API doesn't have a way to flush only failed policies.
|
356
|
+
#
|
357
|
+
# WARNING: Log flushing can take a long time, and the API call doesnt return
|
358
|
+
# until its finished. The connection timeout will be temporarily raised to
|
359
|
+
# 30 minutes, unless it's already higher.
|
360
|
+
#
|
361
|
+
# @param computers[Array<Integer,String>] Identifiers of the target computers
|
362
|
+
# either ids, names, SNs, macaddrs, or UDIDs.
|
363
|
+
#
|
364
|
+
# @param older_than[Integer] 0, 1, 2, 3, or 6, defaults to 0
|
365
|
+
#
|
366
|
+
# @param period[Symbol] :days, :weeks, :months, or :years, defaults to :days
|
367
|
+
#
|
368
|
+
# @param cnx [Jamf::Connection] the API connection to use.
|
369
|
+
#
|
370
|
+
# @return [void]
|
371
|
+
#
|
372
|
+
def self.flush_logs_for_computers(computers = [], older_than: 0, period: :days, api: nil, cnx: Jamf.cnx)
|
373
|
+
cnx = api if api
|
374
|
+
|
375
|
+
computers = [computers] unless computers.is_a? Array
|
376
|
+
raise JSS::InvalidDataError, 'One or more computers must be specified' if computers.empty?
|
377
|
+
|
378
|
+
older_than, period = validate_log_flush_params(older_than, period)
|
379
|
+
|
349
380
|
# build the xml body for a DELETE request
|
350
381
|
xml_doc = REXML::Document.new Jamf::Connection::XML_HEADER
|
351
382
|
lf = xml_doc.add_element 'logflush'
|
352
383
|
lf.add_element('log').text = 'policy'
|
353
|
-
lf.add_element('log_id').text = pol_id.to_s
|
354
384
|
lf.add_element('interval').text = "#{older_than} #{period}"
|
385
|
+
|
355
386
|
comps_elem = lf.add_element 'computers'
|
356
387
|
computers.each do |c|
|
357
388
|
id = Jamf::Computer.valid_id c, cnx: cnx
|
@@ -361,13 +392,41 @@ module Jamf
|
|
361
392
|
ce.add_element('id').text = id.to_s
|
362
393
|
end
|
363
394
|
|
395
|
+
# for debugging the xml...
|
396
|
+
#
|
397
|
+
# formatter = REXML::Formatters::Pretty.new(2)
|
398
|
+
# formatter.compact = true
|
399
|
+
# formatter.write(xml_doc, $stdout)
|
400
|
+
# puts
|
401
|
+
# return
|
402
|
+
|
403
|
+
# log flushes can be really slow
|
404
|
+
orig_timeout = cnx.timeout
|
405
|
+
cnx.timeout = 1800 unless orig_timeout && orig_timeout > 1800
|
406
|
+
|
364
407
|
# Do a DELETE request with a body.
|
365
|
-
cnx.delete(LOG_FLUSH_RSRC) do |req|
|
408
|
+
resp = cnx.c_cnx.delete(LOG_FLUSH_RSRC) do |req|
|
366
409
|
req.headers[Jamf::Connection::HTTP_CONTENT_TYPE_HEADER] = Jamf::Connection::MIME_XML
|
367
410
|
req.body = xml_doc.to_s
|
368
411
|
end
|
412
|
+
|
413
|
+
resp.body
|
414
|
+
ensure
|
415
|
+
cnx.timeout = orig_timeout
|
369
416
|
end
|
370
|
-
|
417
|
+
|
418
|
+
# validate the logflush params
|
419
|
+
# @return [Array<String>]
|
420
|
+
def self.validate_log_flush_params(older_than, period)
|
421
|
+
older_than = LOG_FLUSH_INTERVAL_INTEGERS[older_than]
|
422
|
+
raise Jamf::InvalidDataError, "older_than must be one of these integers: #{LOG_FLUSH_INTERVAL_INTEGERS.keys.join ', '}" unless older_than
|
423
|
+
|
424
|
+
period = LOG_FLUSH_INTERVAL_PERIODS[period]
|
425
|
+
raise Jamf::InvalidDataError, "period must be one of these symbols: :#{LOG_FLUSH_INTERVAL_PERIODS.keys.join ', :'}" unless period
|
426
|
+
|
427
|
+
[older_than, period]
|
428
|
+
end
|
429
|
+
private_class_method :validate_log_flush_params
|
371
430
|
|
372
431
|
# Attributes
|
373
432
|
######################
|
@@ -751,7 +810,7 @@ module Jamf
|
|
751
810
|
@management_account = amaint[:management_account]
|
752
811
|
@accounts = amaint[:accounts]
|
753
812
|
|
754
|
-
@packages = @init_data[:package_configuration][:packages]
|
813
|
+
@packages = @init_data[:package_configuration][:packages] || []
|
755
814
|
|
756
815
|
@scripts = @init_data[:scripts]
|
757
816
|
|
@@ -815,6 +874,7 @@ module Jamf
|
|
815
874
|
#
|
816
875
|
def enabled=(new_val)
|
817
876
|
return if @enabled == new_val
|
877
|
+
|
818
878
|
@enabled = Jamf::Validate.boolean new_val
|
819
879
|
@need_to_update = true
|
820
880
|
end
|
@@ -868,9 +928,7 @@ module Jamf
|
|
868
928
|
|
869
929
|
# if the event is not 'none' and attempts is <= 0,
|
870
930
|
# set events to 1, or the API won't accept it
|
871
|
-
|
872
|
-
@retry_attempts = 1 unless @retry_attempts.positive?
|
873
|
-
end
|
931
|
+
@retry_attempts = 1 if !(evt == RETRY_EVENTS[:none]) && !@retry_attempts.positive?
|
874
932
|
|
875
933
|
@retry_event = evt
|
876
934
|
@need_to_update = true
|
@@ -934,6 +992,7 @@ module Jamf
|
|
934
992
|
#
|
935
993
|
def target_drive=(path_to_drive)
|
936
994
|
raise Jamf::InvalidDataError, 'Path to target drive must be absolute' unless path_to_drive.to_s.start_with? '/'
|
995
|
+
|
937
996
|
@target_drive = path_to_drive.to_s
|
938
997
|
@need_to_update = true
|
939
998
|
end
|
@@ -946,6 +1005,7 @@ module Jamf
|
|
946
1005
|
#
|
947
1006
|
def offline=(new_val)
|
948
1007
|
raise Jamf::InvalidDataError, 'New value must be boolean true or false' unless Jamf::TRUE_FALSE.include? new_val
|
1008
|
+
|
949
1009
|
@offline = new_val
|
950
1010
|
@need_to_update = true
|
951
1011
|
end
|
@@ -960,6 +1020,7 @@ module Jamf
|
|
960
1020
|
#
|
961
1021
|
def set_trigger_event(type, new_val)
|
962
1022
|
raise Jamf::InvalidDataError, "Trigger type must be one of #{TRIGGER_EVENTS.keys.join(', ')}" unless TRIGGER_EVENTS.key?(type)
|
1023
|
+
|
963
1024
|
if type == :custom
|
964
1025
|
raise Jamf::InvalidDataError, 'Custom triggers must be Strings' unless new_val.is_a? String
|
965
1026
|
else
|
@@ -977,6 +1038,7 @@ module Jamf
|
|
977
1038
|
#
|
978
1039
|
def server_side_activation=(activation)
|
979
1040
|
raise Jamf::InvalidDataError, 'Activation must be a Time' unless activation.is_a? Time
|
1041
|
+
|
980
1042
|
@server_side_limitations[:activation] = activation
|
981
1043
|
@need_to_update = true
|
982
1044
|
end
|
@@ -989,6 +1051,7 @@ module Jamf
|
|
989
1051
|
#
|
990
1052
|
def server_side_expiration=(expiration)
|
991
1053
|
raise Jamf::InvalidDataError, 'Expiration must be a Time' unless expiration.is_a? Time
|
1054
|
+
|
992
1055
|
@server_side_limitations[:expiration] = expiration
|
993
1056
|
@need_to_update = true
|
994
1057
|
end
|
@@ -999,6 +1062,7 @@ module Jamf
|
|
999
1062
|
#
|
1000
1063
|
def verify_startup_disk=(bool)
|
1001
1064
|
return if @verify_startup_disk == bool
|
1065
|
+
|
1002
1066
|
@verify_startup_disk = Jamf::Validate.boolean bool
|
1003
1067
|
@need_to_update = true
|
1004
1068
|
end
|
@@ -1007,6 +1071,7 @@ module Jamf
|
|
1007
1071
|
#
|
1008
1072
|
def permissions_repair=(bool)
|
1009
1073
|
return if @permissions_repair == bool
|
1074
|
+
|
1010
1075
|
@permissions_repair = Jamf::Validate.boolean bool
|
1011
1076
|
@need_to_update = true
|
1012
1077
|
end
|
@@ -1015,6 +1080,7 @@ module Jamf
|
|
1015
1080
|
#
|
1016
1081
|
def recon=(bool)
|
1017
1082
|
return if @recon == bool
|
1083
|
+
|
1018
1084
|
@recon = Jamf::Validate.boolean bool
|
1019
1085
|
@need_to_update = true
|
1020
1086
|
end
|
@@ -1024,6 +1090,7 @@ module Jamf
|
|
1024
1090
|
#
|
1025
1091
|
def fix_byhost=(bool)
|
1026
1092
|
return if @fix_byhost == bool
|
1093
|
+
|
1027
1094
|
@fix_byhost = Jamf::Validate.boolean bool
|
1028
1095
|
@need_to_update = true
|
1029
1096
|
end
|
@@ -1032,6 +1099,7 @@ module Jamf
|
|
1032
1099
|
#
|
1033
1100
|
def reset_name=(bool)
|
1034
1101
|
return if @reset_name == bool
|
1102
|
+
|
1035
1103
|
@reset_name = Jamf::Validate.boolean bool
|
1036
1104
|
@need_to_update = true
|
1037
1105
|
end
|
@@ -1040,6 +1108,7 @@ module Jamf
|
|
1040
1108
|
#
|
1041
1109
|
def flush_system_cache=(bool)
|
1042
1110
|
return if @flush_system_cache == bool
|
1111
|
+
|
1043
1112
|
@flush_system_cache = Jamf::Validate.boolean bool
|
1044
1113
|
@need_to_update = true
|
1045
1114
|
end # see attr_reader :recon
|
@@ -1048,6 +1117,7 @@ module Jamf
|
|
1048
1117
|
#
|
1049
1118
|
def install_cached_pkgs=(bool)
|
1050
1119
|
return if @install_cached_pkgs == bool
|
1120
|
+
|
1051
1121
|
@install_cached_pkgs = Jamf::Validate.boolean bool
|
1052
1122
|
@need_to_update = true
|
1053
1123
|
end
|
@@ -1056,6 +1126,7 @@ module Jamf
|
|
1056
1126
|
#
|
1057
1127
|
def flush_user_cache=(bool)
|
1058
1128
|
return if @flush_user_cache == bool
|
1129
|
+
|
1059
1130
|
@flush_user_cache = Jamf::Validate.boolean bool
|
1060
1131
|
@need_to_update = true
|
1061
1132
|
end
|
@@ -1071,6 +1142,7 @@ module Jamf
|
|
1071
1142
|
#
|
1072
1143
|
def no_user_logged_in=(no_user_option)
|
1073
1144
|
raise Jamf::InvalidDataError, "no_user_logged_in options: #{NO_USER_LOGGED_IN.join(', ')}" unless NO_USER_LOGGED_IN.include? no_user_option
|
1145
|
+
|
1074
1146
|
@reboot_options[:no_user_logged_in] = no_user_option
|
1075
1147
|
@need_to_update = true
|
1076
1148
|
end
|
@@ -1083,6 +1155,7 @@ module Jamf
|
|
1083
1155
|
#
|
1084
1156
|
def user_logged_in=(logged_in_option)
|
1085
1157
|
raise Jamf::InvalidDataError, "user_logged_in options: #{USER_LOGGED_IN.join(', ')}" unless USER_LOGGED_IN.include? logged_in_option
|
1158
|
+
|
1086
1159
|
@reboot_options[:user_logged_in] = logged_in_option
|
1087
1160
|
@need_to_update = true
|
1088
1161
|
end
|
@@ -1095,6 +1168,7 @@ module Jamf
|
|
1095
1168
|
#
|
1096
1169
|
def reboot_message=(message)
|
1097
1170
|
raise Jamf::InvalidDataError, 'Reboot message must be a String' unless message.is_a? String
|
1171
|
+
|
1098
1172
|
@reboot_options[:message] = message
|
1099
1173
|
@need_to_update = true
|
1100
1174
|
end
|
@@ -1107,6 +1181,7 @@ module Jamf
|
|
1107
1181
|
# @return [void] description of returned object
|
1108
1182
|
def user_message_start=(message)
|
1109
1183
|
raise Jamf::InvalidDataError, 'User message must be a String' unless message.is_a? String
|
1184
|
+
|
1110
1185
|
@user_message_start = message
|
1111
1186
|
@need_to_update = true
|
1112
1187
|
end
|
@@ -1118,6 +1193,7 @@ module Jamf
|
|
1118
1193
|
# @return [void] description of returned object
|
1119
1194
|
def user_message_end=(message)
|
1120
1195
|
raise Jamf::InvalidDataError, 'User message must be a String' unless message.is_a? String
|
1196
|
+
|
1121
1197
|
@user_message_finish = message
|
1122
1198
|
@need_to_update = true
|
1123
1199
|
end
|
@@ -1133,6 +1209,7 @@ module Jamf
|
|
1133
1209
|
#
|
1134
1210
|
def startup_disk=(startup_disk_option)
|
1135
1211
|
raise Jamf::InvalidDataError, "#{startup_disk_option} is not a valid Startup Disk" unless startup_disk_option.is_a? String
|
1212
|
+
|
1136
1213
|
@reboot_options[:startup_disk] = 'Specify Local Startup Disk'
|
1137
1214
|
self.specify_startup = startup_disk_option
|
1138
1215
|
@need_to_update = true
|
@@ -1147,6 +1224,7 @@ module Jamf
|
|
1147
1224
|
#
|
1148
1225
|
def specify_startup=(startup_volume)
|
1149
1226
|
raise Jamf::InvalidDataError, "#{startup_volume} is not a valid Startup Disk" unless startup_volume.is_a? String
|
1227
|
+
|
1150
1228
|
@reboot_options[:specify_startup] = startup_volume
|
1151
1229
|
@need_to_update = true
|
1152
1230
|
end
|
@@ -1172,6 +1250,7 @@ module Jamf
|
|
1172
1250
|
#
|
1173
1251
|
def minutes_until_reboot=(minutes)
|
1174
1252
|
raise Jamf::InvalidDataError, 'Minutes until reboot must be an Integer' unless minutes.is_a? Integer
|
1253
|
+
|
1175
1254
|
@reboot_options[:minutes_until_reboot] = minutes
|
1176
1255
|
@need_to_update = true
|
1177
1256
|
end
|
@@ -1185,6 +1264,7 @@ module Jamf
|
|
1185
1264
|
#
|
1186
1265
|
def file_vault_2_reboot=(fv_bool)
|
1187
1266
|
raise Jamf::InvalidDataError, 'FileVault 2 Reboot must be a Boolean' unless fv_bool.jss_boolean?
|
1267
|
+
|
1188
1268
|
@reboot_options[:file_vault_2_reboot] = fv_bool
|
1189
1269
|
@need_to_update = true
|
1190
1270
|
end
|
@@ -1206,6 +1286,7 @@ module Jamf
|
|
1206
1286
|
#
|
1207
1287
|
def run_command=(command)
|
1208
1288
|
raise Jamf::InvalidDataError, 'Command to run must be a String' unless command.is_a? String
|
1289
|
+
|
1209
1290
|
@files_processes[:run_command] = command
|
1210
1291
|
@need_to_update = true
|
1211
1292
|
end
|
@@ -1262,7 +1343,7 @@ module Jamf
|
|
1262
1343
|
#
|
1263
1344
|
def search_by_path
|
1264
1345
|
if @files_processes[:search_by_path].nil?
|
1265
|
-
|
1346
|
+
nil
|
1266
1347
|
else
|
1267
1348
|
Pathname.new @files_processes[:search_by_path]
|
1268
1349
|
end
|
@@ -1289,6 +1370,7 @@ module Jamf
|
|
1289
1370
|
#
|
1290
1371
|
def set_search_by_path(path, delete = false)
|
1291
1372
|
raise Jamf::InvalidDataError, 'Path to search for must be a String or a Pathname' unless path.is_a?(String) || path.is_a?(Pathname)
|
1373
|
+
|
1292
1374
|
@files_processes[:search_by_path] = path.to_s
|
1293
1375
|
@files_processes[:delete_file] = delete ? true : false
|
1294
1376
|
@need_to_update = true
|
@@ -1308,6 +1390,7 @@ module Jamf
|
|
1308
1390
|
#
|
1309
1391
|
def spotlight_search=(term)
|
1310
1392
|
raise Jamf::InvalidDataError, 'Spotlight search term must be a String' unless term.is_a? String
|
1393
|
+
|
1311
1394
|
@files_processes[:spotlight_search] = term
|
1312
1395
|
@need_to_update = true
|
1313
1396
|
end
|
@@ -1326,6 +1409,7 @@ module Jamf
|
|
1326
1409
|
#
|
1327
1410
|
def locate_file=(term)
|
1328
1411
|
raise Jamf::InvalidDataError, 'Term to locate must be a String' unless term.is_a? String
|
1412
|
+
|
1329
1413
|
@files_processes[:locate_file] = term
|
1330
1414
|
@need_to_update = true
|
1331
1415
|
end
|
@@ -1571,7 +1655,6 @@ module Jamf
|
|
1571
1655
|
@directory_bindings
|
1572
1656
|
end
|
1573
1657
|
|
1574
|
-
|
1575
1658
|
# Remove a directory binding from this policy by name or id
|
1576
1659
|
#
|
1577
1660
|
# @param identifier [String,Integer] the name or id of the directory binding to remove
|
@@ -1596,7 +1679,6 @@ module Jamf
|
|
1596
1679
|
@dock_items.map { |p| p[:name] }
|
1597
1680
|
end
|
1598
1681
|
|
1599
|
-
|
1600
1682
|
###### Printers
|
1601
1683
|
|
1602
1684
|
# Add a specific printer object to the policy.
|
@@ -1661,7 +1743,7 @@ module Jamf
|
|
1661
1743
|
|
1662
1744
|
name = Jamf::DockItem.map_all_ids_to(:name, cnx: @cnx)[id]
|
1663
1745
|
|
1664
|
-
@dock_items << {id: id, name: name, action: DOCK_ITEM_ACTIONS[action]}
|
1746
|
+
@dock_items << { id: id, name: name, action: DOCK_ITEM_ACTIONS[action] }
|
1665
1747
|
|
1666
1748
|
@need_to_update = true
|
1667
1749
|
@dock_items
|
@@ -1677,24 +1759,18 @@ module Jamf
|
|
1677
1759
|
|
1678
1760
|
# @return [Array] the id's of the printers handled by the policy
|
1679
1761
|
def printer_ids
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
return []
|
1684
|
-
end
|
1762
|
+
@printers.map { |p| p[:id] }
|
1763
|
+
rescue TypeError
|
1764
|
+
[]
|
1685
1765
|
end
|
1686
1766
|
|
1687
1767
|
# @return [Array] the names of the printers handled by the policy
|
1688
1768
|
def printer_names
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
return []
|
1693
|
-
end
|
1769
|
+
@printers.map { |p| p[:name] }
|
1770
|
+
rescue TypeError
|
1771
|
+
[]
|
1694
1772
|
end
|
1695
1773
|
|
1696
|
-
|
1697
|
-
|
1698
1774
|
###### Disk Encryption
|
1699
1775
|
|
1700
1776
|
# Sets the Disk Encryption application to "Remediate" and sets the remediation key type to individual.
|
@@ -1703,12 +1779,12 @@ module Jamf
|
|
1703
1779
|
#
|
1704
1780
|
# @return [Void]
|
1705
1781
|
#
|
1706
|
-
def reissue_key
|
1782
|
+
def reissue_key
|
1707
1783
|
if @disk_encryption[:action] != DISK_ENCRYPTION_ACTIONS[:remediate]
|
1708
1784
|
# Setting New Action
|
1709
1785
|
hash = {
|
1710
1786
|
action: DISK_ENCRYPTION_ACTIONS[:remediate],
|
1711
|
-
remediate_key_type:
|
1787
|
+
remediate_key_type: 'Individual'
|
1712
1788
|
}
|
1713
1789
|
|
1714
1790
|
@disk_encryption = hash
|
@@ -1716,12 +1792,10 @@ module Jamf
|
|
1716
1792
|
|
1717
1793
|
else
|
1718
1794
|
# Update
|
1719
|
-
|
1795
|
+
nil
|
1720
1796
|
end
|
1721
|
-
|
1722
1797
|
end
|
1723
1798
|
|
1724
|
-
|
1725
1799
|
# Sets the Disk Encryption application to "Apply" and sets the correct disk encryption configuration ID using either the name or id.
|
1726
1800
|
#
|
1727
1801
|
# @author Tyler Morgan
|
@@ -1729,7 +1803,6 @@ module Jamf
|
|
1729
1803
|
# @return [Void]
|
1730
1804
|
#
|
1731
1805
|
def apply_encryption_configuration(identifier)
|
1732
|
-
|
1733
1806
|
id = Jamf::DiskEncryptionConfiguration.valid_id identifier
|
1734
1807
|
|
1735
1808
|
return if id.nil?
|
@@ -1744,14 +1817,13 @@ module Jamf
|
|
1744
1817
|
@need_to_update = true
|
1745
1818
|
end
|
1746
1819
|
|
1747
|
-
|
1748
1820
|
# Removes the Disk Encryption settings associated with this specific policy.
|
1749
1821
|
#
|
1750
1822
|
# @author Tyler Morgan
|
1751
1823
|
#
|
1752
1824
|
# @return [Void]
|
1753
1825
|
#
|
1754
|
-
def remove_encryption_configuration
|
1826
|
+
def remove_encryption_configuration
|
1755
1827
|
hash = {
|
1756
1828
|
action: DISK_ENCRYPTION_ACTIONS[:none]
|
1757
1829
|
}
|
@@ -1774,16 +1846,16 @@ module Jamf
|
|
1774
1846
|
|
1775
1847
|
management_data = {}
|
1776
1848
|
|
1777
|
-
if
|
1778
|
-
raise Jamf::MissingDataError,
|
1849
|
+
if %i[change_pw reset_pw].include?(action)
|
1850
|
+
raise Jamf::MissingDataError, ':password must be provided when changing management account password' if opts[:password].nil?
|
1779
1851
|
|
1780
1852
|
management_data = {
|
1781
1853
|
action: MGMT_ACCOUNT_ACTIONS[action],
|
1782
1854
|
managed_password: opts[:password]
|
1783
1855
|
}
|
1784
|
-
elsif
|
1785
|
-
raise Jamf::MissingDataError,
|
1786
|
-
raise Jamf::InvalidDataError,
|
1856
|
+
elsif %i[reset_random generate_pw].include?(action)
|
1857
|
+
raise Jamf::MissingDataError, ':password_length must be provided when setting a random password' if opts[:password_length].nil?
|
1858
|
+
raise Jamf::InvalidDataError, ':password_length must be an Integer' unless opts[:password_length].is_a? Integer
|
1787
1859
|
|
1788
1860
|
management_data = {
|
1789
1861
|
action: MGMT_ACCOUNT_ACTIONS[action],
|
@@ -1800,21 +1872,23 @@ module Jamf
|
|
1800
1872
|
@need_to_update = true
|
1801
1873
|
|
1802
1874
|
@management_account
|
1803
|
-
|
1804
1875
|
end
|
1805
1876
|
|
1806
|
-
#
|
1877
|
+
# @deprecated The API no longer sends SHA256 hashed password data, and instead
|
1878
|
+
# only has a string of asterisks, meaning we can no longer use it to validate
|
1879
|
+
# passwords before attempting to use them. Instead, the processes that use
|
1880
|
+
# the password will fail on their own if the pw is not valid.
|
1807
1881
|
#
|
1808
|
-
#
|
1882
|
+
# This method remains defined for backward-compatibility with any existing
|
1883
|
+
# code that calls it. but it will always return true. Itwill be removed in
|
1884
|
+
# a future version
|
1809
1885
|
#
|
1810
|
-
# @
|
1886
|
+
# @param password[String] ignored
|
1811
1887
|
#
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
return Digest::SHA256.hexdigest(password).to_s == @management_account[:managed_password_sha256].to_s
|
1888
|
+
# @return [TrueClass] Allow the process calling this to continue.
|
1889
|
+
#
|
1890
|
+
def verify_management_password(_password = nil)
|
1891
|
+
true
|
1818
1892
|
end
|
1819
1893
|
|
1820
1894
|
###### Actions
|
@@ -1829,17 +1903,22 @@ module Jamf
|
|
1829
1903
|
#
|
1830
1904
|
def run(show_output = false)
|
1831
1905
|
return nil unless enabled?
|
1906
|
+
|
1832
1907
|
output = Jamf::Client.run_jamf('policy', "-id #{id}", show_output)
|
1833
1908
|
return nil if output.include? 'No policies were found for the ID'
|
1909
|
+
|
1834
1910
|
$CHILD_STATUS.exitstatus.zero? ? true : false
|
1835
1911
|
end
|
1836
1912
|
alias execute run
|
1837
1913
|
|
1838
|
-
# Flush logs for this policy older than
|
1839
|
-
#
|
1840
|
-
#
|
1914
|
+
# Flush logs for this policy older than a given time period.
|
1915
|
+
#
|
1916
|
+
# IMPORTANT: from the Jamf Developer Site:
|
1917
|
+
# The ability to flush logs is currently only supported for flushing all logs
|
1918
|
+
# for a given policy or all logs for a given computer. There is no support for
|
1919
|
+
# flushing logs for a given policy and computer combination.
|
1841
1920
|
#
|
1842
|
-
# With no parameters,
|
1921
|
+
# With no parameters, will flush all logs for the policy
|
1843
1922
|
#
|
1844
1923
|
# NOTE: Currently the API doesn't have a way to flush only failed policies.
|
1845
1924
|
#
|
@@ -1851,19 +1930,16 @@ module Jamf
|
|
1851
1930
|
#
|
1852
1931
|
# @param period[Symbol] :days, :weeks, :months, or :years
|
1853
1932
|
#
|
1854
|
-
# @param computers[Array<Integer,String>] Identifiers of the target computers
|
1855
|
-
# either ids, names, SNs, macaddrs, or UDIDs
|
1856
|
-
#
|
1857
1933
|
# @return [void]
|
1858
1934
|
#
|
1859
|
-
def flush_logs(older_than: 0, period: :days
|
1860
|
-
raise Jamf::NoSuchItemError, "Policy doesn't exist in the JSS. Use #
|
1935
|
+
def flush_logs(older_than: 0, period: :days)
|
1936
|
+
raise Jamf::NoSuchItemError, "Policy doesn't exist in the JSS. Use #save first." unless @in_jss
|
1861
1937
|
|
1862
1938
|
Jamf::Policy.flush_logs(
|
1863
1939
|
@id,
|
1864
1940
|
older_than: older_than,
|
1865
1941
|
period: period,
|
1866
|
-
|
1942
|
+
cnx: @cnx
|
1867
1943
|
)
|
1868
1944
|
end
|
1869
1945
|
|
@@ -1944,6 +2020,7 @@ module Jamf
|
|
1944
2020
|
|
1945
2021
|
id = Jamf::Script.valid_id identifier, cnx: @cnx
|
1946
2022
|
raise Jamf::NoSuchItemError, "No script matches '#{identifier}'" unless id
|
2023
|
+
|
1947
2024
|
id
|
1948
2025
|
end
|
1949
2026
|
|
@@ -1963,12 +2040,13 @@ module Jamf
|
|
1963
2040
|
else Jamf::Validate.integer(opts[:position])
|
1964
2041
|
end
|
1965
2042
|
|
1966
|
-
|
1967
|
-
|
2043
|
+
# if the given position is past the end, set it to -1 (the end)
|
2044
|
+
opts[:position] = -1 if opts[:position] > @directory_bindings.size
|
2045
|
+
|
2046
|
+
id = Jamf::DirectoryBinding.valid_id identifier, cnx: @cnx
|
2047
|
+
raise Jamf::NoSuchItemError, "No directory binding matches '#{identifier}'" unless id
|
1968
2048
|
|
1969
|
-
|
1970
|
-
raise Jamf::NoSuchItemError, "No directory binding matches '#{identifier}'" unless id
|
1971
|
-
id
|
2049
|
+
id
|
1972
2050
|
end
|
1973
2051
|
|
1974
2052
|
# Raises an error if the printer being added isn't valid, additionally checks the options and sets defaults where possible.
|
@@ -1994,14 +2072,17 @@ module Jamf
|
|
1994
2072
|
raise Jamf::MissingDataError, "action must be provided, must be one of :#{PRINTER_ACTIONS.keys.join(':,')}." if opts[:action].nil?
|
1995
2073
|
raise Jamf::InvalidDataError, "action must be one of :#{PRINTER_ACTIONS.keys.join(',:')}." unless PRINTER_ACTIONS.keys.include? opts[:action]
|
1996
2074
|
|
1997
|
-
|
1998
2075
|
# Checks if the make_default option is valid, and sets the default if needed.
|
1999
|
-
|
2076
|
+
unless opts[:make_default].is_a?(TrueClass) || opts[:make_default].is_a?(FalseClass) || opts[:make_default].nil?
|
2077
|
+
raise Jamf::InvalidDataError,
|
2078
|
+
'make_default must be either true or false.'
|
2079
|
+
end
|
2000
2080
|
|
2001
2081
|
opts[:make_default] = false if opts[:make_default].nil?
|
2002
2082
|
|
2003
2083
|
id = Jamf::Printer.valid_id identifier, cnx: @cnx
|
2004
2084
|
raise Jamf::NoSuchItemError, "No printer matches '#{identifier}'" unless id
|
2085
|
+
|
2005
2086
|
id
|
2006
2087
|
end
|
2007
2088
|
|
@@ -2081,7 +2162,7 @@ module Jamf
|
|
2081
2162
|
|
2082
2163
|
disk_encryption = obj.add_element 'disk_encryption'
|
2083
2164
|
|
2084
|
-
@disk_encryption.each do |k,v|
|
2165
|
+
@disk_encryption.each do |k, v|
|
2085
2166
|
disk_encryption.add_element(k.to_s).text = v.to_s
|
2086
2167
|
end
|
2087
2168
|
|
@@ -476,7 +476,10 @@ module Jamf
|
|
476
476
|
item_id = validate_item(:target, key, item)
|
477
477
|
return if @targets[key]&.include?(item_id)
|
478
478
|
|
479
|
-
|
479
|
+
if @exclusions[key]&.include?(item_id)
|
480
|
+
raise Jamf::AlreadyExistsError,
|
481
|
+
"Can't set #{key} target to '#{item}' because it's already an explicit exclusion."
|
482
|
+
end
|
480
483
|
|
481
484
|
@targets[key] << item_id
|
482
485
|
@all_targets = false
|
@@ -775,7 +778,7 @@ module Jamf
|
|
775
778
|
################
|
776
779
|
def scoped_machines
|
777
780
|
scoped_machines = {}
|
778
|
-
@target_class.all_objects(cnx: container.cnx).each do |machine|
|
781
|
+
@target_class.all_objects(:refresh, cnx: container.cnx).each do |machine|
|
779
782
|
scoped_machines[machine.id] = machine.name if in_scope? machine
|
780
783
|
end
|
781
784
|
scoped_machines
|
@@ -19,14 +19,14 @@
|
|
19
19
|
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
20
20
|
# KIND, either express or implied. See the Apache License for the specific
|
21
21
|
# language governing permissions and limitations under the Apache License.
|
22
|
-
|
23
|
-
#
|
22
|
+
|
23
|
+
# frozen_string_literal: true
|
24
24
|
|
25
25
|
module Jamf
|
26
26
|
|
27
27
|
# This module should be mixed in to Jamf::Computer and Jamf::ComputerGroup
|
28
28
|
#
|
29
|
-
# It provides access to the macos-managed-software-updates JPAPI resource for
|
29
|
+
# It provides access to the macos-managed-software-updates JPAPI resource for
|
30
30
|
# managed OS update commands to managed macs running Big Sur or higher.
|
31
31
|
#
|
32
32
|
module MacOSManagedUpdates
|
@@ -37,7 +37,7 @@ module Jamf
|
|
37
37
|
includer.extend(ClassMethods)
|
38
38
|
end
|
39
39
|
|
40
|
-
# These resources in the Jamf Pro API can be used to send Managed macOS
|
40
|
+
# These resources in the Jamf Pro API can be used to send Managed macOS
|
41
41
|
# updates to clients running Big Sur or higher
|
42
42
|
MANAGED_SW_UPDATES_RSRC = 'v1/macos-managed-software-updates'
|
43
43
|
|
@@ -45,7 +45,7 @@ module Jamf
|
|
45
45
|
MANAGED_SW_UPDATES_AVAILABLE_VERSIONS_RSRC = "#{MANAGED_SW_UPDATES_RSRC}/available-updates"
|
46
46
|
|
47
47
|
# POSTing JSON data to this resource will send the MDM commands to install os updates
|
48
|
-
# For details about the data to send, see
|
48
|
+
# For details about the data to send, see
|
49
49
|
# https://developer.jamf.com/jamf-pro/reference/post_v1-macos-managed-software-updates-send-updates
|
50
50
|
MANAGED_SW_UPDATES_SEND_UPDATES_RSRC = "#{MANAGED_SW_UPDATES_RSRC}/send-updates"
|
51
51
|
|
@@ -53,6 +53,12 @@ module Jamf
|
|
53
53
|
DOWNLOAD_AND_INSTALL = 'DOWNLOAD_AND_INSTALL'
|
54
54
|
DOWNLOAD_ONLY = 'DOWNLOAD_ONLY'
|
55
55
|
|
56
|
+
# for easier use of these values as the updateAction
|
57
|
+
UPDATE_ACTIONS = {
|
58
|
+
install: DOWNLOAD_AND_INSTALL,
|
59
|
+
download: DOWNLOAD_ONLY
|
60
|
+
}
|
61
|
+
|
56
62
|
# Class Methods
|
57
63
|
#####################################
|
58
64
|
module ClassMethods
|
@@ -73,48 +79,52 @@ module Jamf
|
|
73
79
|
|
74
80
|
# Send the os update command to target Computers or a ComputerGroup
|
75
81
|
#
|
76
|
-
# @param updateAction [
|
82
|
+
# @param updateAction [Symbol] Required. Use :install to send the
|
83
|
+
# DOWNLOAD_AND_INSTALL action, or :download to send DOWNLOAD_ONLY
|
77
84
|
#
|
78
|
-
# @param deviceIds [String, Integer, Array<String, Integer>] Identifiers for the
|
85
|
+
# @param deviceIds [String, Integer, Array<String, Integer>] Identifiers for the
|
79
86
|
# computer targets. Required if no groupId is given.
|
80
87
|
#
|
81
88
|
# @param groupId [String, Integer] Identifier for the computer group target.
|
82
|
-
# Requied if no
|
89
|
+
# Requied if no deviceIds are given.
|
83
90
|
#
|
84
|
-
# @param maxDeferrals [Integer] Allow users to defer the update the provided number
|
85
|
-
# of times before macOS forces the update. If a value is provided, the Software
|
86
|
-
# Update will use the InstallLater install action. MaxDeferral is ignored if using the
|
87
|
-
#
|
91
|
+
# @param maxDeferrals [Integer] Allow users to defer the update the provided number
|
92
|
+
# of times before macOS forces the update. If a value is provided, the Software
|
93
|
+
# Update will use the InstallLater install action. MaxDeferral is ignored if using the
|
94
|
+
# :download updateAction.
|
88
95
|
#
|
89
|
-
# @param version [String] The OS version to install. If no value is provided, the
|
96
|
+
# @param version [String] The OS version to install. If no value is provided, the
|
90
97
|
# version will default to latest version based on device eligibility.
|
91
98
|
#
|
92
99
|
# @param skipVersionVerification [Boolean] Should the specified version be installed
|
93
100
|
# even it it isn't applicable to this machine? If no value is provided, will default to false.
|
94
|
-
# If true, the specified version will be forced to complete
|
95
|
-
# install action.
|
101
|
+
# If true, the specified version will be forced to complete the :install updateAction.
|
96
102
|
#
|
97
103
|
# @param applyMajorUpdate [Boolean] Available only when updating to the latest version
|
98
104
|
# based on device eligibility. Defaults to false. If false the calculated latest version
|
99
105
|
# will only include minor version updates. If a value is provided, the calculated latest
|
100
106
|
# version will include minor and major version updates.
|
101
107
|
#
|
102
|
-
# @param forceRestart [Boolean] Will default to false. Can only be true if updateAction
|
103
|
-
# is
|
104
|
-
# If true, the DownloadAndInstall action is performed, a restart will be forced.
|
105
|
-
# MaxDeferral will be ignored if true.
|
108
|
+
# @param forceRestart [Boolean] Will default to false. Can only be true if updateAction
|
109
|
+
# is :install and the target devices are on macOs 11 or higher.
|
110
|
+
# If true, the DownloadAndInstall action is performed, a restart will be forced.
|
111
|
+
# MaxDeferral will be ignored if true.
|
106
112
|
#
|
107
|
-
# @param cnx [Jamf::Connection] The API connection to use. Defaults to Jamf.cnx
|
113
|
+
# @param cnx [Jamf::Connection] The API connection to use. Defaults to Jamf.cnx
|
108
114
|
#
|
109
|
-
# @return [Jamf::OAPISchemas::MacOsManagedSoftwareUpdateResponse]
|
115
|
+
# @return [Jamf::OAPISchemas::MacOsManagedSoftwareUpdateResponse]
|
110
116
|
########################
|
111
117
|
def send_managed_os_update(updateAction:, deviceIds: nil, groupId: nil, maxDeferrals: nil, version: nil, skipVersionVerification: false, applyMajorUpdate: false, forceRestart: false, cnx: Jamf.cnx)
|
112
|
-
|
118
|
+
action_to_send = UPDATE_ACTIONS.value?(updateAction) ? updateAction : UPDATE_ACTIONS[updateAction]
|
119
|
+
|
120
|
+
raise ArgumentError, "Unknown updateAction, must be one of: #{UPDATE_ACTIONS.keys.join ', '}" unless action_to_send
|
121
|
+
|
122
|
+
if self == Jamf::Computer
|
113
123
|
raise ArgumentError, 'Must provide one or more deviceIds' unless deviceIds
|
114
124
|
elsif self == Jamf::ComputerGroup
|
115
125
|
raise ArgumentError, 'Must provide a groupId' unless groupId
|
116
126
|
else
|
117
|
-
raise Jamf::UnsupportedError, 'This method is only available for Jamf::Computer and Jamf::ComputerGroup'
|
127
|
+
raise Jamf::UnsupportedError, 'This method is only available for Jamf::Computer and Jamf::ComputerGroup'
|
118
128
|
end
|
119
129
|
|
120
130
|
if version
|
@@ -124,9 +134,9 @@ module Jamf
|
|
124
134
|
|
125
135
|
if deviceIds
|
126
136
|
deviceIds = [deviceIds] unless deviceIds.is_a?(Array)
|
127
|
-
deviceIds.map! { |id| valid_id id }
|
137
|
+
deviceIds.map! { |id| valid_id id, cnx: cnx }
|
128
138
|
end
|
129
|
-
groupId = valid_id
|
139
|
+
groupId = valid_id(groupId, cnx: cnx) if groupId
|
130
140
|
|
131
141
|
data = {}
|
132
142
|
# ids in the JPAPI are string containing integers
|
@@ -137,11 +147,11 @@ module Jamf
|
|
137
147
|
data[:version] = version if version
|
138
148
|
data[:skipVersionVerification] = skipVersionVerification if skipVersionVerification
|
139
149
|
data[:applyMajorUpdate] = applyMajorUpdate if applyMajorUpdate
|
140
|
-
data[:updateAction] =
|
141
|
-
data[:forceRestart] = forceRestart if forceRestart
|
142
|
-
|
150
|
+
data[:updateAction] = action_to_send
|
151
|
+
data[:forceRestart] = forceRestart if forceRestart
|
152
|
+
|
143
153
|
payload = Jamf::OAPISchemas::MacOsManagedSoftwareUpdate.new(data).to_json
|
144
|
-
|
154
|
+
|
145
155
|
result = cnx.jp_post MANAGED_SW_UPDATES_SEND_UPDATES_RSRC, payload
|
146
156
|
Jamf::OAPISchemas::MacOsManagedSoftwareUpdateResponse.new result
|
147
157
|
end
|
@@ -161,14 +171,14 @@ module Jamf
|
|
161
171
|
groupId = is_a?(Jamf::Computer) ? nil : @id
|
162
172
|
|
163
173
|
self.class.send_managed_os_update(
|
164
|
-
deviceIds: deviceIds,
|
165
|
-
groupId: groupId,
|
166
|
-
maxDeferrals: maxDeferrals,
|
167
|
-
version: version,
|
168
|
-
skipVersionVerification: skipVersionVerification,
|
169
|
-
applyMajorUpdate: applyMajorUpdate,
|
170
|
-
forceRestart: forceRestart,
|
171
|
-
updateAction: updateAction,
|
174
|
+
deviceIds: deviceIds,
|
175
|
+
groupId: groupId,
|
176
|
+
maxDeferrals: maxDeferrals,
|
177
|
+
version: version,
|
178
|
+
skipVersionVerification: skipVersionVerification,
|
179
|
+
applyMajorUpdate: applyMajorUpdate,
|
180
|
+
forceRestart: forceRestart,
|
181
|
+
updateAction: updateAction,
|
172
182
|
cnx: @cnx
|
173
183
|
)
|
174
184
|
end
|
data/lib/jamf/validate.rb
CHANGED
@@ -98,7 +98,9 @@ module Jamf
|
|
98
98
|
#
|
99
99
|
# @return [Object] the validated unique value
|
100
100
|
#
|
101
|
-
def self.doesnt_already_exist(klass, identifier, val, msg: nil, api: Jamf.cnx)
|
101
|
+
def self.doesnt_already_exist(klass, identifier, val, msg: nil, api: nil, cnx: Jamf.cnx)
|
102
|
+
cnx = api if api
|
103
|
+
|
102
104
|
return val unless klass.all(:refresh, cnx: cnx).map { |i| i[identifier] }.include? val
|
103
105
|
|
104
106
|
key = klass.real_lookup_key identifier
|
data/lib/jamf/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-jss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0b1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Lasell
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-04-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: CFPropertyList
|
@@ -824,9 +824,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
824
824
|
version: 2.6.3
|
825
825
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
826
826
|
requirements:
|
827
|
-
- - "
|
827
|
+
- - ">"
|
828
828
|
- !ruby/object:Gem::Version
|
829
|
-
version:
|
829
|
+
version: 1.3.1
|
830
830
|
requirements: []
|
831
831
|
rubygems_version: 3.0.3.1
|
832
832
|
signing_key:
|