ruby-jss 1.2.10 → 1.3.2

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.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +92 -1
  3. data/lib/jamf/api/abstract_classes/json_object.rb +1 -1
  4. data/lib/jamf/api/abstract_classes/prestage.rb +1 -1
  5. data/lib/jamf/api/connection.rb +7 -3
  6. data/lib/jamf/configuration.rb +7 -9
  7. data/lib/jamf/ruby_extensions.rb +1 -0
  8. data/lib/jamf/ruby_extensions/array.rb +1 -1
  9. data/lib/jamf/ruby_extensions/array/utils.rb +3 -3
  10. data/lib/jamf/ruby_extensions/dig.rb +52 -0
  11. data/lib/jss.rb +2 -0
  12. data/lib/jss/api_connection.rb +2 -29
  13. data/lib/jss/api_object.rb +15 -2
  14. data/lib/jss/api_object/directory_binding.rb +273 -0
  15. data/lib/jss/api_object/directory_binding_type.rb +90 -0
  16. data/lib/jss/api_object/directory_binding_type/active_directory.rb +502 -0
  17. data/lib/jss/api_object/directory_binding_type/admitmac.rb +525 -0
  18. data/lib/jss/api_object/directory_binding_type/centrify.rb +212 -0
  19. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  20. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  21. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  22. data/lib/jss/api_object/distribution_point.rb +95 -35
  23. data/lib/jss/api_object/dock_item.rb +137 -0
  24. data/lib/jss/api_object/mobile_device_application.rb +12 -0
  25. data/lib/jss/api_object/network_segment.rb +152 -58
  26. data/lib/jss/api_object/package.rb +106 -41
  27. data/lib/jss/api_object/policy.rb +379 -4
  28. data/lib/jss/api_object/printer.rb +440 -0
  29. data/lib/jss/api_object/scopable/scope.rb +24 -24
  30. data/lib/jss/composer.rb +1 -1
  31. data/lib/jss/utility.rb +8 -22
  32. data/lib/jss/version.rb +1 -1
  33. metadata +13 -2
@@ -174,7 +174,9 @@ module JSS
174
174
  change_pw: 'specified',
175
175
  generate_pw: 'random',
176
176
  enable_fv2: 'fileVaultEnable',
177
- disable_fv2: 'fileVaultDisable'
177
+ disable_fv2: 'fileVaultDisable',
178
+ reset_random: 'resetRandom',
179
+ reset_pw: 'reset'
178
180
  }.freeze
179
181
 
180
182
  PACKAGE_ACTIONS = {
@@ -191,6 +193,12 @@ module JSS
191
193
  after: 'After'
192
194
  }.freeze
193
195
 
196
+ DISK_ENCRYPTION_ACTIONS = {
197
+ apply: "apply",
198
+ remediate: "remediate",
199
+ none: "none"
200
+ }
201
+
194
202
  PRINTER_ACTIONS = {
195
203
  map: 'install',
196
204
  unmap: 'uninstall'
@@ -541,6 +549,7 @@ module JSS
541
549
 
542
550
  # @return [String] the message shown the user at policy end
543
551
  attr_reader :user_message_finish
552
+ alias user_message_end user_message_finish
544
553
 
545
554
  # @return [Hash]
546
555
  #
@@ -670,6 +679,7 @@ module JSS
670
679
  @disk_encryption = @init_data[:disk_encryption]
671
680
 
672
681
  @printers = @init_data[:printers]
682
+ @printers.shift
673
683
 
674
684
  # Not in jss yet
675
685
  end
@@ -914,6 +924,30 @@ module JSS
914
924
  end
915
925
  alias message= reboot_message=
916
926
 
927
+ # Set User Start Message
928
+ #
929
+ # @param user_message[String] Text of User Message
930
+ #
931
+ # @return [void] description of returned object
932
+ def user_message_start=(message)
933
+ raise JSS::InvalidDataError, 'User message must be a String' unless message.is_a? String
934
+ @user_message_start = message
935
+ @need_to_update = true
936
+ end
937
+
938
+ # Set User Finish Message
939
+ #
940
+ # @param user_message[String] Text of User Message
941
+ #
942
+ # @return [void] description of returned object
943
+ def user_message_end=(message)
944
+ raise JSS::InvalidDataError, 'User message must be a String' unless message.is_a? String
945
+ @user_message_finish = message
946
+ @need_to_update = true
947
+ end
948
+
949
+ alias user_message_finish= user_message_end=
950
+
917
951
  # Set Startup Disk
918
952
  # Only Supports 'Specify Local Startup Disk' at the moment
919
953
  #
@@ -1180,7 +1214,7 @@ module JSS
1180
1214
 
1181
1215
  # Remove a package from this policy by name or id
1182
1216
  #
1183
- # @param identfier [String,Integer] the name or id of the package to remove
1217
+ # @param identifier [String,Integer] the name or id of the package to remove
1184
1218
  #
1185
1219
  # @return [Array, nil] the new packages array or nil if no change
1186
1220
  #
@@ -1270,7 +1304,7 @@ module JSS
1270
1304
 
1271
1305
  # Remove a script from this policy by name or id
1272
1306
  #
1273
- # @param identfier [String,Integer] the name or id of the script to remove
1307
+ # @param identifier [String,Integer] the name or id of the script to remove
1274
1308
  #
1275
1309
  # @return [Array, nil] the new scripts array or nil if no change
1276
1310
  #
@@ -1292,6 +1326,49 @@ module JSS
1292
1326
  @directory_bindings.map { |p| p[:name] }
1293
1327
  end
1294
1328
 
1329
+ # Add a Directory Bidning to the list of directory_bindings handled by this policy.
1330
+ # If the directory binding already exists in the policy, nil is returned and
1331
+ # no changes are made.
1332
+ #
1333
+ # @param [String,Integer] identifier the name or id of the directory binding to add to this policy
1334
+ #
1335
+ # @param position [Symbol, Integer] where to add this directory binding among the list of
1336
+ # directory_bindings. Zero-based, :start and 0 are the same, as are :end and -1.
1337
+ # Defaults to :end
1338
+ #
1339
+ # @return [Array, nil] the new @directory_bindings array, nil if directory_binding was already in the policy
1340
+ #
1341
+ def add_directory_binding(identifier, **opts)
1342
+ id = validate_directory_binding_opts identifier, opts
1343
+
1344
+ return nil if @directory_bindings.map { |s| s[:id] }.include? id
1345
+
1346
+ name = JSS::DirectoryBinding.map_all_ids_to(:name, api: @api)[id]
1347
+
1348
+ directory_binding_data = {
1349
+ id: id,
1350
+ name: name
1351
+ }
1352
+
1353
+ @directory_bindings.insert opts[:position], directory_binding_data
1354
+
1355
+ @need_to_update = true
1356
+ @directory_bindings
1357
+ end
1358
+
1359
+
1360
+ # Remove a directory binding from this policy by name or id
1361
+ #
1362
+ # @param identifier [String,Integer] the name or id of the directory binding to remove
1363
+ #
1364
+ # @return [Array, nil] the new directory bindings array or nil if no change
1365
+ #
1366
+ def remove_directory_binding(identifier)
1367
+ removed = @directory_bindings.delete_if { |s| s[:id] == identifier || s[:name] == identifier }
1368
+ @need_to_update = true if removed
1369
+ removed
1370
+ end
1371
+
1295
1372
  ###### Dock items
1296
1373
 
1297
1374
  # @return [Array] the id's of the dock_items handled by the policy
@@ -1304,6 +1381,86 @@ module JSS
1304
1381
  @dock_items.map { |p| p[:name] }
1305
1382
  end
1306
1383
 
1384
+
1385
+ ###### Printers
1386
+
1387
+ # Add a specific printer object to the policy.
1388
+ #
1389
+ # @author Tyler Morgan
1390
+ #
1391
+ # @param newvalue [String,Integer] The name or the id of the printer to be added to this policy.
1392
+ #
1393
+ # @param position [Symbol, Integer] where to add this printer object among the list of printer
1394
+ # objects. Zero-based, :start and 0 are the same, as are :end and -1.
1395
+ # Defaults to :end
1396
+ #
1397
+ # @param action [Symbol] One of the PRINTER_ACTIONS symbols. What you want done with the printer object upon policy execution.
1398
+ #
1399
+ # @param make_default [TrueClass,FalseClass] Should this printer object be set to default.
1400
+ # Defaults to false
1401
+ #
1402
+ # @return [String] The new printers array or nil if the printer was already in the policy
1403
+ def add_printer(identifier, **opts)
1404
+ id = validate_printer_opts identifier, opts
1405
+
1406
+ return nil if @printers.map { |p| p[:id] }.include? id
1407
+
1408
+ name = JSS::Printer.map_all_ids_to(:name, api: @api)[id]
1409
+
1410
+ printer_data = {
1411
+ id: id,
1412
+ name: name,
1413
+ action: PRINTER_ACTIONS[opts[:action]],
1414
+ make_default: opts[:make_default]
1415
+ }
1416
+
1417
+ @printers.insert opts[:position], printer_data
1418
+
1419
+ @need_to_update = true
1420
+ @printers
1421
+ end
1422
+
1423
+
1424
+ # Remove a specific printer object from the policy.
1425
+ #
1426
+ # @author Tyler Morgan
1427
+ #
1428
+ # @param identifier [String,Integer] The name or id of the printer to be removed.
1429
+ #
1430
+ # @return [Array, nil] The new printers array or nil if no change.
1431
+ def remove_printer(identifier)
1432
+ removed = @printers.delete_if { |p| p[:id] == identifier || p[:name] == identifier }
1433
+
1434
+ @need_to_update = true
1435
+ removed
1436
+ end
1437
+
1438
+ # Add a dock item to the policy
1439
+ def add_dock_item(identifier, action)
1440
+ id = JSS::DockItem.valid_id identifier, api: @api
1441
+
1442
+ raise JSS::NoSuchItemError, "No Dock Item matches '#{identifier}'" unless id
1443
+
1444
+ raise JSS::InvalidDataError, "Action must be one of: :#{DOCK_ITEM_ACTIONS.keys.join ', :'}" unless DOCK_ITEM_ACTIONS.include? action
1445
+
1446
+ return nil if @dock_items.map { |d| d[:id] }.include? id
1447
+
1448
+ name = JSS::DockItem.map_all_ids_to(:name, api: @api)[id]
1449
+
1450
+ @dock_items << {id: id, name: name, action: DOCK_ITEM_ACTIONS[action]}
1451
+
1452
+ @need_to_update = true
1453
+ @dock_items
1454
+ end
1455
+
1456
+ # Remove a dock item from the policy
1457
+ def remove_dock_item(identifier)
1458
+ # TODO: Add validation against JSS::DockItem
1459
+ removed = @dock_items.delete_if { |d| d[:id] == identifier || d[:name] == identifier }
1460
+ @need_to_update = true if removed
1461
+ removed
1462
+ end
1463
+
1307
1464
  # @return [Array] the id's of the printers handled by the policy
1308
1465
  def printer_ids
1309
1466
  begin
@@ -1312,7 +1469,7 @@ module JSS
1312
1469
  return []
1313
1470
  end
1314
1471
  end
1315
-
1472
+
1316
1473
  # @return [Array] the names of the printers handled by the policy
1317
1474
  def printer_names
1318
1475
  begin
@@ -1322,6 +1479,130 @@ module JSS
1322
1479
  end
1323
1480
  end
1324
1481
 
1482
+
1483
+
1484
+ ###### Disk Encryption
1485
+
1486
+ # Sets the Disk Encryption application to "Remediate" and sets the remediation key type to individual.
1487
+ #
1488
+ # @author Tyler Morgan
1489
+ #
1490
+ # @return [Void]
1491
+ #
1492
+ def reissue_key()
1493
+ if @disk_encryption[:action] != DISK_ENCRYPTION_ACTIONS[:remediate]
1494
+ # Setting New Action
1495
+ hash = {
1496
+ action: DISK_ENCRYPTION_ACTIONS[:remediate],
1497
+ remediate_key_type: "Individual"
1498
+ }
1499
+
1500
+ @disk_encryption = hash
1501
+ @need_to_update = true
1502
+
1503
+ else
1504
+ # Update
1505
+ return
1506
+ end
1507
+
1508
+ end
1509
+
1510
+
1511
+ # Sets the Disk Encryption application to "Apply" and sets the correct disk encryption configuration ID using either the name or id.
1512
+ #
1513
+ # @author Tyler Morgan
1514
+ #
1515
+ # @return [Void]
1516
+ #
1517
+ def apply_encryption_configuration(identifier)
1518
+
1519
+ id = JSS::DiskEncryptionConfiguration.valid_id identifier
1520
+
1521
+ return if id.nil?
1522
+
1523
+ hash = {
1524
+ action: DISK_ENCRYPTION_ACTIONS[:apply],
1525
+ disk_encryption_configuration_id: id,
1526
+ auth_restart: false
1527
+ }
1528
+
1529
+ @disk_encryption = hash
1530
+ @need_to_update = true
1531
+ end
1532
+
1533
+
1534
+ # Removes the Disk Encryption settings associated with this specific policy.
1535
+ #
1536
+ # @author Tyler Morgan
1537
+ #
1538
+ # @return [Void]
1539
+ #
1540
+ def remove_encryption_configuration()
1541
+ hash = {
1542
+ action: DISK_ENCRYPTION_ACTIONS[:none]
1543
+ }
1544
+
1545
+ @disk_encryption = hash
1546
+ @need_to_update = true
1547
+ end
1548
+
1549
+ # Interact with management account settings
1550
+ #
1551
+ # @param action [Key] one of the MGMT_ACCOUNT_ACTIONS keys
1552
+ #
1553
+ # @return The current specified management settings.
1554
+ #
1555
+ # Reference: https://developer.jamf.com/documentation#resources-with-passwords
1556
+ #
1557
+ def set_management_account(action, **opts)
1558
+ # TODO: Add proper error handling
1559
+ raise JSS::InvalidDataError, "Action must be one of: :#{MGMT_ACCOUNT_ACTIONS.keys.join ', :'}" unless MGMT_ACCOUNT_ACTIONS.include? action
1560
+
1561
+ management_data = {}
1562
+
1563
+ if action == :change_pw || action == :reset_pw
1564
+ raise JSS::MissingDataError, ":password must be provided when changing management account password" if opts[:password].nil?
1565
+
1566
+ management_data = {
1567
+ action: MGMT_ACCOUNT_ACTIONS[action],
1568
+ managed_password: opts[:password]
1569
+ }
1570
+ elsif action == :reset_random || action == :generate_pw
1571
+ raise JSS::MissingDataError, ":password_length must be provided when setting a random password" if opts[:password_length].nil?
1572
+ raise JSS::InvalidDataError, ":password_length must be an Integer" unless opts[:password_length].is_a? Integer
1573
+
1574
+ management_data = {
1575
+ action: MGMT_ACCOUNT_ACTIONS[action],
1576
+ managed_password_length: opts[:password_length]
1577
+ }
1578
+ else
1579
+ management_data = {
1580
+ action: MGMT_ACCOUNT_ACTIONS[action]
1581
+ }
1582
+ end
1583
+
1584
+ @management_account = management_data
1585
+
1586
+ @need_to_update = true
1587
+
1588
+ @management_account
1589
+
1590
+ end
1591
+
1592
+ # Check if management password matches provided password
1593
+ #
1594
+ # @param password[String] the password that is SHA256'ed to compare to the one from the API.
1595
+ #
1596
+ # @return [Boolean] The result of the comparison of the management password and provided text.
1597
+ #
1598
+ def verify_management_password(password)
1599
+ raise JSS::InvalidDataError, "Management password must be a string." unless password.is_a? String
1600
+
1601
+ raise JSS::UnsupportedError, "'#{@management_account[:action].to_s}' does not support management passwords." unless @management_account[:action] == MGMT_ACCOUNT_ACTIONS[:change_pw] || @management_account[:action] == MGMT_ACCOUNT_ACTIONS[:reset_pw]
1602
+
1603
+ return Digest::SHA256.hexdigest(password).to_s == @management_account[:managed_password_sha256].to_s
1604
+ end
1605
+
1325
1606
  ###### Actions
1326
1607
 
1327
1608
  # Try to execute this policy on this machine.
@@ -1439,6 +1720,64 @@ module JSS
1439
1720
  id
1440
1721
  end
1441
1722
 
1723
+ # raise an error if the directory binding being added isn't valid
1724
+ #
1725
+ # @see #add_directory_binding
1726
+ #
1727
+ # @return [Integer, nil] the valid id for the package
1728
+ #
1729
+ def validate_directory_binding_opts(identifier, opts)
1730
+ opts[:position] ||= -1
1731
+
1732
+ opts[:position] =
1733
+ case opts[:position]
1734
+ when :start then 0
1735
+ when :end then -1
1736
+ else JSS::Validate.integer(opts[:position])
1737
+ end
1738
+
1739
+ # if the given position is past the end, set it to -1 (the end)
1740
+ opts[:position] = -1 if opts[:position] > @directory_bindings.size
1741
+
1742
+ id = JSS::DirectoryBinding.valid_id identifier, api: @api
1743
+ raise JSS::NoSuchItemError, "No directory binding matches '#{identifier}'" unless id
1744
+ id
1745
+ end
1746
+
1747
+ # Raises an error if the printer being added isn't valid, additionally checks the options and sets defaults where possible.
1748
+ #
1749
+ # @see #add_printer
1750
+ #
1751
+ # @return [Integer, nil] the valid id for the package
1752
+ #
1753
+ def validate_printer_opts(identifier, opts)
1754
+ opts[:position] ||= -1
1755
+
1756
+ opts[:position] =
1757
+ case opts[:position]
1758
+ when :start then 0
1759
+ when :end then -1
1760
+ else JSS::Validate.integer(opts[:position])
1761
+ end
1762
+
1763
+ # If the given position is past the end, set it to -1 (the end)
1764
+ opts[:position] = -1 if opts[:position] > @printers.size
1765
+
1766
+ # Checks if action to be done with the printer object is provided and valid.
1767
+ raise JSS::MissingDataError, "action must be provided, must be one of :#{PRINTER_ACTIONS.keys.join(':,')}." if opts[:action].nil?
1768
+ raise JSS::InvalidDataError, "action must be one of :#{PRINTER_ACTIONS.keys.join(',:')}." unless PRINTER_ACTIONS.keys.include? opts[:action]
1769
+
1770
+
1771
+ # Checks if the make_default option is valid, and sets the default if needed.
1772
+ raise JSS::InvalidDataError, "make_default must be either true or false." unless opts[:make_default].is_a?(TrueClass) || opts[:make_default].is_a?(FalseClass) || opts[:make_default].nil?
1773
+
1774
+ opts[:make_default] = false if opts[:make_default].nil?
1775
+
1776
+ id = JSS::Printer.valid_id identifier, api: @api
1777
+ raise JSS::NoSuchItemError, "No printer matches '#{identifier}'" unless id
1778
+ id
1779
+ end
1780
+
1442
1781
  def rest_xml
1443
1782
  doc = REXML::Document.new APIConnection::XML_HEADER
1444
1783
  obj = doc.add_element RSRC_OBJECT_KEY.to_s
@@ -1475,6 +1814,22 @@ module JSS
1475
1814
  maint.add_element('user_cache').text = @user_cache.to_s
1476
1815
  maint.add_element('verify').text = @verify_startup_disk.to_s
1477
1816
 
1817
+ acct_maint = obj.add_element 'account_maintenance'
1818
+
1819
+ mgmt_acct = acct_maint.add_element 'management_account'
1820
+ JSS.hash_to_rexml_array(@management_account).each { |x| mgmt_acct << x }
1821
+
1822
+ directory_bindings = acct_maint.add_element 'directory_bindings'
1823
+ @directory_bindings.each do |b|
1824
+ directory_binding = directory_bindings.add_element 'binding'
1825
+ dbdeets = JSS.hash_to_rexml_array b
1826
+ dbdeets.each { |d| directory_binding << d }
1827
+ end
1828
+
1829
+ user_interaction = obj.add_element 'user_interaction'
1830
+ user_interaction.add_element('message_start').text = @user_message_start.to_s
1831
+ user_interaction.add_element('message_finish').text = @user_message_finish.to_s
1832
+
1478
1833
  files_processes = obj.add_element 'files_processes'
1479
1834
  JSS.hash_to_rexml_array(@files_processes).each { |f| files_processes << f }
1480
1835
 
@@ -1493,6 +1848,26 @@ module JSS
1493
1848
  sdeets.each { |d| script << d }
1494
1849
  end
1495
1850
 
1851
+ disk_encryption = obj.add_element 'disk_encryption'
1852
+
1853
+ @disk_encryption.each do |k,v|
1854
+ disk_encryption.add_element(k.to_s).text = v.to_s
1855
+ end
1856
+
1857
+ printers = obj.add_element 'printers'
1858
+ @printers.each do |pr|
1859
+ printer = printers.add_element 'printer'
1860
+ pdeets = JSS.hash_to_rexml_array pr
1861
+ pdeets.each { |d| printer << d }
1862
+ end
1863
+
1864
+ dock_items = obj.add_element 'dock_items'
1865
+ @dock_items.each do |d|
1866
+ dock_item = dock_items.add_element 'dock_item'
1867
+ ddeets = JSS.hash_to_rexml_array d
1868
+ ddeets.each { |de| dock_item << de }
1869
+ end
1870
+
1496
1871
  add_self_service_xml doc
1497
1872
  add_site_to_xml doc
1498
1873