ruby-jss 1.2.3 → 1.2.4a1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jamf.rb +169 -0
  3. data/lib/jamf/api/abstract_classes/collection_resource.rb +422 -0
  4. data/lib/jamf/api/abstract_classes/generic_reference.rb +145 -0
  5. data/lib/jamf/api/abstract_classes/json_object.rb +1074 -0
  6. data/lib/jamf/api/abstract_classes/prestage.rb +219 -0
  7. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +126 -0
  8. data/lib/jamf/api/abstract_classes/resource.rb +250 -0
  9. data/lib/jamf/api/abstract_classes/singleton_resource.rb +87 -0
  10. data/lib/jamf/api/attribute_classes/ip_address.rb +66 -0
  11. data/lib/jamf/api/attribute_classes/timestamp.rb +144 -0
  12. data/lib/jamf/api/connection.rb +734 -0
  13. data/lib/jamf/api/connection/api_error.rb +111 -0
  14. data/lib/jamf/api/connection/api_error_styleguide.rb +96 -0
  15. data/lib/jamf/api/connection/token.rb +220 -0
  16. data/lib/jamf/api/json_objects/account_prefs.rb +79 -0
  17. data/lib/jamf/api/json_objects/android_details.rb +139 -0
  18. data/lib/jamf/api/json_objects/appletv_details.rb +110 -0
  19. data/lib/jamf/api/json_objects/attachment.rb +68 -0
  20. data/lib/jamf/api/json_objects/cellular_network.rb +151 -0
  21. data/lib/jamf/api/json_objects/change_log_entry.rb +77 -0
  22. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +67 -0
  23. data/lib/jamf/api/json_objects/country.rb +51 -0
  24. data/lib/jamf/api/json_objects/extension_attribute_value.rb +128 -0
  25. data/lib/jamf/api/json_objects/installed_application.rb +59 -0
  26. data/lib/jamf/api/json_objects/installed_certificate.rb +53 -0
  27. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +67 -0
  28. data/lib/jamf/api/json_objects/installed_ebook.rb +58 -0
  29. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +59 -0
  30. data/lib/jamf/api/json_objects/inventory_preload_extension_attribute.rb +52 -0
  31. data/lib/jamf/api/json_objects/ios_details.rb +244 -0
  32. data/lib/jamf/api/json_objects/location.rb +95 -0
  33. data/lib/jamf/api/json_objects/md_prestage_name.rb +57 -0
  34. data/lib/jamf/api/json_objects/md_prestage_names.rb +82 -0
  35. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +165 -0
  36. data/lib/jamf/api/json_objects/mobile_device_details.rb +219 -0
  37. data/lib/jamf/api/json_objects/mobile_device_security.rb +101 -0
  38. data/lib/jamf/api/json_objects/prestage_assignment.rb +61 -0
  39. data/lib/jamf/api/json_objects/prestage_location.rb +104 -0
  40. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +132 -0
  41. data/lib/jamf/api/json_objects/prestage_scope.rb +54 -0
  42. data/lib/jamf/api/json_objects/prestage_sync_status.rb +63 -0
  43. data/lib/jamf/api/json_objects/purchasing_data.rb +125 -0
  44. data/lib/jamf/api/mixins/abstract.rb +58 -0
  45. data/lib/jamf/api/mixins/bulk_deletable.rb +39 -0
  46. data/lib/jamf/api/mixins/change_log.rb +136 -0
  47. data/lib/jamf/api/mixins/extendable.rb +75 -0
  48. data/lib/jamf/api/mixins/immutable.rb +39 -0
  49. data/lib/jamf/api/mixins/locatable.rb +124 -0
  50. data/lib/jamf/api/mixins/lockable.rb +48 -0
  51. data/lib/jamf/api/mixins/referable.rb +92 -0
  52. data/lib/jamf/api/mixins/searchable.rb +202 -0
  53. data/lib/jamf/api/mixins/uncreatable.rb +40 -0
  54. data/lib/jamf/api/mixins/undeletable.rb +40 -0
  55. data/lib/jamf/api/resources/collection_resources/account.rb +163 -0
  56. data/lib/jamf/api/resources/collection_resources/building.rb +114 -0
  57. data/lib/jamf/api/resources/collection_resources/category.rb +82 -0
  58. data/lib/jamf/api/resources/collection_resources/computer.rb +49 -0
  59. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +80 -0
  60. data/lib/jamf/api/resources/collection_resources/department.rb +79 -0
  61. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +45 -0
  62. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +274 -0
  63. data/lib/jamf/api/resources/collection_resources/md_prestage.rb +139 -0
  64. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +315 -0
  65. data/lib/jamf/api/resources/collection_resources/script.rb +190 -0
  66. data/lib/jamf/api/resources/collection_resources/site.rb +77 -0
  67. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +131 -0
  68. data/lib/jamf/api/resources/singleton_resources/authorization.rb +88 -0
  69. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +139 -0
  70. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +95 -0
  71. data/lib/jamf/client.rb +301 -0
  72. data/lib/jamf/client/jamf_binary.rb +132 -0
  73. data/lib/jamf/client/jamf_helper.rb +298 -0
  74. data/lib/jamf/client/management_action.rb +114 -0
  75. data/lib/jamf/compatibility.rb +88 -0
  76. data/lib/jamf/composer.rb +190 -0
  77. data/lib/jamf/configuration.rb +281 -0
  78. data/lib/jamf/exceptions.rb +107 -0
  79. data/lib/jamf/ruby_extensions.rb +36 -0
  80. data/lib/jamf/ruby_extensions/array.rb +35 -0
  81. data/lib/jamf/ruby_extensions/array/predicates.rb +46 -0
  82. data/lib/jamf/ruby_extensions/array/utils.rb +47 -0
  83. data/lib/jamf/ruby_extensions/filetest.rb +32 -0
  84. data/lib/jamf/ruby_extensions/filetest/predicates.rb +46 -0
  85. data/lib/jamf/ruby_extensions/hash.rb +33 -0
  86. data/lib/jamf/ruby_extensions/hash/backports.rb +92 -0
  87. data/lib/jamf/ruby_extensions/ipaddr.rb +37 -0
  88. data/lib/jamf/ruby_extensions/ipaddr/utils.rb +95 -0
  89. data/lib/jamf/ruby_extensions/object.rb +30 -0
  90. data/lib/jamf/ruby_extensions/object/predicates.rb +51 -0
  91. data/lib/jamf/ruby_extensions/pathname.rb +39 -0
  92. data/lib/jamf/ruby_extensions/pathname/predicates.rb +50 -0
  93. data/lib/jamf/ruby_extensions/pathname/utils.rb +75 -0
  94. data/lib/jamf/ruby_extensions/string.rb +35 -0
  95. data/lib/jamf/ruby_extensions/string/backports.rb +66 -0
  96. data/lib/jamf/ruby_extensions/string/conversions.rb +65 -0
  97. data/lib/jamf/ruby_extensions/string/predicates.rb +47 -0
  98. data/lib/jamf/utility.rb +423 -0
  99. data/lib/jamf/validate.rb +224 -0
  100. data/lib/jamf/version.rb +32 -0
  101. data/lib/jpapi.rb +26 -0
  102. data/lib/jss/version.rb +1 -1
  103. metadata +104 -4
@@ -0,0 +1,132 @@
1
+ ### Copyright 2019 Pixar
2
+
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+ ###
25
+
26
+ ###
27
+ module JSS
28
+
29
+ #
30
+ class Client
31
+
32
+ # Constants
33
+ #####################################
34
+
35
+ # The Pathname to the jamf binary executable
36
+ # Before SIP (macOS 10.10 and below)
37
+ ORIG_JAMF_BINARY = Pathname.new '/usr/sbin/jamf'
38
+
39
+ # The Pathname to the jamf binary executable
40
+ # After SIP (OS X 10.11 and above)
41
+ SIP_JAMF_BINARY = USR_LOCAL_BIN_FOLDER + 'jamf'
42
+
43
+ # The path to the jamf binary
44
+ JAMF_BINARY = SIP_JAMF_BINARY.executable? ? SIP_JAMF_BINARY : ORIG_JAMF_BINARY
45
+
46
+ # These jamf commands don't need root privs (most do)
47
+ ROOTLESS_JAMF_COMMANDS = %i[
48
+ about
49
+ checkJSSConnection
50
+ getARDFields
51
+ getComputerName
52
+ help
53
+ listUsers
54
+ version
55
+ ].freeze
56
+
57
+ # the option that makes the jamf binary verbose
58
+ JAMF_VERBOSE_OPT = ' -verbose'.freeze
59
+
60
+ # class Methods
61
+ #####################################
62
+
63
+ # Run an arbitrary jamf binary command.
64
+ #
65
+ # @note Most jamf commands require superuser/root privileges.
66
+ #
67
+ # @param command[String,Symbol] the jamf binary command to run
68
+ # The command is the single jamf command that comes after the/usr/bin/jamf.
69
+ #
70
+ # @param args[String,Array] the arguments passed to the jamf command.
71
+ # This is to be passed to Kernel.` (backtick), after being combined with the
72
+ # jamf binary and the jamf command
73
+ #
74
+ # @param verbose[Boolean] Should the stdout & stderr of the jamf binary be sent to
75
+ # the current stdout in realtime, as well as returned as a string?
76
+ #
77
+ # @return [String] the stdout & stderr of the jamf binary.
78
+ #
79
+ # @example
80
+ # These two are equivalent:
81
+ #
82
+ # JSS::Client.run_jamf "recon", "-assetTag 12345 -department 'IT Support'"
83
+ #
84
+ # JSS::Client.run_jamf :recon, ['-assetTag', '12345', '-department', 'IT Support'"]
85
+ #
86
+ #
87
+ # The details of the Process::Status for the jamf binary process can be
88
+ # captured from $CHILD_STATUS immediately after calling. (See Process::Status)
89
+ #
90
+ def self.run_jamf(command, args = nil, verbose = false)
91
+ raise JSS::UnmanagedError, 'The jamf binary is not installed on this computer.' unless installed?
92
+ unless ROOTLESS_JAMF_COMMANDS.include?(command.to_sym) || JSS.superuser?
93
+ raise JSS::UnsupportedError, 'You must have root privileges to run that jamf binary command'
94
+ end
95
+ cmd = build_jamf_command command, args
96
+ cmd += " #{JAMF_VERBOSE_OPT}" if verbose && !cmd.include?(JAMF_VERBOSE_OPT)
97
+ execute_jamf cmd, verbose
98
+ end # run_jamf
99
+
100
+ private_class_method
101
+
102
+ def self.build_jamf_command(command, args)
103
+ case args
104
+ when nil
105
+ "#{JAMF_BINARY} #{command}"
106
+ when String
107
+ "#{JAMF_BINARY} #{command} #{args}"
108
+ when Array
109
+ ([JAMF_BINARY.to_s, command] + args).join(' ')
110
+ else
111
+ raise JSS::InvalidDataError, 'args must be a String or Array of Strings'
112
+ end # case
113
+ end
114
+
115
+ def self.execute_jamf(cmd, verbose)
116
+ puts "Running: #{cmd}" if verbose
117
+ output = ''
118
+ IO.popen("#{cmd} 2>&1") do |proc|
119
+ loop do
120
+ line = proc.gets
121
+ break unless line
122
+ output << line
123
+ puts line if verbose
124
+ end
125
+ end
126
+ output.force_encoding('UTF-8')
127
+ output
128
+ end
129
+
130
+ end # class Client
131
+
132
+ end # module
@@ -0,0 +1,298 @@
1
+ ### Copyright 2019 Pixar
2
+
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+ ###
25
+
26
+ ###
27
+ module JSS
28
+
29
+ #
30
+ class Client
31
+
32
+ # Constants
33
+ #####################################
34
+
35
+ # The Pathname to the jamfHelper executable
36
+ JAMF_HELPER = SUPPORT_BIN_FOLDER + 'jamfHelper.app/Contents/MacOS/jamfHelper'
37
+
38
+ # The window_type options for jamfHelper
39
+ JAMF_HELPER_WINDOW_TYPES = {
40
+ hud: 'hud',
41
+ utility: 'utility',
42
+ util: 'utility',
43
+ full_screen: 'fs',
44
+ fs: 'fs'
45
+ }.freeze
46
+
47
+ # The possible window positions for jamfHelper
48
+ JAMF_HELPER_WINDOW_POSITIONS = [nil, :ul, :ll, :ur, :lr].freeze
49
+
50
+ # The available buttons in jamfHelper
51
+ JAMF_HELPER_BUTTONS = [1, 2].freeze
52
+
53
+ # The possible alignment positions in jamfHelper
54
+ JAMF_HELPER_ALIGNMENTS = %i[right left center justified natural].freeze
55
+
56
+ # class Methods
57
+ #####################################
58
+
59
+
60
+ # A wrapper for the jamfHelper command, which can display a window on the client machine.
61
+ #
62
+ # The first parameter must be a symbol defining what kind of window to display. The options are
63
+ # - :hud - creates an Apple "Heads Up Display" style window
64
+ # - :utility or :util - creates an Apple "Utility" style window
65
+ # - :fs or :full_screen or :fullscreen - creates a full screen window that restricts all user input
66
+ # WARNING: Remote access must be used to unlock machines in this mode
67
+ #
68
+ # The remaining options Hash can contain any of the options listed. See below for descriptions.
69
+ #
70
+ # The value returned is the Integer exitstatus/stdout (both are the same) of the jamfHelper command.
71
+ # The meanings of those integers are:
72
+ #
73
+ # - 0 - Button 1 was clicked
74
+ # - 1 - The Jamf Helper was unable to launch
75
+ # - 2 - Button 2 was clicked
76
+ # - 3 - Process was started as a launchd task
77
+ # - XX1 - Button 1 was clicked with a value of XX seconds selected in the drop-down
78
+ # - XX2 - Button 2 was clicked with a value of XX seconds selected in the drop-down
79
+ # - 239 - The exit button was clicked
80
+ # - 240 - The "ProductVersion" in sw_vers did not return 10.5.X, 10.6.X or 10.7.X
81
+ # - 243 - The window timed-out with no buttons on the screen
82
+ # - 250 - Bad "-windowType"
83
+ # - 254 - Cancel button was select with delay option present
84
+ # - 255 - No "-windowType"
85
+ #
86
+ # If the :abandon_process option is given, the integer returned is the Process ID
87
+ # of the abondoned process running jamfHelper.
88
+ #
89
+ # See also /Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -help
90
+ #
91
+ # @note the -startlaunchd and -kill options are not available in this implementation, since
92
+ # they don't work at the moment (casper 9.4).
93
+ # -startlaunchd seems to be required to NOT use launchd, and when it's ommited, an error is generated
94
+ # about the launchd plist permissions being incorrect.
95
+ #
96
+ # @param window_type[Symbol] The type of window to display
97
+ #
98
+ # @param opts[Hash] the options for the window
99
+ #
100
+ # @option opts :window_position [Symbol,nil] one of [ nil, :ul, :ll. :ur, :lr ]
101
+ # Positions window in the upper right, upper left, lower right or lower left of the user's screen
102
+ # If no input is given, the window defaults to the center of the screen
103
+ #
104
+ # @option opts :title [String]
105
+ # Sets the window's title to the specified string
106
+ #
107
+ # @option opts :heading [String]
108
+ # Sets the heading of the window to the specified string
109
+ #
110
+ # @option opts :align_heading [Symbol] one of [:right, :left, :center, :justified, :natural]
111
+ # Aligns the heading to the specified alignment
112
+ #
113
+ # @option opts :description [String]
114
+ # Sets the main contents of the window to the specified string
115
+ #
116
+ # @option opts :align_description [Symbol] one of [:right, :left, :center, :justified, :natural]
117
+ # Aligns the description to the specified alignment
118
+ #
119
+ # @option opts :icon [String,Pathname]
120
+ # Sets the windows image field to the image located at the specified path
121
+ #
122
+ # @option opts :icon_size [Integer]
123
+ # Changes the image frame to the specified pixel size
124
+ #
125
+ # @option opts :full_screen_icon [any value]
126
+ # Scales the "icon" to the full size of the window.
127
+ # Note: Only available in full screen mode
128
+ #
129
+ # @option opts :button1 [String]
130
+ # Creates a button with the specified label
131
+ #
132
+ # @option opts :button2 [String]
133
+ # Creates a second button with the specified label
134
+ #
135
+ # @option opts :default_button [Integer] either 1 or 2
136
+ # Sets the default button of the window to the specified button. The Default Button will respond to "return"
137
+ #
138
+ # @option opts :cancel_button [Integer] either 1 or 2
139
+ # Sets the cancel button of the window to the specified button. The Cancel Button will respond to "escape"
140
+ #
141
+ # @option opts :timeout [Integer]
142
+ # Causes the window to timeout after the specified amount of seconds
143
+ # Note: The timeout will cause the default button, button 1 or button 2 to be selected (in that order)
144
+ #
145
+ # @option opts :show_delay_options [String,Array<Integer>] A String of comma-separated Integers, or an Array of Integers.
146
+ # Enables the "Delay Options Mode". The window will display a dropdown with the values passed through the string
147
+ #
148
+ # @option opts :countdown [any value]
149
+ # Displays a string notifying the user when the window will time out
150
+ #
151
+ # @option opts :align_countdown [Symbol] one of [:right, :left, :center, :justified, :natural]
152
+ # Aligns the countdown to the specified alignment
153
+ #
154
+ # @option opts :lock_hud [Boolean]
155
+ # Removes the ability to exit the HUD by selecting the close button
156
+ #
157
+ # @option opts :abandon_process [Boolean] Abandon the jamfHelper process so that your code can exit.
158
+ # This is mostly used so that a policy can finish while a dialog is waiting
159
+ # (possibly forever) for user response. When true, the returned value is the
160
+ # process id of the abandoned jamfHelper process.
161
+ #
162
+ # @option opts :output_file [String, Pathname] Save the output of jamfHelper
163
+ # (the exit code) into this file. This is useful when using abandon_process.
164
+ # The output file can be examined later to see what happened. If this option
165
+ # is not provided, no output is saved.
166
+ #
167
+ # @option opts :arg_string [String] The jamfHelper commandline args as a single
168
+ # String, the way you'd specify them in a shell. This is appended to any
169
+ # Ruby options provided when calling the method. So calling:
170
+ # JSS::Client.jamf_helper :hud, title: 'This is a title', arg_string: '-heading "this is a heading"'
171
+ # will run
172
+ # jamfHelper -windowType hud -title 'this is a title' -heading "this is a heading"
173
+ # When using this, be careful not to specify the windowType, since it's generated
174
+ # by the first, required, parameter of this method.
175
+ #
176
+ # @return [Integer] the exit status of the jamfHelper command. See above.
177
+ #
178
+ def self.jamf_helper(window_type = :hud, opts = {})
179
+ raise JSS::UnmanagedError, 'The jamfHelper app is not installed properly on this computer.' unless JAMF_HELPER.executable?
180
+
181
+ unless JAMF_HELPER_WINDOW_TYPES.include? window_type
182
+ raise JSS::InvalidDataError, "The first parameter must be a window type, one of :#{JAMF_HELPER_WINDOW_TYPES.keys.join(', :')}."
183
+ end
184
+
185
+ # start building the arg array
186
+
187
+ args = ['-startlaunchd', '-windowType', JAMF_HELPER_WINDOW_TYPES[window_type]]
188
+
189
+ opts.keys.each do |opt|
190
+ case opt
191
+ when :window_position
192
+ raise JSS::InvalidDataError, ":window_position must be one of :#{JAMF_HELPER_WINDOW_POSITIONS.join(', :')}." unless \
193
+ JAMF_HELPER_WINDOW_POSITIONS.include? opts[opt].to_sym
194
+ args << '-windowPosition'
195
+ args << opts[opt].to_s
196
+
197
+ when :title
198
+ args << '-title'
199
+ args << opts[opt].to_s
200
+
201
+ when :heading
202
+ args << '-heading'
203
+ args << opts[opt].to_s
204
+
205
+ when :align_heading
206
+ raise JSS::InvalidDataError, ":align_heading must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
207
+ JAMF_HELPER_ALIGNMENTS.include? opts[opt].to_sym
208
+ args << '-alignHeading'
209
+ args << opts[opt].to_s
210
+
211
+ when :description
212
+ args << '-description'
213
+ args << opts[opt].to_s
214
+
215
+ when :align_description
216
+ raise JSS::InvalidDataError, ":align_description must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
217
+ JAMF_HELPER_ALIGNMENTS.include? opts[opt].to_sym
218
+ args << '-alignDescription'
219
+ args << opts[opt].to_s
220
+
221
+ when :icon
222
+ args << '-icon'
223
+ args << opts[opt].to_s
224
+
225
+ when :icon_size
226
+ args << '-iconSize'
227
+ args << opts[opt].to_s
228
+
229
+ when :full_screen_icon
230
+ args << '-fullScreenIcon'
231
+
232
+ when :button1
233
+ args << '-button1'
234
+ args << opts[opt].to_s
235
+
236
+ when :button2
237
+ args << '-button2'
238
+ args << opts[opt].to_s
239
+
240
+ when :default_button
241
+ raise JSS::InvalidDataError, ":default_button must be one of #{JAMF_HELPER_BUTTONS.join(', ')}." unless \
242
+ JAMF_HELPER_BUTTONS.include? opts[opt]
243
+ args << '-defaultButton'
244
+ args << opts[opt].to_s
245
+
246
+ when :cancel_button
247
+ raise JSS::InvalidDataError, ":cancel_button must be one of #{JAMF_HELPER_BUTTONS.join(', ')}." unless \
248
+ JAMF_HELPER_BUTTONS.include? opts[opt]
249
+ args << '-cancelButton'
250
+ args << opts[opt].to_s
251
+
252
+ when :timeout
253
+ args << '-timeout'
254
+ args << opts[opt].to_s
255
+
256
+ when :show_delay_options
257
+ args << '-showDelayOptions'
258
+ args << JSS.to_s_and_a(opts[opt])[:arrayform].join(', ')
259
+
260
+ when :countdown
261
+ args << '-countdown' if opts[opt]
262
+
263
+ when :align_countdown
264
+ raise JSS::InvalidDataError, ":align_countdown must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
265
+ JAMF_HELPER_ALIGNMENTS.include? opts[opt].to_sym
266
+ args << '-alignCountdown'
267
+ args << opts[opt].to_s
268
+
269
+ when :lock_hud
270
+ args << '-lockHUD' if opts[opt]
271
+
272
+ end # case opt
273
+ end # each do opt
274
+
275
+ cmd = Shellwords.escape JAMF_HELPER.to_s
276
+ args.each { |arg| cmd << " #{Shellwords.escape arg}" }
277
+ cmd << " #{opts[:arg_string]}" if opts[:arg_string]
278
+ cmd << " > #{Shellwords.escape opts[:output_file]}" if opts[:output_file]
279
+
280
+ if opts[:abandon_process]
281
+ pid = Process.fork
282
+ if pid.nil?
283
+ # In child
284
+ exec cmd
285
+ else
286
+ # In parent
287
+ Process.detach(pid)
288
+ pid
289
+ end
290
+ else
291
+ system cmd
292
+ $CHILD_STATUS.exitstatus
293
+ end
294
+ end # def self.jamf_helper
295
+
296
+ end # class Client
297
+
298
+ end # module
@@ -0,0 +1,114 @@
1
+ ### Copyright 2019 Pixar
2
+
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+ ###
25
+
26
+ ###
27
+ module JSS
28
+
29
+ # jamf client computer
30
+ class Client
31
+
32
+ # Constants
33
+ #####################################
34
+
35
+ # The Pathname to the Management Action executable
36
+ MGMT_ACTION = SUPPORT_BIN_FOLDER + 'Management Action.app/Contents/MacOS/Management Action'
37
+
38
+ # NC_ALERT_STYLE_FLAGS = 4432
39
+ # NCPREFS_DOMAIN = 'com.apple.ncprefs'.freeze
40
+ # MGMT_ACTION_BUNDLE_ID = 'com.jamfsoftware.Management-Action'.freeze
41
+ # HUP_NOTIF_CTR_CMD = '/usr/bin/killall sighup usernoted NotificationCenter'.freeze
42
+
43
+ # class Methods
44
+ #####################################
45
+
46
+ def self.management_action(msg, title: nil, subtitle: nil, delay: 0)
47
+ raise JSS::InvalidDataError, 'delay: must be a non-negative integer.' unless delay.is_a?(Integer) && delay > -1
48
+
49
+ cmd = Shellwords.escape MGMT_ACTION.to_s
50
+ cmd << " -message #{Shellwords.escape msg.to_s}"
51
+ cmd << " -title #{Shellwords.escape title.to_s}" if title
52
+ cmd << " -subtitle #{Shellwords.escape subtitle.to_s}" if subtitle
53
+ cmd << " -deliverydelay #{Shellwords.escape delay}" if delay > 0
54
+ `#{cmd} 2>&1`
55
+ end
56
+
57
+ # an alias of management_action
58
+ def self.nc_notify(msg, title: nil, subtitle: nil, delay: 0)
59
+ management_action(msg, title: title, subtitle: subtitle, delay: delay)
60
+ end
61
+
62
+ private_class_method
63
+
64
+ # Skipping all the force-alerts stuff until we figure out cleaner
65
+ # ways to do it in 10.13+
66
+ # The plan is to be able to make the NotificationCenter notification be an
67
+ # 'alert' (which stays visible til the user clicks) or a
68
+ # 'banner' (which vanishes in a few seconds), regardless of the user's
69
+ # setting in the NC prefs.
70
+
71
+ def self.force_alerts
72
+ orig_flags = {}
73
+ console_users.each do |user|
74
+ orig_flags[user] = set_mgmt_action_ncprefs_flags user, NC_ALERT_STYLE_FLAGS, hup: false
75
+ end
76
+ system HUP_NOTIF_CTR_CMD unless orig_flags.empty?
77
+ sleep 1
78
+ orig_flags
79
+ end
80
+
81
+ def self.restore_alerts(orig_flags)
82
+ orig_flags.each do |user, flags|
83
+ set_mgmt_action_ncprefs_flags user, flags, hup: false
84
+ end
85
+ system HUP_NOTIF_CTR_CMD unless orig_flags.empty?
86
+ end
87
+
88
+ # set the NotificationCenter option flags for a user
89
+ # flags = an integer.
90
+ #
91
+ # Doesn't seem to work in 10.13, so ignore this for now.
92
+ #
93
+ # @return [Integer] the original flags, or given flags if no originals.
94
+ #
95
+ def self.set_mgmt_action_ncprefs_flags(user, flags, hup: true)
96
+ plist = Pathname.new "/Users/#{user}/Library/Preferences/#{NCPREFS_DOMAIN}.plist"
97
+ prefs = JSS.parse_plist plist
98
+ mgmt_action_setting = prefs['apps'].select { |a| a['bundle-id'] == MGMT_ACTION_BUNDLE_ID }.first
99
+ if mgmt_action_setting
100
+ orig_flags = mgmt_action_setting['flags']
101
+ mgmt_action_setting['flags'] = flags
102
+ else
103
+ orig_flags = flags
104
+ prefs['apps'] << { 'bundle-id' => MGMT_ACTION_BUNDLE_ID, 'flags' => flags }
105
+ end
106
+ # system "/usr/bin/defaults write #{NCPREFS_DOMAIN} '#{prefs.to_plist}'"
107
+ plist.open('w') { |f| f.write prefs.to_plist }
108
+ system HUP_NOTIF_CTR_CMD if hup
109
+ orig_flags
110
+ end
111
+
112
+ end # class Client
113
+
114
+ end # module