xolo-server 2.1.0 → 2.2.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.
@@ -56,7 +56,7 @@ module Xolo
56
56
  end
57
57
 
58
58
  # Create title-level things in jamf when creating a title.
59
- #
59
+ # No need to deal with versions here, there are none yet.
60
60
  # @return [void]
61
61
  ################################
62
62
  def create_title_in_jamf
@@ -85,6 +85,10 @@ module Xolo
85
85
  # Just calling this will create it if it doesn't exist.
86
86
  jamf_frozen_group
87
87
 
88
+ # If we have target-groups, create the jamf_target_groups_exclusion_group
89
+ # to use as an exclusion
90
+ jamf_target_groups_exclusion_group if target_groups && !target_groups.pix_empty?
91
+
88
92
  # This either notifies, or does it
89
93
  # TODO: EAs for subscribed titles can change at any time and need
90
94
  # re-accepted - Notifications must happen.
@@ -100,9 +104,31 @@ module Xolo
100
104
  def update_title_in_jamf
101
105
  # ORDER MATTERS
102
106
 
107
+ # target group changes are tricky cuz the related group is in scopes
108
+ # all over the place.
109
+ need_to_delete_jamf_target_groups_exclusion_group = false
110
+
111
+ # TODO: Move this to a sep. method
112
+ if changes_for_update[:target_groups]
113
+ # if some->none, update the scopes later, then delete the group at the end
114
+ if changes_for_update[:target_groups][:new].empty?
115
+ need_to_delete_jamf_target_groups_exclusion_group = true
116
+
117
+ # if from none->some, create the group - add to scopes later
118
+ elsif changes_for_update[:target_groups][:old].empty?
119
+ # create the group
120
+ jamf_target_groups_exclusion_group
121
+
122
+ # if tgt grps changed, just update the smartgroup, don't change any scopes
123
+ else
124
+ configure_jamf_target_groups_exclusion_group changes_for_update[:target_groups][:new]
125
+ progress "Jamf: Done updating smart group '#{jamf_target_groups_exclusion_group_name}'", log: :debug
126
+ end
127
+ end
128
+
103
129
  # if the exclusions have changed update the manual install released policy
104
- if changes_for_update[:excluded_groups]
105
- progress "Jamf: Updating excluded groups for Manual Released Policy '#{jamf_manual_install_released_policy_name}'."
130
+ if changes_for_update[:target_groups] || changes_for_update[:excluded_groups]
131
+ progress "Jamf: Updating scope for Manual Released Policy '#{jamf_manual_install_released_policy_name}'."
106
132
  configure_jamf_manual_install_released_policy(jamf_manual_install_released_policy)
107
133
  end
108
134
 
@@ -132,39 +158,32 @@ module Xolo
132
158
  update_ssvc
133
159
  # TODO: deal with icon changes: if changes_for_update&.key? :self_service_icon
134
160
 
161
+ # are there any versions yet? if no, not active
135
162
  if jamf_title_active?
136
163
  update_versions_for_title_changes_in_jamf
137
164
  else
138
165
  log_debug "Jamf: Title '#{display_name}' (#{title}) is not yet active to Jamf, nothing to update in versions."
139
166
  end
167
+
168
+ # version scopes should have been updated, now do the title
169
+ configure_jamf_manual_install_released_policy
170
+ delete_jamf_target_groups_exclusion_group if need_to_delete_jamf_target_groups_exclusion_group
140
171
  end
141
172
 
142
173
  # Repair this title in Jamf Pro
143
- # - TODO: activate title in patch mgmt
144
- # - TODO: Accept Patch EA
145
- # - title-installed smart group 'xolo-<title>-installed'
146
- # - frozen static group 'xolo-<title>-frozen'
147
- # - manual/SSvc install-current-release policy 'xolo-<title>-install'
148
- # - trigger 'xolo-<title>-install'
149
- # - ssvc icon
150
- # - ssvc category
151
- # - description
152
- # - if uninstallable
153
- # - uninstall script 'xolo-<title>-uninstall'
154
- # - uninstall policy 'xolo-<title>-uninstall'
155
- # - if expirable
156
- # - expire policy 'xolo-<title>-expire'
157
- # - trigger 'xolo-<title>-expire'
174
+ # - TODO: activate title in patch mgmt if needed
175
+ # - TODO: Accept Patch EA if needed
158
176
  #
159
177
  ###############################################
160
178
  def repair_jamf_title_objects
161
179
  progress "Jamf: Repairing Jamf objects for title '#{title}'", log: :info
162
180
 
163
- configure_jamf_installed_group
181
+ repair_jamf_installed_group
164
182
  repair_jamf_uninstall_policy
165
183
  repair_jamf_uninstall_script
166
184
  repair_jamf_expire_policy
167
185
  repair_frozen_group
186
+ repair_jamf_target_groups_exclusion_group
168
187
  repair_jamf_manual_install_released_policy
169
188
  end
170
189
 
@@ -186,9 +205,11 @@ module Xolo
186
205
 
187
206
  delete_jamf_patch_title
188
207
 
189
- # static group deleted last,
208
+ # excl groups deleted last,
190
209
  # was used in scopes for patch and normal policies
191
210
  delete_jamf_frozen_group
211
+
212
+ delete_jamf_target_groups_exclusion_group
192
213
  end
193
214
 
194
215
  # If any title changes require updates to existing versions in
@@ -206,9 +227,13 @@ module Xolo
206
227
  ############################
207
228
  def update_versions_for_title_changes_in_jamf
208
229
  version_objects.each do |vers_obj|
230
+ progress "Jamf: Applying changes to version '#{vers_obj.version}' of title '#{title}' (#{self.class})", log: :info
209
231
  vers_obj.update_release_groups(ttl_obj: self) if changes_for_update&.key? :release_groups
210
- vers_obj.update_excluded_groups(ttl_obj: self) if changes_for_update&.key? :excluded_groups
232
+
233
+ vers_obj.update_excluded_groups(ttl_obj: self) if changes_for_update&.key?(:excluded_groups) || changes_for_update&.key?(:target_groups)
234
+
211
235
  vers_obj.update_jamf_package_notes(ttl_obj: self) if need_to_update_description?
236
+ vers_obj.update_patch_policy_deployment(ttl_obj: self) if changes_for_update&.key? :self_service_updates
212
237
  end
213
238
  end
214
239
 
@@ -792,8 +817,13 @@ module Xolo
792
817
 
793
818
  jamf_installed_group.criteria = Jamf::Criteriable::Criteria.new(jamf_installed_group_criteria)
794
819
  jamf_installed_group.save
795
- log_debug 'Jamf: Sleeping 30 secs to let Jamf server see changes to Installed smart group.'
796
- sleep 30
820
+ log_debug 'Jamf: Sleeping 15 secs to let Jamf server see changes to Installed smart group.'
821
+ sleep 15
822
+ end
823
+
824
+ ############################
825
+ def repair_jamf_installed_group
826
+ configure_jamf_installed_group
797
827
  end
798
828
 
799
829
  # The criteria for the smart group in Jamf that contains all Macs
@@ -846,6 +876,141 @@ module Xolo
846
876
  @jamf_installed_group_url = "#{jamf_gui_url}/smartComputerGroups.html?id=#{gr_id}&o=r"
847
877
  end
848
878
 
879
+ ####### The TargetGroups Exclusion Group
880
+ ###########################################
881
+ ###########################################
882
+
883
+ ############################
884
+ def jamf_target_groups_exclusion_group
885
+ return @jamf_target_groups_exclusion_group if @jamf_target_groups_exclusion_group
886
+ return if target_groups_to_use.pix_empty?
887
+
888
+ if jamf_target_groups_exclusion_group_exist?
889
+ @jamf_target_groups_exclusion_group = Jamf::ComputerGroup.fetch(
890
+ name: jamf_target_groups_exclusion_group_name,
891
+ cnx: jamf_cnx
892
+ )
893
+ else
894
+ return if deleting?
895
+
896
+ progress "Jamf: Creating smart group '#{jamf_target_groups_exclusion_group_name}'", log: :info
897
+
898
+ @jamf_target_groups_exclusion_group = Jamf::ComputerGroup.create(
899
+ name: jamf_target_groups_exclusion_group_name,
900
+ type: :smart,
901
+ cnx: jamf_cnx
902
+ )
903
+ @jamf_target_groups_exclusion_group.save
904
+ configure_jamf_target_groups_exclusion_group
905
+ progress "Jamf: Done creating smart group '#{jamf_target_groups_exclusion_group_name}'", log: :debug
906
+
907
+ end
908
+
909
+ @jamf_target_groups_exclusion_group
910
+ end
911
+
912
+ ############################
913
+ def jamf_target_groups_exclusion_group_exist?
914
+ Jamf::ComputerGroup.all_names(:refresh, cnx: jamf_cnx).include? jamf_target_groups_exclusion_group_name
915
+ end
916
+
917
+ ############################
918
+ def jamf_target_groups_exclusion_group_criteria(tgt_grps = nil)
919
+ # for some reason this can be really slow
920
+ jamf_cnx.timeout = 1800
921
+ tgt_grps ||= target_groups_to_use
922
+ criteria = []
923
+ tgt_grps.each do |tgrp|
924
+ progress "Jamf: Adding criterion for target group '#{tgrp}' (can be slow)", log: :info
925
+ criteria << Jamf::Criteriable::Criterion.new(
926
+ and_or: :and,
927
+ name: 'Computer Group',
928
+ search_type: 'not member of',
929
+ value: tgrp
930
+ )
931
+ end
932
+ criteria
933
+ end
934
+
935
+ ############################
936
+ def configure_jamf_target_groups_exclusion_group(tgt_grps = nil)
937
+ return if target_groups_to_use.pix_empty?
938
+
939
+ tgt_grps ||= target_groups_to_use
940
+ progress "Jamf: Configuring smart group '#{jamf_target_groups_exclusion_group_name}'", log: :info
941
+
942
+ jamf_target_groups_exclusion_group.criteria =
943
+ Jamf::Criteriable::Criteria.new jamf_target_groups_exclusion_group_criteria(tgt_grps)
944
+
945
+ jamf_target_groups_exclusion_group.save
946
+
947
+ progress "Jamf: Sleeping 10 secs to let Jamf server see changes to smart group '#{jamf_target_groups_exclusion_group_name}'", log: :debug
948
+ sleep 10
949
+ end
950
+
951
+ ############################
952
+ def repair_jamf_target_groups_exclusion_group
953
+ progress "Jamf: Repairing smart group '#{jamf_target_groups_exclusion_group_name}'", log: :info
954
+
955
+ if target_groups_to_use.pix_empty?
956
+ delete_jamf_target_groups_exclusion_group
957
+ else
958
+ configure_jamf_target_groups_exclusion_group
959
+ progress "Jamf: Done repairing smart group '#{jamf_target_groups_exclusion_group_name}'", log: :debug
960
+
961
+ end
962
+ end
963
+
964
+ ############################
965
+ def delete_jamf_target_groups_exclusion_group
966
+ return unless jamf_target_groups_exclusion_group_exist?
967
+
968
+ progress "Jamf: Deleting smart group '#{jamf_target_groups_exclusion_group_name}'", log: :info
969
+ grp = Jamf::ComputerGroup.fetch(
970
+ name: jamf_target_groups_exclusion_group_name,
971
+ cnx: jamf_cnx
972
+ )
973
+ grp.delete
974
+
975
+ # give the server time to see the deletion
976
+ log_debug "Jamf: Sleeping 10 secs to let server see deletion of smart group '#{jamf_target_groups_exclusion_group_name}'"
977
+ sleep 10
978
+ end
979
+
980
+ ############################
981
+ def jamf_target_groups_exclusion_group_url
982
+ return @jamf_target_groups_exclusion_group_url if @jamf_target_groups_exclusion_group_url
983
+
984
+ gr_id = Jamf::ComputerGroup.valid_id jamf_target_groups_exclusion_group_name, cnx: jamf_cnx
985
+ return unless gr_id
986
+
987
+ @jamf_target_groups_exclusion_group_url = "#{jamf_gui_url}/smartComputerGroups.html?id=#{gr_id}&o=r"
988
+ end
989
+
990
+ # should we use the jamf_target_groups_exclusion_group in our exclusions?
991
+ # If yes, it must have been created before now.
992
+ # If no, it can't have been deleted yet.
993
+ #
994
+ # @return [Boolean] should we use the jamf_target_groups_exclusion_group in our exclusions?
995
+ #########
996
+ def use_jamf_target_groups_exclusion_group?
997
+ if changes_for_update[:target_groups]
998
+ ## if some-to-none, no
999
+ if changes_for_update[:target_groups][:new].empty?
1000
+ false
1001
+ # if from none-to-some, yes
1002
+ elsif changes_for_update[:target_groups][:old].empty?
1003
+ true
1004
+ # if tgt grps changed, just update the smartgroup, don't change any scopes
1005
+ else
1006
+ true
1007
+ end
1008
+
1009
+ else
1010
+ !target_groups.empty?
1011
+ end
1012
+ end
1013
+
849
1014
  ####### The Frozen Group
850
1015
  ###########################################
851
1016
  ###########################################
@@ -1260,14 +1425,14 @@ module Xolo
1260
1425
  self.title_id = title
1261
1426
  log_debug "Jamf: Display Name in managed? after setting patch_source and title_id: #{display_name}"
1262
1427
 
1263
- # display name is required for managed titles, but will be empty for subbed
1264
- # so for subbed, we look it up from the patch source
1428
+ # display name & publisher are required for managed titles, but will be empty for subbed
1429
+ # so for subbed, we look them up from the patch source in set_subscribed_display_name_and_publisher
1265
1430
  else
1266
- log_debug "Jamf: Title '#{title}' is subscribed, so looking up patch source and title_id from"
1431
+ log_debug "Jamf: Title '#{title}' is subscribed, so looking up patch source and title_id"
1267
1432
  log_debug "Jamf: Display Name in NOT managed?: #{display_name}"
1268
- if display_name.pix_empty?
1269
- self.display_name = Jamf::PatchSource.available_titles(patch_source, cnx: jamf_cnx).select { |t| t[:name_id] == title_id }.first&.dig :app_name
1270
- end
1433
+
1434
+ set_subscribed_display_name_and_publisher
1435
+
1271
1436
  end # if managed
1272
1437
 
1273
1438
  log_debug "Jamf: class: #{self.class}, display_name: #{display_name}, patch_source: #{patch_source}, title_id: #{title_id}"
@@ -1284,11 +1449,48 @@ module Xolo
1284
1449
  )
1285
1450
  jamf_patch_title.category = Xolo::Server::JAMF_XOLO_CATEGORY
1286
1451
  self.jamf_patch_title_id = jamf_patch_title.save
1287
- log_debug "Activated Jamf Patch Title '#{display_name}' (#{title}) with id #{jamf_patch_title_id}"
1452
+
1453
+ log_debug "Jamf: Activated Jamf Patch Title '#{display_name}' (#{title}) with id #{jamf_patch_title_id}"
1288
1454
 
1289
1455
  jamf_patch_title
1290
1456
  end
1291
1457
 
1458
+ # set the display name and publisher from the patch title data
1459
+ ########################
1460
+ def set_subscribed_display_name_and_publisher
1461
+ return unless subscribed?
1462
+
1463
+ # if we already have a patch title id, the title won't be available from the patch source,
1464
+ # so use the JPAPI endpoint to look up the data from the already active title.
1465
+ # TODO: update this when ruby-jss uses the JPAPI for patch title stuff
1466
+ if jamf_patch_title_id
1467
+ log_debug 'Jamf: Getting display name and publisher from already-active title.'
1468
+ patch_title_data = jamf_cnx.jp_get "v2/patch-software-title-configurations/#{jamf_patch_title_id}"
1469
+
1470
+ dname = patch_title_data[:displayName]
1471
+ publ = patch_title_data[:softwareTitlePublisher]
1472
+
1473
+ # we don't yet have the patch title id, so the title is still 'available' from the patch source
1474
+ # so get the data there
1475
+ else
1476
+ log_debug 'Jamf: Getting display name and publisher from avilable/not-yet-active title.'
1477
+ patch_title_data = Jamf::PatchSource.available_titles(patch_source, cnx: jamf_cnx).select { |t| t[:name_id] == title_id }.first
1478
+
1479
+ dname = patch_title_data&.dig :app_name
1480
+ publ = patch_title_data&.dig :publisher
1481
+ end # if jamf_patch_title_id
1482
+
1483
+ if dname
1484
+ progress "Jamf: Setting display name for subscribed title: #{dname}", log: :debug
1485
+ self.display_name = dname
1486
+ end
1487
+
1488
+ return unless publ
1489
+
1490
+ progress "Jamf: Setting publisher for subscribed title: #{publ}", log: :debug
1491
+ self.publisher = publ
1492
+ end
1493
+
1292
1494
  # wait up to 60secs for a managed title to become available to be activated
1293
1495
  # subscribed titles are already available
1294
1496
  ####################
@@ -1408,7 +1610,11 @@ module Xolo
1408
1610
  # @param pol [Jamf::Policy] the policy we are configuring
1409
1611
  # @return [void]
1410
1612
  ###################
1411
- def configure_jamf_manual_install_released_policy(pol)
1613
+ def configure_jamf_manual_install_released_policy(pol = nil)
1614
+ progress "Jamf: Configuring manual install-released policy '#{jamf_manual_install_released_policy_name}'", log: :info
1615
+
1616
+ pol ||= jamf_manual_install_released_policy
1617
+
1412
1618
  pol.category = Xolo::Server::JAMF_XOLO_CATEGORY
1413
1619
  pol.set_trigger_event :checkin, false
1414
1620
  pol.set_trigger_event :custom, jamf_manual_install_released_policy_name
@@ -1421,19 +1627,9 @@ module Xolo
1421
1627
 
1422
1628
  toggle_jamf_manual_install_released_policy pol
1423
1629
 
1424
- # figure out the exclusions.
1425
- #
1426
- # explicit exlusions for the title
1427
- excls = changes_for_update&.key?(:excluded_groups) ? changes_for_update[:excluded_groups][:new].dup : excluded_groups.dup
1428
- excls ||= []
1429
- # plus the frozen group
1430
- excls << jamf_frozen_group_name
1431
- # plus any forced group from the server config
1432
- excls << valid_forced_exclusion_group_name if valid_forced_exclusion_group_name
1433
- # NOTE: we do not exclude existing installs, so that manual re-installs can be a thing.
1434
- log_debug "Setting exclusions for manual install policy for current release: #{excls}"
1630
+ log_debug "Setting exclusions for manual install policy for current release: #{excluded_groups_to_use}"
1435
1631
 
1436
- pol.scope.set_exclusions :computer_groups, excls
1632
+ pol.scope.set_exclusions :computer_groups, excluded_groups_to_use
1437
1633
 
1438
1634
  if self_service?
1439
1635
  add_title_to_self_service(pol)
@@ -1442,6 +1638,30 @@ module Xolo
1442
1638
  end
1443
1639
  end
1444
1640
 
1641
+ # what exclusions should we use now on all title-level scopable things?
1642
+ #######################
1643
+ def excluded_groups_to_use
1644
+ # always the frozen group
1645
+ excls = [jamf_frozen_group_name]
1646
+
1647
+ # plus any explicit exclusions for the title
1648
+ excls += changes_for_update&.key?(:excluded_groups) ? changes_for_update[:excluded_groups][:new] : excluded_groups
1649
+
1650
+ # plus the target_groups_exclusion_group if needed
1651
+ excls << jamf_target_groups_exclusion_group_name if use_jamf_target_groups_exclusion_group?
1652
+
1653
+ # plus any forced group from the server config
1654
+ excls << valid_forced_exclusion_group_name if valid_forced_exclusion_group_name
1655
+
1656
+ excls
1657
+ end
1658
+
1659
+ # what target groups should we use now on all title-level scopable things?
1660
+ #######################
1661
+ def target_groups_to_use
1662
+ changes_for_update&.key?(:target_groups) ? changes_for_update[:target_groups][:new] : target_groups
1663
+ end
1664
+
1445
1665
  # enable or disable the manual install policy for the current release, depending on
1446
1666
  # whether or not we have a released version
1447
1667
  # @param pol [Jamf::Policy] the manual install policy for the current release, which may or may not be saved yet.
@@ -1504,13 +1724,6 @@ module Xolo
1504
1724
 
1505
1725
  configure_pol_for_self_service(pol)
1506
1726
  pol.save
1507
-
1508
- # loop thru versions to make any SSvc changes
1509
- version_objects.each do |vobj|
1510
- ppol = vobj.jamf_patch_policy
1511
- vobj.configure_patch_pol_for_self_service ppol
1512
- ppol.save
1513
- end
1514
1727
  end
1515
1728
 
1516
1729
  # Add the jamf_manual_install_released_policy to self service if needed
@@ -1593,12 +1806,17 @@ module Xolo
1593
1806
  pol.self_service_description = new_desc
1594
1807
 
1595
1808
  pol.self_service_install_button_text = Xolo::Server::Title::SELF_SERVICE_INSTALL_BTN_TEXT
1809
+ # icon already uploaded to jamf
1810
+ return if ssvc_icon_id
1811
+
1812
+ # icon never uploaded to xolo
1596
1813
  return unless ssvc_icon_file
1597
1814
 
1598
- # TODO: Is this needed if we already have a ssvc_icon_id ??
1815
+ # Upload the icon from xolo to jamd
1599
1816
  progress 'Jamf: Uploading Self Service icon', log: :debug
1600
1817
  pol.save # won't do anything unless needed, but has to exist before we can upload icons
1601
1818
  pol.upload :icon, ssvc_icon_file
1819
+
1602
1820
  # re-fetch the pol to get the icon id
1603
1821
  self.ssvc_icon_id = Jamf::Policy.fetch(id: pol.id, cnx: jamf_cnx).icon.id
1604
1822
  end
@@ -45,6 +45,14 @@ module Xolo
45
45
  # changes
46
46
  JAMF_POLICY_NAME_AUTO_REINSTALL_SFX = 'auto-reinstall'
47
47
 
48
+ PATCH_POL_SSVC_NOTIFICATION_TYPE = :ssvc_and_nctr
49
+ PATCH_POL_SSVC_INSTALL_BTN_TXT = 'Update'
50
+ PATCH_POL_SSVC_REMINDER_FREQ_HRS = 24
51
+ PATCH_POL_SSVC_DEADLINE_DAYS = 7
52
+
53
+ PATCH_POL_GRACE_PERIOD_MINUTES = 15
54
+ PATCH_POL_GRACE_PERIOD_SUBJ = 'Important'
55
+ PATCH_POL_GRACE_PERIOD_MSG = '$APP_NAMES will quit in $DELAY_MINUTES minutes so that $SOFTWARE_TITLE can be updated. Please save anything you are working on and quit the app(s).'
48
56
  # POLICIES, PATCH POLICIES, SCOPING
49
57
  #############################
50
58
  #
@@ -402,19 +410,6 @@ module Xolo
402
410
  jamf_package.save
403
411
  end
404
412
 
405
- # update the :patch_unknown for the patch policy
406
- # @return [void]
407
- ##############################
408
- def update_jamf_patch_policy_patch_unknown
409
- return unless changes_for_update&.key? :patch_unknown
410
-
411
- ppol = jamf_patch_policy
412
- action = changes_for_update[:patch_unknown][:new] ? 'Enabling' : 'Disabling'
413
- progress "Jamf: #{action} 'patch_unknown' for patch policy #{ppol.name}", log: :debug
414
- ppol.patch_unknown = changes_for_update[:patch_unknown][:new] ? true : false
415
- ppol.save
416
- end
417
-
418
413
  # repair the package object only
419
414
  #############################
420
415
  def repair_jamf_package
@@ -915,16 +910,33 @@ module Xolo
915
910
  ppol.save
916
911
  end
917
912
 
913
+ # update the :patch_unknown for the patch policy
914
+ # @return [void]
915
+ ##############################
916
+ def update_jamf_patch_policy_patch_unknown
917
+ return unless changes_for_update&.key? :patch_unknown
918
+
919
+ ppol = jamf_patch_policy
920
+ action = changes_for_update[:patch_unknown][:new] ? 'Enabling' : 'Disabling'
921
+ progress "Jamf: #{action} 'patch_unknown' for patch policy #{ppol.name}", log: :debug
922
+ ppol.patch_unknown = changes_for_update[:patch_unknown][:new] ? true : false
923
+ ppol.save
924
+ end
925
+
918
926
  # Configure the patch policy
919
927
  # NOTE: This doesn't save the changes!
920
928
  ##############################
921
929
  def configure_jamf_patch_policy(ppol)
930
+ progress "Jamf: Configuring Patch Policy for Version '#{version}' of Title '#{title}'.", log: :info
931
+
922
932
  ppol.name = jamf_patch_policy_name
923
933
  ppol.target_version = version
924
934
 
925
935
  # This should default to false, so that
926
936
  # we don't accidentally downgrade non-xolo test installs,
927
937
  # or server-pushed updates (like with commvault or cisco VPN)
938
+ # The ternary operator is used here so that nils become
939
+ # explicit false
928
940
  ppol.patch_unknown = patch_unknown ? true : false
929
941
 
930
942
  # when first creating a patch policy, its status is always
@@ -940,43 +952,79 @@ module Xolo
940
952
  # exclusions are for always
941
953
  set_policy_exclusions ppol
942
954
 
955
+ # deployment method
956
+ configure_patch_pol_deployment ppol: ppol
957
+
943
958
  # only pilot and released versions should have the patch policy enabled
944
- if pilot? || released?
959
+ if pilot? || released? || creating? || releasing?
945
960
  ppol.enable
946
961
  else
947
962
  ppol.disable
948
963
  end
964
+ end
965
+
966
+ # Update the patch policy deployment settings if
967
+ # they were changed in the title.
968
+ #
969
+ # @param ttl_obj [Xolo::Server::Title] the title object that is being changed.
970
+ ###############################
971
+ def update_patch_policy_deployment(ttl_obj:)
972
+ return unless ttl_obj.changes_for_update[:self_service_updates]
949
973
 
950
- configure_patch_pol_for_self_service ppol
974
+ ppol = jamf_patch_policy
975
+ configure_patch_pol_deployment ttl_obj: ttl_obj, ppol: ppol
976
+ ppol.save
951
977
  end
952
978
 
953
- # Configure the patch policy for self service
979
+ # Configure the patch policy for self service or automatic deployment
954
980
  # NOTE: Does NOT save the policy changes!
955
981
  # @param ppol [Jamf::PatchPolicy] The patch policy to configure
956
982
  # @return [void]
957
983
  # ###############################
958
- def configure_patch_pol_for_self_service(ppol = nil)
984
+ def configure_patch_pol_deployment(ppol: nil, ttl_obj: nil)
959
985
  ppol ||= jamf_patch_policy
986
+ ttl_obj ||= title_object
987
+
988
+ use_ssvc_updates =
989
+ if ttl_obj.changes_for_update&.dig :self_service_updates
990
+ ttl_obj.changes_for_update[:self_service_updates][:new]
991
+ else
992
+ ttl_obj.self_service_updates
993
+ end
994
+
995
+ # always set the grace period regardless of deployment type
996
+ progress "Jamf: Configuring Patch Policy grace period for version '#{version}' of title '#{title}' ", log: :info
997
+ ppol.grace_period = PATCH_POL_GRACE_PERIOD_MINUTES
998
+ ppol.grace_period_subject = PATCH_POL_GRACE_PERIOD_SUBJ
999
+ ppol.grace_period_message = PATCH_POL_GRACE_PERIOD_MSG
1000
+
1001
+ # Self Service deployment
1002
+ if use_ssvc_updates
1003
+ progress "Jamf: Configuring Patch Policy for version '#{version}' of title '#{title}' for Self Service", log: :info
960
1004
 
961
- # if we're here we're in ssvc
962
- progress "Jamf: Configuring patch policy for version '#{version}' of title '#{title}' for Self Service'", log: :info
1005
+ ppol.add_to_self_service
963
1006
 
964
- # TODO: xadm settings for most of these ssvc values.
965
- # TODO: deadlines, graceperiod ? needed in ruby-jss
966
- msg = "#{title_object.display_name} is ready to be updated to version #{version}"
967
- ppol.add_to_self_service
968
- ppol.self_service_install_button_text = 'Update'
969
- ppol.self_service_description = msg
970
- ppol.self_service_notifications_enabled = true
971
- ppol.self_service_notification_type = :ssvc_and_nctr
972
- ppol.self_service_notification_subject = "#{title_object.display_name} update available"
973
- ppol.self_service_notification_message = msg
974
- ppol.self_service_reminders_enabled = true
975
- ppol.self_service_reminder_frequency = 24 # hours
1007
+ msg = "#{title_object.display_name} is ready to be updated to version #{version}"
976
1008
 
977
- return unless title_object.ssvc_icon_id
1009
+ ppol.self_service_install_button_text = PATCH_POL_SSVC_INSTALL_BTN_TXT
1010
+ ppol.self_service_description = msg
1011
+ ppol.self_service_notifications_enabled = true
1012
+ ppol.self_service_notification_type = PATCH_POL_SSVC_NOTIFICATION_TYPE
1013
+ ppol.self_service_notification_subject = "#{title_object.display_name} update available"
1014
+ ppol.self_service_notification_message = msg
1015
+ ppol.self_service_reminders_enabled = true
1016
+ ppol.self_service_reminder_frequency = PATCH_POL_SSVC_REMINDER_FREQ_HRS
1017
+ ppol.deadline = PATCH_POL_SSVC_DEADLINE_DAYS
978
1018
 
979
- set_patch_policy_ssvc_icon ppol, title_object.ssvc_icon_id
1019
+ return unless title_object.ssvc_icon_id
1020
+
1021
+ set_patch_policy_ssvc_icon ppol, title_object.ssvc_icon_id
1022
+
1023
+ # Automatic deployment
1024
+ else
1025
+ progress "Jamf: Configuring Patch Policy for version '#{version}' of title '#{title}' for automatic deployment", log: :info
1026
+ ppol.remove_from_self_service
1027
+ end
980
1028
  end
981
1029
 
982
1030
  # Set an existing ssvc icon for a given patch policy
@@ -1086,6 +1134,7 @@ module Xolo
1086
1134
  ############################
1087
1135
  def set_policy_exclusions(pol, ttl_obj: nil)
1088
1136
  ttl_obj ||= title_object
1137
+
1089
1138
  # dup, so when we add the installed group below, we don't
1090
1139
  # keep that for future calls to this method.
1091
1140
  exclusions = excluded_groups_to_use(ttl_obj: ttl_obj).dup
@@ -1254,7 +1303,7 @@ module Xolo
1254
1303
  pol = jamf_patch_policy
1255
1304
  return unless pol
1256
1305
 
1257
- progress "Jamf: Updating exccluded groups for Patch Policy '#{jamf_patch_policy_name}'."
1306
+ progress "Jamf: Updating excluded groups for Patch Policy '#{jamf_patch_policy_name}'."
1258
1307
  set_policy_exclusions(pol, ttl_obj: ttl_obj)
1259
1308
  pol.save
1260
1309
  end