xolo-server 1.0.1 → 2.0.3

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/data/client/xolo +182 -82
  3. data/lib/xolo/core/base_classes/title.rb +261 -20
  4. data/lib/xolo/core/base_classes/version.rb +53 -8
  5. data/lib/xolo/core/constants.rb +7 -3
  6. data/lib/xolo/core/security_cmd.rb +128 -0
  7. data/lib/xolo/core/version.rb +1 -1
  8. data/lib/xolo/core.rb +1 -0
  9. data/lib/xolo/server/app.rb +7 -0
  10. data/lib/xolo/server/configuration.rb +243 -37
  11. data/lib/xolo/server/constants.rb +10 -0
  12. data/lib/xolo/server/helpers/auth.rb +19 -2
  13. data/lib/xolo/server/helpers/autopkg.rb +170 -0
  14. data/lib/xolo/server/helpers/client_data.rb +91 -61
  15. data/lib/xolo/server/helpers/file_transfers.rb +412 -82
  16. data/lib/xolo/server/helpers/jamf_pro.rb +30 -7
  17. data/lib/xolo/server/helpers/log.rb +2 -0
  18. data/lib/xolo/server/helpers/maintenance.rb +1 -0
  19. data/lib/xolo/server/helpers/notification.rb +4 -3
  20. data/lib/xolo/server/helpers/pkg_signing.rb +16 -12
  21. data/lib/xolo/server/helpers/progress_streaming.rb +9 -12
  22. data/lib/xolo/server/helpers/subscriptions.rb +119 -0
  23. data/lib/xolo/server/helpers/titles.rb +27 -3
  24. data/lib/xolo/server/helpers/versions.rb +23 -11
  25. data/lib/xolo/server/mixins/changelog.rb +9 -16
  26. data/lib/xolo/server/mixins/title_jamf_access.rb +395 -383
  27. data/lib/xolo/server/mixins/title_ted_access.rb +29 -3
  28. data/lib/xolo/server/mixins/version_jamf_access.rb +185 -159
  29. data/lib/xolo/server/mixins/version_ted_access.rb +25 -0
  30. data/lib/xolo/server/object_locks.rb +2 -1
  31. data/lib/xolo/server/routes/auth.rb +2 -2
  32. data/lib/xolo/server/routes/jamf_pro.rb +11 -1
  33. data/lib/xolo/server/routes/maint.rb +2 -1
  34. data/lib/xolo/server/routes/subscriptions.rb +126 -0
  35. data/lib/xolo/server/routes/title_editor.rb +1 -1
  36. data/lib/xolo/server/routes/titles.rb +30 -17
  37. data/lib/xolo/server/routes/uploads.rb +0 -14
  38. data/lib/xolo/server/routes/versions.rb +22 -17
  39. data/lib/xolo/server/routes.rb +9 -0
  40. data/lib/xolo/server/title.rb +107 -78
  41. data/lib/xolo/server/tmp_overrides.rb +38 -0
  42. data/lib/xolo/server/version.rb +193 -15
  43. data/lib/xolo/server.rb +12 -0
  44. metadata +8 -9
@@ -65,6 +65,11 @@ module Xolo
65
65
  # @return [Windoo::SoftwareTitle]
66
66
  ##########################
67
67
  def create_title_in_ted
68
+ if subscribed?
69
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor creation"
70
+ return
71
+ end
72
+
68
73
  # delete an old one if its there
69
74
  ted_title&.delete if Windoo::SoftwareTitle.all_ids(cnx: ted_cnx).include? title
70
75
 
@@ -173,6 +178,10 @@ module Xolo
173
178
  # @return [void]
174
179
  ##########################
175
180
  def update_title_in_ted
181
+ if subscribed?
182
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor update"
183
+ return
184
+ end
176
185
  return unless changes_for_update
177
186
 
178
187
  unless any_ted_changes?
@@ -217,10 +226,12 @@ module Xolo
217
226
  req_change = requirement_change
218
227
  return unless req_change
219
228
 
220
- new_app_name = changes_for_update.dig :app_name, :new
221
- new_app_bundle_id = changes_for_update.dig :app_bundle_id, :new
222
229
  new_ea_script = changes_for_update.dig :version_script, :new
223
230
 
231
+ # if either of these are nil in changes, then use the existing value
232
+ new_app_name = changes_for_update.dig(:app_name, :new) || app_name
233
+ new_app_bundle_id = changes_for_update.dig(:app_bundle_id, :new) || app_bundle_id
234
+
224
235
  case req_change
225
236
  when :app_to_ea
226
237
  # create the ea
@@ -241,6 +252,7 @@ module Xolo
241
252
  when :update_app
242
253
  # set the requirement to use the new app data
243
254
  set_ted_title_requirement app_name: new_app_name, app_bundle_id: new_app_bundle_id
255
+
244
256
  # for all versions, update the patch compotent criteria to use the new app data
245
257
  set_ted_patch_component_criteria_after_update app_name: new_app_name, app_bundle_id: new_app_bundle_id
246
258
 
@@ -292,11 +304,19 @@ module Xolo
292
304
  end
293
305
  end
294
306
 
307
+ # In the TitleEditor, the version script is
308
+ # stored as an Extension Attribute - each title can
309
+ # only have one.
310
+ # and it needs a 'key', which is the name used to indicate the
311
+ # EA in various criteria, and is the EA name in Jamf Patch.
312
+ # The key is jamf_obj_name_pfx on the title
313
+ # so for title 'foobar', it is 'xolo-foobar' or 'xolotest-foobar' for test servers
314
+ # That value is also used as the display name
295
315
  # @return [String] The key and display name of a version script stored
296
316
  # in the title editor as the ExtAttr for this title
297
317
  #####################
298
318
  def ted_ea_key
299
- @ted_ea_key ||= self.class.ted_ea_key title
319
+ @ted_ea_key ||= "#{jamf_obj_name_pfx_base}#{title}"
300
320
  end
301
321
 
302
322
  # Create the EA in the Title Editor
@@ -470,6 +490,8 @@ module Xolo
470
490
  # @return [String] the URL for the title in the Title Editor
471
491
  #####################
472
492
  def ted_title_url
493
+ return unless managed?
494
+
473
495
  "https://#{Xolo::Server.config.ted_hostname}/softwaretitles/#{ted_id_number}"
474
496
  end
475
497
 
@@ -482,6 +504,10 @@ module Xolo
482
504
  # @return [void]
483
505
  ############################
484
506
  def repair_ted_title
507
+ if subscribed?
508
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor repair"
509
+ return
510
+ end
485
511
  progress "Title Editor: Repairing SoftwareTitle '#{title}'", log: :info
486
512
 
487
513
  # TODO: version order??
@@ -26,29 +26,24 @@ module Xolo
26
26
 
27
27
  # The group of macs with this version installed
28
28
  # is named the full prefix plus this suffix.
29
- JAMF_SMART_GROUP_NAME_INSTALLED_SFX = '-installed'
29
+ JAMF_SMART_GROUP_NAME_INSTALLED_SFX = 'installed'
30
30
 
31
31
  # The policy that does initial installs on-demand
32
32
  # (via 'xolo install <title> <version') is named the full
33
33
  # prefix plus this suffix.
34
- JAMF_POLICY_NAME_MANUAL_INSTALL_SFX = '-manual-install'
34
+ JAMF_POLICY_NAME_MANUAL_INSTALL_SFX = 'manual-install'
35
35
 
36
36
  # The policy that does auto-installs is named the full
37
37
  # prefix plus this suffix.
38
38
  # The scope is changed as needed when a version's status
39
39
  # changes
40
- JAMF_POLICY_NAME_AUTO_INSTALL_SFX = '-auto-install'
40
+ JAMF_POLICY_NAME_AUTO_INSTALL_SFX = 'auto-install'
41
41
 
42
42
  # The policy that does auto-re-installs is named the full
43
43
  # prefix plus this suffix.
44
44
  # The scope is changed as needed when a version's status
45
45
  # changes
46
- JAMF_POLICY_NAME_AUTO_REINSTALL_SFX = '-auto-reinstall'
47
-
48
- # How long to wait after a pkg re-upload before creating/enabling/flushing
49
- # the auto-reinstall policy
50
- # See TODO in #wait_to_enable_reinstall_policy
51
- JAMF_AUTO_REINSTALL_WAIT_SECS = 15 * 60
46
+ JAMF_POLICY_NAME_AUTO_REINSTALL_SFX = 'auto-reinstall'
52
47
 
53
48
  # POLICIES, PATCH POLICIES, SCOPING
54
49
  #############################
@@ -197,7 +192,11 @@ module Xolo
197
192
  jamf_auto_install_policy
198
193
  jamf_manual_install_policy
199
194
 
200
- activate_patch_version_in_jamf
195
+ if subscribed?
196
+ activate_subscribed_patch_version_in_jamf
197
+ else
198
+ activate_managed_patch_version_in_jamf
199
+ end
201
200
  end
202
201
 
203
202
  # Apply edits to the Xolo version to Jamf as needed
@@ -213,16 +212,7 @@ module Xolo
213
212
  update_jamf_pkg_reboot if changes_for_update&.key? :reboot
214
213
  update_jamf_pkg_min_os if changes_for_update&.key? :min_os
215
214
 
216
- # TODO: Update the critera for the jamf_installed_group IF
217
- #
218
- # - the group exists AND
219
- # - the title has changed how it determines installed versions, e.g. by adding or
220
- # changing a version_script or app_bundle_id
221
- # Changing those is very rare, and ill-advised, so we will implement
222
- # this later.
223
- #
224
- # if jamf_installed_group_exist?
225
- # end
215
+ update_jamf_patch_policy_patch_unknown if changes_for_update&.key? :patch_unknown
226
216
  end
227
217
 
228
218
  # Validate and fix any Jamf::JPackage objects that
@@ -276,8 +266,6 @@ module Xolo
276
266
  # Delete package object
277
267
  # This is slow and it blocks, so do it in a thread and update progress every
278
268
  # 15 secs
279
- return unless Jamf::JPackage.valid_id packageName: jamf_pkg_name, cnx: jamf_cnx
280
-
281
269
  delete_jamf_package
282
270
 
283
271
  # The code below is used when we want real-time progress updates to xadm
@@ -321,6 +309,8 @@ module Xolo
321
309
  @jamf_package =
322
310
  if id
323
311
  log_debug "Jamf: Fetching Jamf::JPackage '#{id}'"
312
+ self.jamf_pkg_id = id # in case we only had the name before, now we have the id, so save it
313
+ save_local_data
324
314
  Jamf::JPackage.fetch id: id, cnx: jamf_cnx
325
315
  else
326
316
  return if deleting?
@@ -329,10 +319,16 @@ module Xolo
329
319
  end
330
320
  end
331
321
 
322
+ # @return [Boolean] does the jamf_package exist?
323
+ #########################
324
+ def jamf_package_exist?
325
+ !Jamf::JPackage.valid_id(packageName: jamf_pkg_name, cnx: jamf_cnx).nil?
326
+ end
327
+
332
328
  # @return [Jamf::JPackage] Create the Jamf::JPackage object for this version and return it
333
329
  #########################
334
330
  def create_jamf_package
335
- progress "Jamf: Creating Package object '#{jamf_pkg_name}'", log: :info
331
+ progress "Jamf: Creating Jamf::JPackage '#{jamf_pkg_name}'", log: :info
336
332
 
337
333
  # The filename is temporary, and will be replaced when the file is uploaded
338
334
  pkg = Jamf::JPackage.create(
@@ -406,6 +402,19 @@ module Xolo
406
402
  jamf_package.save
407
403
  end
408
404
 
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
+
409
418
  # repair the package object only
410
419
  #############################
411
420
  def repair_jamf_package
@@ -442,13 +451,13 @@ module Xolo
442
451
  # @return [void]
443
452
  #########################
444
453
  def delete_jamf_package
445
- pkg_id = Jamf::JPackage.valid_id packageName: jamf_pkg_name, cnx: jamf_cnx
454
+ pkg_id = jamf_pkg_id || Jamf::JPackage.valid_id(packageName: jamf_pkg_name, cnx: jamf_cnx)
446
455
  return unless pkg_id
447
456
 
448
457
  msg = "Jamf: Starting deletion of Package '#{jamf_pkg_name}' id #{jamf_pkg_id} at #{Time.now.strftime '%F %T'}"
449
458
  progress msg, log: :info
450
459
 
451
- warning = +"IMPORTANT: Package deletion is slow. If you plan to re-add this version, '#{version}', please\n "
460
+ warning = +"IMPORTANT: Package deletion can be slow. If you plan to re-add this version, '#{version}', please\n "
452
461
  warning <<
453
462
  if Xolo::Server.config.alert_tool
454
463
  'check your Xolo alerts for completion, which can take up to 5 minutes,'
@@ -685,8 +694,6 @@ module Xolo
685
694
  )
686
695
  else
687
696
  return if deleting?
688
- # don't create unless there's been a re-upload of the pkg
689
- return unless reupload_date
690
697
 
691
698
  create_jamf_installed_group
692
699
  end
@@ -736,51 +743,20 @@ module Xolo
736
743
  # The criteria for the smart group in Jamf that contains all Macs
737
744
  # with this version of this title installed
738
745
  #
739
- # If we have, or are about to update to, a version_script (EA) then use it,
740
- # otherwise use the app_name and app_bundle_id.
746
+ # We use the "Patch Reporting: #{title_object.display_name}" criterion so that we don't
747
+ # care whether the title uses a version-script or app data.
741
748
  #
742
749
  # @return [Array<Jamf::Criteriable::Criterion>]
743
750
  ###################################
744
751
  def jamf_installed_group_criteria
745
- # does this title use an app bundle?
746
- if title_object.app_name
747
- [
748
- Jamf::Criteriable::Criterion.new(
749
- and_or: :and,
750
- name: 'Application Title',
751
- search_type: 'is',
752
- value: title_object.app_name
753
- ),
754
-
755
- Jamf::Criteriable::Criterion.new(
756
- and_or: :and,
757
- name: 'Application Bundle ID',
758
- search_type: 'is',
759
- value: title_object.app_bundle_id
760
- ),
761
-
762
- Jamf::Criteriable::Criterion.new(
763
- and_or: :and,
764
- name: 'Application Version',
765
- search_type: 'is',
766
- value: version
767
- )
768
- ]
769
-
770
- # if not, it must have a version script
771
- elsif title_object.version_script
772
- [
773
- Jamf::Criteriable::Criterion.new(
774
- and_or: :and,
775
- name: title_object.jamf_normal_ea_name,
776
- search_type: 'is',
777
- value: version
778
- )
779
- ]
780
-
781
- else
782
- raise Xolo::Core::Exceptions::InvalidDataError, "Title #{title} has neither a version_script nor a defined app bundle."
783
- end
752
+ [
753
+ Jamf::Criteriable::Criterion.new(
754
+ and_or: :or,
755
+ name: "Patch Reporting: #{title_object.display_name}",
756
+ search_type: 'is',
757
+ value: version
758
+ )
759
+ ]
784
760
  end
785
761
 
786
762
  #########################
@@ -800,7 +776,7 @@ module Xolo
800
776
  # @return [Boolean] does the jamf_auto_reinstall_policy exist?
801
777
  ##########################
802
778
  def jamf_auto_reinstall_policy_exist?
803
- Jamf::Policy.all_names(cnx: jamf_cnx).include? jamf_auto_reinstall_policy_name
779
+ Jamf::Policy.all_names(:refresh, cnx: jamf_cnx).include? jamf_auto_reinstall_policy_name
804
780
  end
805
781
 
806
782
  # Create or fetch the auto re-install policy for this version
@@ -814,8 +790,6 @@ module Xolo
814
790
  Jamf::Policy.fetch(name: jamf_auto_reinstall_policy_name, cnx: jamf_cnx)
815
791
  else
816
792
  return if deleting?
817
- # don't create unless there's been a re-upload of the pkg
818
- return unless reupload_date
819
793
 
820
794
  create_jamf_auto_reinstall_policy
821
795
  end
@@ -845,6 +819,9 @@ module Xolo
845
819
  # @param pol [Jamf::Policy] the policy to configure
846
820
  ######################
847
821
  def configure_jamf_auto_reinstall_policy(pol)
822
+ # this creates the installed group if it doesn't already exist
823
+ jamf_installed_group
824
+
848
825
  pol.category = Xolo::Server::JAMF_XOLO_CATEGORY
849
826
  pol.set_trigger_event :checkin, true
850
827
  pol.set_trigger_event :custom, Xolo::BLANK
@@ -852,7 +829,7 @@ module Xolo
852
829
  pol.recon = false
853
830
  pol.retry_event = :checkin
854
831
  pol.retry_attempts = 5
855
- pol.scope.set_targets :computer_groups, [jamf_installed_group_name]
832
+ pol.scope.set_targets :computer_groups, [jamf_installed_group.name]
856
833
 
857
834
  # exclusions are for always
858
835
  set_policy_exclusions pol
@@ -876,41 +853,6 @@ module Xolo
876
853
  @jamf_auto_reinstall_policy_url = "#{jamf_gui_url}/policies.html?id=#{pol_id}&o=r"
877
854
  end
878
855
 
879
- # This will start a thread
880
- # that will wait some period of time (to allow for pkg uploads
881
- # to complete) before enabling and flushing the logs for the reinstall policy.
882
- # This will make all macs with this version installed get it re-installed.
883
- # @return [void]
884
- def wait_to_enable_reinstall_policy
885
- return if @enable_reinstall_policy_thread&.alive?
886
- return unless reupload_date
887
-
888
- # TODO: some setting to determine how long to wait?
889
- # - If uploading via the Jamf API, we need to give it time
890
- # to then upload the file to the cloud distribution point
891
- # - If uploading via a custom tool, we need to give that
892
- # tool time to re-upload to wherever it uploads to
893
- # - May need to wait for other non-jamf/non-xolo processes
894
- # to sync the package to other distribution points. This
895
- # might be very site-specific.
896
-
897
- # For now, we wait 15 minutes.
898
- wait_time = JAMF_AUTO_REINSTALL_WAIT_SECS
899
-
900
- @enable_reinstall_policy_thread = Thread.new do
901
- log_debug "Jamf: Starting enable_reinstall_policy_thread: waiting #{wait_time} seconds before enabling reinstall policy for version #{version} of title #{title}"
902
- sleep wait_time
903
-
904
- log_debug "Jamf: enable_reinstall_policy_thread: enabling and flushing logs for reinstall policy for version #{version} of title #{title}"
905
-
906
- pol = jamf_auto_reinstall_policy
907
- pol.enable
908
- pol.flush_logs
909
- pol.save
910
- end
911
- @enable_reinstall_policy_thread.name = "enable_reinstall_policy_thread-#{title}-#{version}"
912
- end
913
-
914
856
  ####### The Jamf Patch Policy
915
857
  ###########################################
916
858
  ###########################################
@@ -941,28 +883,6 @@ module Xolo
941
883
  def create_jamf_patch_policy
942
884
  progress "Jamf: Creating Patch Policy for Version '#{version}' of Title '#{title}'.", log: :info
943
885
 
944
- # TODO: decide how many patch policies - see comments at top
945
- # Probably one: for pilots initially and then rescoped to all for release
946
- #
947
- # TODO: How to set these, and should they be settable
948
- # at the Xolo::Title or Xolo::Version level?
949
- #
950
- # allow downgrade? No, to start with.
951
- # When a version is released, IF we are rolling back, then this will be set.
952
- # This is to be set only on the current release and only when it was a rollback.
953
- #
954
- # patch_unknown_versions... yes?
955
- #
956
- # if not in ssvc:
957
- # - grace period?
958
- # - update warning Message and Subject
959
- #
960
- # if in ssvc:
961
- # - any way to use existing icon?
962
- # - use title desc... do we want a version desc??
963
- # - notifications? Message and Subject? SSvc only, Notif Ctr?
964
- # - deadline and grace period message and subbject
965
-
966
886
  ppol = Jamf::PatchPolicy.create(
967
887
  cnx: jamf_cnx,
968
888
  name: jamf_patch_policy_name,
@@ -970,26 +890,12 @@ module Xolo
970
890
  target_version: version
971
891
  )
972
892
 
973
- # when first creating a patch policy, its status is always
974
- # 'pilot' so the scope targets are the pilot groups, if any.
975
- # When the version is released, the patch policy will be
976
- # rescoped to all targets (limited by eligibility)
977
- set_policy_pilot_groups ppol
978
-
979
- # exclusions are for always
980
- set_policy_exclusions ppol
893
+ configure_jamf_patch_policy(ppol)
981
894
 
982
- # This will be set to true as needed if
895
+ # This is always false to start will be set to true as needed if
983
896
  # a rollback is being done
984
897
  ppol.allow_downgrade = false
985
898
 
986
- # This should always be false, so that
987
- # we don't accidentally downgrade non-xolo test installs,
988
- # or server-pushed updates (like with commvault or cisco VPN)
989
- ppol.patch_unknown = false
990
-
991
- ppol.enable
992
-
993
899
  ppol.save
994
900
 
995
901
  # refetch it rather than using the one we just created
@@ -1003,14 +909,28 @@ module Xolo
1003
909
  assign_pkg_to_patch_in_jamf
1004
910
 
1005
911
  ppol = jamf_patch_policy
912
+
913
+ configure_jamf_patch_policy(ppol)
914
+
915
+ ppol.save
916
+ end
917
+
918
+ # Configure the patch policy
919
+ # NOTE: This doesn't save the changes!
920
+ ##############################
921
+ def configure_jamf_patch_policy(ppol)
1006
922
  ppol.name = jamf_patch_policy_name
1007
923
  ppol.target_version = version
1008
924
 
1009
- # This should always be false, so that
925
+ # This should default to false, so that
1010
926
  # we don't accidentally downgrade non-xolo test installs,
1011
927
  # or server-pushed updates (like with commvault or cisco VPN)
1012
- ppol.patch_unknown = false
928
+ ppol.patch_unknown = patch_unknown ? true : false
1013
929
 
930
+ # when first creating a patch policy, its status is always
931
+ # 'pilot' so the scope targets are the pilot groups, if any.
932
+ # When the version is released, the patch policy will be
933
+ # rescoped to all targets (limited by eligibility)
1014
934
  if pilot?
1015
935
  set_policy_pilot_groups ppol
1016
936
  else
@@ -1020,13 +940,74 @@ module Xolo
1020
940
  # exclusions are for always
1021
941
  set_policy_exclusions ppol
1022
942
 
943
+ # only pilot and released versions should have the patch policy enabled
1023
944
  if pilot? || released?
1024
945
  ppol.enable
1025
946
  else
1026
947
  ppol.disable
1027
948
  end
1028
949
 
1029
- ppol.save
950
+ configure_patch_pol_for_self_service ppol
951
+ end
952
+
953
+ # Configure the patch policy for self service
954
+ # NOTE: Does NOT save the policy changes!
955
+ # @param ppol [Jamf::PatchPolicy] The patch policy to configure
956
+ # @return [void]
957
+ # ###############################
958
+ def configure_patch_pol_for_self_service(ppol = nil)
959
+ ppol ||= jamf_patch_policy
960
+
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
963
+
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
976
+
977
+ return unless title_object.ssvc_icon_id
978
+
979
+ set_patch_policy_ssvc_icon ppol, title_object.ssvc_icon_id
980
+ end
981
+
982
+ # Set an existing ssvc icon for a given patch policy
983
+ #
984
+ # NOTE: Update this if/when ruby-jss and the JPAPI can handle
985
+ # PatchPolicy Icons.
986
+ #
987
+ # This shouldn't interfere with a future #save of a PatchPolicy
988
+ # object, since that xml won't contain self_service_icon data at all.
989
+ #
990
+ # @param ppol [Jamf::PatchPolicy] The Patch Pol. to set the icon for
991
+ # @param icon_id [Integer, String] The id of the existing icon to use.
992
+ # @return [Void]
993
+ ##########################
994
+ def set_patch_policy_ssvc_icon(ppol, icon_id)
995
+ # this str can't be frozen for now
996
+ icon_xml = +<<~ENDXML
997
+ <?xml version="1.0" encoding="UTF-8"?>
998
+ <patch_policy>
999
+ <user_interaction>
1000
+ <self_service_icon>
1001
+ <id>#{icon_id}</id>
1002
+ </self_service_icon>
1003
+ </user_interaction>
1004
+ </patch_policy>
1005
+ ENDXML
1006
+
1007
+ log_debug "Jamf: Adding existing SSvc icon to patch policy for version '#{version}' of title '#{title}'"
1008
+ # TODO: in ruby-jss, update c_put and related methods to
1009
+ # use unfrozen dups of strings for #gsub
1010
+ jamf_cnx.c_put ppol.rest_rsrc, icon_xml
1030
1011
  end
1031
1012
 
1032
1013
  # @return [String] the URL for the Jamf Pro Patch Policy that updates to this version
@@ -1296,7 +1277,14 @@ module Xolo
1296
1277
  @jamf_patch_version = title_object.jamf_patch_title.versions[version]
1297
1278
  return @jamf_patch_version if @jamf_patch_version
1298
1279
 
1299
- # TODO: wait for it to appear when adding?
1280
+ if repairing?
1281
+ # if we're repairing, and the version isn't visible in Jamf, then
1282
+ # jamf polled the title editor in the few moments it was disabled.
1283
+ # and jamf will see it again within 5 minutes.
1284
+ return nil
1285
+ end
1286
+
1287
+ # TODO: wait for it to appear when adding, or re-appear when repairing?
1300
1288
  msg = "Jamf: Version '#{version}' of Title '#{title}' is not visible in Jamf. Is the Patch enabled in the Title Editor?"
1301
1289
  log_error msg
1302
1290
  raise Xolo::NoSuchItemError, msg
@@ -1310,7 +1298,7 @@ module Xolo
1310
1298
  #
1311
1299
  # @return [void]
1312
1300
  #########################
1313
- def activate_patch_version_in_jamf
1301
+ def activate_managed_patch_version_in_jamf
1314
1302
  # don't do this if there's already one running for this instance
1315
1303
  if @activate_patch_version_thread&.alive?
1316
1304
  log_debug "Jamf: activate_patch_version_thread already running. Caller: #{caller_locations.first}"
@@ -1342,13 +1330,7 @@ module Xolo
1342
1330
  end
1343
1331
 
1344
1332
  if did_it
1345
- assign_pkg_to_patch_in_jamf
1346
- # give jamf a moment to catch up and refresh the patch title
1347
- # so we see the pkg has been assigned
1348
- sleep 2
1349
- title_object.jamf_patch_title(refresh: true)
1350
-
1351
- create_jamf_patch_policy
1333
+ activate_patch_version_in_jamf
1352
1334
  msg = "Jamf: Version '#{version}' of title '#{title}' is now visible in Jamf Pro. Package assigned and Patch policy created."
1353
1335
  log_info msg, alert: true
1354
1336
  else
@@ -1359,6 +1341,37 @@ module Xolo
1359
1341
  @activate_patch_version_thread.name = "activate_patch_version_thread-#{title}-#{version}"
1360
1342
  end
1361
1343
 
1344
+ # Patches for subscribed titles are already visible in Jamf Patch Management
1345
+ # So we just need to assign the pkg to the patch version, and create the patch policy.
1346
+ ##########################
1347
+ def activate_subscribed_patch_version_in_jamf
1348
+ msg = "Jamf: Assigning package and creating patch policy for version '#{version}' of subscribed title '#{title}'"
1349
+ log_info msg
1350
+ activate_patch_version_in_jamf
1351
+ end
1352
+
1353
+ # Assign the package for this version to the Jamf::PatchTitle::Version in Jamf
1354
+ # and create the patch policy for this version.
1355
+ #
1356
+ # @return [void]
1357
+ ##########################
1358
+ def activate_patch_version_in_jamf
1359
+ log_debug "Jamf: Activating patch version in Jamf for version '#{version}' of title '#{title}'"
1360
+
1361
+ # create the Jamf::JPackage object if needed
1362
+ jamf_package
1363
+ title_object.jamf_patch_title(refresh: true)
1364
+ sleep 3
1365
+
1366
+ assign_pkg_to_patch_in_jamf
1367
+ # give jamf a moment to catch up and refresh the patch title
1368
+ # so we see the pkg has been assigned
1369
+ sleep 2
1370
+ title_object.jamf_patch_title(refresh: true)
1371
+
1372
+ create_jamf_patch_policy
1373
+ end
1374
+
1362
1375
  # Assign the Package to the Jamf::PatchTitle::Version for this Xolo version.
1363
1376
  # This 'activates' the version in Jamf Patch, and must happen before
1364
1377
  # patch policies can be created
@@ -1374,10 +1387,23 @@ module Xolo
1374
1387
  # @return [void]
1375
1388
  ########################################
1376
1389
  def assign_pkg_to_patch_in_jamf
1377
- log_info "Jamf: Assigning package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}'"
1390
+ patch_vers_obj = jamf_patch_version
1391
+
1392
+ if patch_vers_obj.nil? && repairing?
1393
+ msg = "Jamf: Cant re-assign package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}' at this time. If there are problems with it, try 'repair' again later."
1394
+ progress msg, log: :info
1395
+ return
1396
+ end
1397
+
1398
+ progress "Jamf: Assigning package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}'", log: :info
1399
+
1400
+ log_debug "Jamf: jamf_patch_version is: #{patch_vers_obj}"
1401
+
1402
+ patch_vers_obj.package = jamf_pkg_name
1403
+ log_debug "Jamf: jamf_patch_version after assignment is: #{patch_vers_obj}"
1378
1404
 
1379
- jamf_patch_version.package = jamf_pkg_name
1380
1405
  title_object.jamf_patch_title.save
1406
+ log_debug 'Jamf: Saved jamf_patch_title after assigning package to version.'
1381
1407
  end
1382
1408
 
1383
1409
  # Get the patch report for this version
@@ -48,6 +48,19 @@ module Xolo
48
48
  # @return [void]
49
49
  ##########################
50
50
  def create_patch_in_ted
51
+ if subscribed?
52
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor patch creation"
53
+ return
54
+ end
55
+
56
+ # if the patch exists, remove and recreate it
57
+ if ted_patch
58
+ progress "Title Editor: Patch '#{version}' of SoftwareTitle '#{title}' already exists, removing & readding it..."
59
+ ted_title.patches.delete_patch ted_patch.patchId
60
+ sleep 2
61
+ ted_patch(refresh: true)
62
+ end
63
+
51
64
  progress "Title Editor: Creating Patch '#{version}' of SoftwareTitle '#{title}'", log: :info
52
65
  ted_title.patches.add_patch(
53
66
  version: version,
@@ -75,6 +88,11 @@ module Xolo
75
88
  # @return [void]
76
89
  ##########################
77
90
  def update_patch_in_ted
91
+ if subscribed?
92
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor patch update"
93
+ return
94
+ end
95
+
78
96
  progress "Title Editor: Updating Patch '#{version}' SoftwareTitle '#{title}'", log: :info
79
97
 
80
98
  Xolo::Server::Version::ATTRIBUTES.each do |attr, deets|
@@ -340,12 +358,19 @@ module Xolo
340
358
  # @return [String] the URL for the Title Editor Web App page for this patch
341
359
  ###################################
342
360
  def ted_patch_url
361
+ return unless managed?
362
+
343
363
  "https://#{Xolo::Server.config.ted_hostname}/patches/#{ted_id_number}"
344
364
  end
345
365
 
346
366
  # Ensure all the TEd items for this version are correct based on the server data.
347
367
  #########################
348
368
  def repair_ted_patch
369
+ if subscribed?
370
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor patch repair"
371
+ return
372
+ end
373
+
349
374
  progress "Title Editor: Repairing Patch '#{version}' of SoftwareTitle '#{title}'", log: :info
350
375
 
351
376
  Xolo::Server::Version::ATTRIBUTES.each do |attr, deets|