ruby-jss 0.6.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.

Potentially problematic release.


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

Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGES.md +112 -0
  4. data/LICENSE.txt +174 -0
  5. data/README.md +426 -0
  6. data/THANKS.md +6 -0
  7. data/bin/cgrouper +485 -0
  8. data/bin/subnet-update +400 -0
  9. data/lib/jss-api.rb +2 -0
  10. data/lib/jss.rb +190 -0
  11. data/lib/jss/api_connection.rb +410 -0
  12. data/lib/jss/api_object.rb +616 -0
  13. data/lib/jss/api_object/advanced_search.rb +389 -0
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
  17. data/lib/jss/api_object/building.rb +92 -0
  18. data/lib/jss/api_object/category.rb +147 -0
  19. data/lib/jss/api_object/computer.rb +852 -0
  20. data/lib/jss/api_object/creatable.rb +98 -0
  21. data/lib/jss/api_object/criteriable.rb +189 -0
  22. data/lib/jss/api_object/criteriable/criteria.rb +231 -0
  23. data/lib/jss/api_object/criteriable/criterion.rb +228 -0
  24. data/lib/jss/api_object/department.rb +93 -0
  25. data/lib/jss/api_object/distribution_point.rb +560 -0
  26. data/lib/jss/api_object/extendable.rb +221 -0
  27. data/lib/jss/api_object/extension_attribute.rb +466 -0
  28. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  29. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  30. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  31. data/lib/jss/api_object/group.rb +380 -0
  32. data/lib/jss/api_object/group/computer_group.rb +124 -0
  33. data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
  34. data/lib/jss/api_object/group/user_group.rb +139 -0
  35. data/lib/jss/api_object/ldap_server.rb +535 -0
  36. data/lib/jss/api_object/locatable.rb +286 -0
  37. data/lib/jss/api_object/matchable.rb +97 -0
  38. data/lib/jss/api_object/mobile_device.rb +556 -0
  39. data/lib/jss/api_object/netboot_server.rb +148 -0
  40. data/lib/jss/api_object/network_segment.rb +414 -0
  41. data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
  42. data/lib/jss/api_object/package.rb +839 -0
  43. data/lib/jss/api_object/peripheral.rb +335 -0
  44. data/lib/jss/api_object/peripheral_type.rb +295 -0
  45. data/lib/jss/api_object/policy.rb +898 -0
  46. data/lib/jss/api_object/purchasable.rb +316 -0
  47. data/lib/jss/api_object/removable_macaddr.rb +98 -0
  48. data/lib/jss/api_object/scopable.rb +136 -0
  49. data/lib/jss/api_object/scopable/scope.rb +621 -0
  50. data/lib/jss/api_object/script.rb +631 -0
  51. data/lib/jss/api_object/self_servable.rb +356 -0
  52. data/lib/jss/api_object/site.rb +93 -0
  53. data/lib/jss/api_object/software_update_server.rb +109 -0
  54. data/lib/jss/api_object/updatable.rb +117 -0
  55. data/lib/jss/api_object/uploadable.rb +138 -0
  56. data/lib/jss/api_object/user.rb +272 -0
  57. data/lib/jss/client.rb +504 -0
  58. data/lib/jss/compatibility.rb +66 -0
  59. data/lib/jss/composer.rb +185 -0
  60. data/lib/jss/configuration.rb +306 -0
  61. data/lib/jss/db_connection.rb +298 -0
  62. data/lib/jss/exceptions.rb +95 -0
  63. data/lib/jss/ruby_extensions.rb +35 -0
  64. data/lib/jss/ruby_extensions/filetest.rb +43 -0
  65. data/lib/jss/ruby_extensions/hash.rb +79 -0
  66. data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
  67. data/lib/jss/ruby_extensions/pathname.rb +77 -0
  68. data/lib/jss/ruby_extensions/string.rb +59 -0
  69. data/lib/jss/ruby_extensions/time.rb +63 -0
  70. data/lib/jss/server.rb +108 -0
  71. data/lib/jss/utility.rb +478 -0
  72. data/lib/jss/version.rb +31 -0
  73. metadata +187 -0
@@ -0,0 +1,898 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ ######################
29
+ ### Module Constants
30
+ ######################
31
+
32
+
33
+ ######################
34
+ ### Module Variables
35
+ ######################
36
+
37
+ ######################
38
+ ### Module Methods
39
+ ######################
40
+
41
+
42
+ #####################################
43
+ ### Classes
44
+ #####################################
45
+
46
+ ###
47
+ ### A class implementing a JSS Policy.
48
+ ###
49
+ ### Like many API objects, the data comes from the API in sections, and
50
+ ### the items in the :general section are mapped to direct attributes
51
+ ### of this Class.
52
+ ###
53
+ ###
54
+ ### Policy instances are partially read-only:
55
+ ### - New policies cannot be created via this class, please use the WebApp.
56
+ ### - Only a few attributes can be changed and updated via the Policy class:
57
+ ### - - name
58
+ ### - - frequency
59
+ ### - - target_drive
60
+ ### - - offline
61
+ ### - - enabled
62
+ ### - - category
63
+ ### - - triggers
64
+ ### - - scope, see {JSS::Scopable} and {JSS::Scopable::Scope}
65
+ ### - - files and processes
66
+ ### All other values and sections must be edited via the Web App.
67
+ ###
68
+ ### Policies may be deleted via this class
69
+ ###
70
+ ### @see JSS::APIObject
71
+ ###
72
+ class Policy < JSS::APIObject
73
+
74
+ #####################################
75
+ ### Mix-Ins
76
+ #####################################
77
+
78
+ include JSS::Updatable
79
+ include JSS::Scopable
80
+ include JSS::Uploadable
81
+
82
+ #####################################
83
+ ### Class Methods
84
+ #####################################
85
+
86
+ #####################################
87
+ ### Class Constants
88
+ #####################################
89
+
90
+
91
+ ### The base for REST resources of this class
92
+ RSRC_BASE = "policies"
93
+
94
+ ### the hash key used for the JSON list output of all objects in the JSS
95
+ RSRC_LIST_KEY = :policies
96
+
97
+ ### The hash key used for the JSON object output.
98
+ ### It's also used in various error messages
99
+ RSRC_OBJECT_KEY = :policy
100
+
101
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
102
+ VALID_DATA_KEYS = [:scope, :user_interaction, :files_processes ]
103
+
104
+
105
+ SECTIONS = [
106
+ :general,
107
+ :maintenance,
108
+ :account_maintenance,
109
+ :scripts,
110
+ :self_service,
111
+ :package_configuration,
112
+ :scope,
113
+ :user_interaction,
114
+ :reboot,
115
+ :files_processes,
116
+ :dock_items,
117
+ :disk_encryption,
118
+ :printers
119
+ ]
120
+
121
+ FREQUENCIES = {
122
+ :ongoing => "Ongoing",
123
+ :once_per_computer => "Once per computer",
124
+ :once_per_user =>"Once per user",
125
+ :daily => "Once every day",
126
+ :weekly => "Once every week",
127
+ :monthly => "Once every month"
128
+ }
129
+
130
+ RESTART_WHEN = {
131
+ :if_pkg_requires => "Restart if a package or update requires it",
132
+ :now => "Restart immediately",
133
+ :delayed => "Restart",
134
+ :dont => "Do not restart"
135
+ }
136
+
137
+ RESTART_DISKS = {
138
+ :current => "Current Startup Disk",
139
+ :selected => "Currently Selected Startup Disk (No Bless)",
140
+ :netboot => "NetBoot",
141
+ :os_installer => "inPlaceOSUpgradeDirectory"
142
+ } # Note: any other value in :specify_startup is a path to some other drive to boot from, e.g. /Volumes/Foo
143
+
144
+ ACCOUNT_ACTIONS = {
145
+ :create => "Create",
146
+ :change_pw => "Reset",
147
+ :delete => "Delete",
148
+ :disable_fv2 => "DisableFileVault"
149
+ }
150
+
151
+ MGMT_ACCOUNT_ACTIONS = {
152
+ :no_change => "doNotChange",
153
+ :change_pw => "specified",
154
+ :generate_pw => "random",
155
+ :enable_fv2 => "fileVaultEnable",
156
+ :disable_fv2 => "fileVaultDisable"
157
+ }
158
+
159
+ PACKAGE_ACTIONS = {
160
+ :install => "Install",
161
+ :remove => "Uninstall",
162
+ :cache =>"Cache",
163
+ :install_cache => "Install Cached"
164
+ }
165
+
166
+ SCRIPT_PRIORITIES = {:pre => "Before", :post => "After"}
167
+
168
+ PRINTER_ACTIIONS = {:map => "install", :unmap => "uninstall"}
169
+
170
+ DOCK_ITEM_ACTIONS = {:add_start => "Add To Beginning", :add_end => "Add To End", :remove => "Remove"}
171
+
172
+ NETWORK_REQUIREMENTS = {:any => "Any", :ethernet => "EtherNet"}
173
+
174
+ TRIGGER_EVENTS = {
175
+ :startup => :trigger_startup,
176
+ :login => :trigger_login,
177
+ :logout => :trigger_logout,
178
+ :checkin => :trigger_checkin,
179
+ :network_state => :trigger_network_state_changed ,
180
+ :enrollment => :trigger_enrollment_complete ,
181
+ :custom => :trigger_other
182
+ }
183
+
184
+ TRIGGER_TYPES = {:event => "EVENT", :user => "USER_INITIATED"}
185
+
186
+ SCOPE_TARGET_KEY = :computers
187
+
188
+ ######################
189
+ ### Attributes
190
+ ######################
191
+
192
+ ##### General
193
+ ### This data comes from the :general hash in the raw JSON data
194
+ ### and correspond to the general section of the Edit Policy window in
195
+ ### the JSS WebApp. They are general settings for this policy.
196
+ ### We'll map it to direct attributes.
197
+
198
+ ### @return [String] policy category name
199
+ attr_reader :category
200
+
201
+ ### @return [String] how often to run the policy on each computer
202
+ attr_reader :frequency
203
+
204
+ ### @return [String] which drive should the policy target
205
+ attr_reader :target_drive
206
+
207
+ ### @return [Boolean] should be policy be available offline
208
+ attr_reader :offline
209
+
210
+ ### @return [Boolean] is the policy enabled?
211
+ attr_reader :enabled
212
+
213
+ ### @return [String] a string with the site name
214
+ attr_reader :site
215
+
216
+
217
+ ### @return [Hash]
218
+ ###
219
+ ### Overrides for various defaults
220
+ ###
221
+ ### The hash looks like: !{ :distribution_point => "", :force_afp_smb => false, :netboot_server => "current", :target_drive => "default", :sus => "default"}
222
+ attr_reader :override_default_settings
223
+
224
+ ### The API has a :network_requirements key in the general section, but
225
+ ### in the UI its in a subsection called Client Side Limitiations.
226
+ ### so we'll store it in a hash called client_side_limitations,
227
+ ### defined below.
228
+
229
+ ### the network_limitations hash of the general section seems to be redundant.
230
+ ### it contains minimum_network_connection ("Ethernet" or "No Minimum")
231
+ ### which is also reflected in the general[:network_requirements] ("Ethernet" or "Any")
232
+ ### it contains network_segments, which are also listed
233
+ ### in the limitations hash of the scope section
234
+ ### it contains any_ip_address, which is true or false based on there being
235
+ ### any network_segment limitations.
236
+ ### Therefore, we'll ignore it, and use the other places for that data
237
+
238
+ ### The API has a general key ":date_time_limitations" which has this
239
+ ### this data:
240
+ ### :activation - Time
241
+ ### :expiration - Time
242
+ ### :no_execute_on - An array of short day names as symbols, e.g. [:sun, :mon, :wed, :thu]
243
+ ### :no_execute_start - Time
244
+ ### :no_execute_end - Time
245
+ ### but in the UI, those are set in the Server Side Limitiations and Client Side Limitiations.
246
+ ### areas, so we'll store them in matching hashes below.
247
+ ### attr_reader :date_time_limitations
248
+
249
+ ### @return [Hash]
250
+ ###
251
+ ### The server-side limitations of this policy.
252
+ ###
253
+ ### The keys are :activation and :expiration, both are Times.
254
+ ###
255
+ ### the data comes from the API in the date_time_limitations hash of the general
256
+ ### section, but the UI shows them in the Server Side Limitations area.
257
+ ### This attribute is just for convience and consistency, and just
258
+ ### refers to the data in their API locations
259
+ attr_reader :server_side_limitations
260
+
261
+ ### @return [Hash]
262
+ ###
263
+ ### The client-side limitations of this policy.
264
+ ###
265
+ ### The keys are:
266
+ ### - :no_execute_on - An array of short day names as strings, e.g. ["Sun", "Mon", "Tue"]
267
+ ### - :no_execute_start - Time
268
+ ### - :no_execute_end - Time
269
+ ### - :network_connection - String
270
+ ### The data for the first three comes from the API in the date_time_limitations
271
+ ### hash of the general section.
272
+ ### The fourth comes from the network_requirements of the general section of the API,
273
+ ### but the UI shows them in the Client Side Limitations area.
274
+ ###
275
+ ### This attribute is just for convience and consistency, and just
276
+ ### refers to the data in their API locations
277
+ attr_reader :client_side_limitations
278
+
279
+ ### @return [String]
280
+ ###
281
+ ### Either EVENT or USER_INITIATED
282
+ ###
283
+ ### If it's EVENT, then one or more of the members @trigger_events must true.
284
+ attr_reader :trigger
285
+
286
+ ### @return [Hash]
287
+ ###
288
+ ### The triggers that cause this policy to execute on a client when the @trigger is "EVENT"
289
+ ###
290
+ ### This is a hash with the following keys. Each comes from the API
291
+ ### as a key in the :general hash, but they make more sense separated out
292
+ ### like this.
293
+ ### - :trigger_startup => Bool
294
+ ### - :trigger_login => Bool
295
+ ### - :trigger_logout => Bool
296
+ ### - :trigger_checkin => Bool
297
+ ### - :trigger_network_state_changed => Bool
298
+ ### - :trigger_enrollment_complete => Bool
299
+ ### - :trigger_other => the String that causes a custom trigger
300
+ ###
301
+ ### To edit a value, call
302
+ ### set_trigger_event(type, new_val)
303
+ ### where type is one of the keys in TRIGGER_EVENTS and new val is the new value (usually boolean)
304
+ ###
305
+ attr_reader :trigger_events
306
+
307
+ ##### client machine maintenence
308
+ ### These are the computer maint. tasks
309
+ ### that might be performed by this policy
310
+ ### All are boolean
311
+
312
+ ### @return [Boolean] client maintenance task
313
+ attr_reader :verify_startup_disk
314
+
315
+ ### @return [Boolean] client maintenance task
316
+ attr_reader :permissions_repair
317
+
318
+ ### @return [Boolean] client maintenance task
319
+ attr_reader :recon
320
+
321
+ ### @return [Boolean] client maintenance task
322
+ attr_reader :fix_byhost
323
+
324
+ ### @return [Boolean] client maintenance task
325
+ attr_reader :reset_name
326
+
327
+ ### @return [Boolean] client maintenance task
328
+ attr_reader :flush_system_cache
329
+
330
+ ### @return [Boolean] client maintenance task
331
+ attr_reader :install_cached_pkgs
332
+
333
+ ### @return [Boolean] client maintenance task
334
+ attr_reader :flush_user_cache
335
+
336
+ ### attr_reader :heal # deprecated
337
+ ### attr_reader :prebinding # deprecated
338
+
339
+ ##### client account maint
340
+ ### acct related maintenence performed by this policy
341
+
342
+ ### @return [Array<Hash>]
343
+ ###
344
+ ### The directory bindings applied
345
+ ###
346
+ ### each hash is like: !{:name => "LDAP", :id => 4}
347
+ attr_reader :directory_bindings
348
+
349
+
350
+ ### @return [Hash] the open firmware mode and password
351
+ attr_reader :open_firmware_efi_password
352
+
353
+ ### @return [Hash]
354
+ ###
355
+ ### The management accout changes applied by the policy
356
+ ###
357
+ ### The keys are:
358
+ ### - :action see MGMT_ACCOUNT_ACTIONS
359
+ ### - :managed_password
360
+ ### - :managed_password_md5
361
+ ### - :managed_password_sha256
362
+ ### - :managed_password_length # for random generating pws
363
+ ###
364
+ attr_reader :management_account
365
+
366
+ ### @return [Array<Hash>]
367
+ ###
368
+ ### Local accts acted-upon by this policy
369
+ ###
370
+ ### Keys are:
371
+ ### - :action => "Create",
372
+ ### - :hint => "foo bar",
373
+ ### - :picture => "/path/to/pic.tif",
374
+ ### - :admin => true,
375
+ ### - :home => "/Users/chrisltest",
376
+ ### - :realname => "ChrisTest Lasell",
377
+ ### - :filevault_enabled => true,
378
+ ### - :username => "chrisltest",
379
+ ### - :password_md5 => "3858f62230ac3c915f300c664312c63f",
380
+ ### - : password => "foobar",
381
+ ### - :password_sha256=> "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"
382
+ ###
383
+ attr_reader :accounts
384
+
385
+ ### @return [Array<Hash>]
386
+ ###
387
+ ### The pkgs handled by this policy
388
+ ###
389
+ ### Hash keys are:
390
+ ### - :action => "Install"
391
+ ### - :update_autorun => false,
392
+ ### - :feu => false,
393
+ ### - :name => "rbgem-json-1.6.5-4.pkg",
394
+ ### - :id => 1073
395
+ ###
396
+ attr_reader :packages
397
+
398
+ ### @return [Array<Hash>]
399
+ ###
400
+ ### The scripts run by this policy
401
+ ###
402
+ ### Hash keys are:
403
+ ### - :name => "chromegetter.sh",
404
+ ### - :parameter4 => "",
405
+ ### - :parameter5 => "",
406
+ ### - :parameter6 => "",
407
+ ### - :parameter7 => "",
408
+ ### - :parameter8 => "",
409
+ ### - :parameter9 => "",
410
+ ### - :parameter10 => "",
411
+ ### - :parameter11 => "",
412
+ ### - :id => 1428,
413
+ ### - :priority => "After"
414
+ ###
415
+ attr_reader :scripts
416
+
417
+
418
+ ### @return [Hash]
419
+ ###
420
+ ### Self-service-related data for this policy
421
+ ###
422
+ ### The hash keys are:
423
+ ### - :self_service_icon => !{:uri => String,:id => Integer, :filename => String}
424
+ ### - :use_for_self_service => true,
425
+ ### - :install_button_text => "Install",
426
+ ### - :self_service_description => "Descriptive text",
427
+ ### - :force_users_to_view_description => false
428
+ ###
429
+ ### Note: we'll add a ruby-std convenience method below "self_service?"
430
+ ### which returns the :use_for_self_service key.
431
+ attr_reader :self_service
432
+
433
+ #### user interaction
434
+ ### These are extracted from the :user_interaction hash
435
+ ### in the JSON output, which looks like this:
436
+ ### :message_start => "",
437
+ ### :allow_users_to_defer => false,
438
+ ### :allow_deferral_until_utc => "",
439
+ ### :message_finish => ""
440
+ ###
441
+
442
+ ### @return [Boolean] can the user defer the policy?
443
+ attr_reader :user_may_defer
444
+
445
+ ### @return [Time] when is the user no longer allowed to defer?
446
+ attr_reader :user_may_defer_until
447
+
448
+ ### @return [String] the message shown the user at policy start
449
+ attr_reader :user_message_start
450
+
451
+ ### @return [String] the message shown the user at policy end
452
+ attr_reader :user_message_finish
453
+
454
+ ### @return [Hash]
455
+ ###
456
+ ### Reboot options for the policy
457
+ ###
458
+ ### The hash keys are:
459
+ ### - :user_logged_in => "Do not restart",
460
+ ### - :minutes_until_reboot => 5,
461
+ ### - :message=> "This computer will restart in 5 minutes. Please save anything you are working on and log out by choosing Log Out from the bottom of the Apple menu.",
462
+ ### - :startup_disk => "Current Startup Disk",
463
+ ### - :specify_startup => "",
464
+ ### - :no_user_logged_in => "Do not restart"
465
+ ###
466
+ attr_reader :reboot_options
467
+
468
+ ##### files & processes
469
+ ### a hash like this:
470
+ ### {:spotlight_search => "Spotlight This",
471
+ ### :search_for_process => "SafariProcess",
472
+ ### :search_by_path => "/this/is/a/path",
473
+ ### :kill_process => true,
474
+ ### :delete_file => true,
475
+ ### :run_command => "/usr/local/pixar/sbin/force-fde-logout --setup",
476
+ ### :locate_file => "this-is-a-filename",
477
+ ### :update_locate_database => true}
478
+ ###
479
+ ### NOTE, since these items are editable, they have custom getters/setters
480
+ ### so that the hash isn't directly changable without @need_to_update.
481
+ ### attr_reader :files_processes
482
+
483
+
484
+ ### @return [Array<Hash>]
485
+ ###
486
+ ### The dock items handled by this policy
487
+ ###
488
+ ### each item hash looks like: !{:name => "Mail", :id => 14, :action => "Add To Beginning"}
489
+ attr_reader :dock_items
490
+
491
+ ### @return [Hash]
492
+ ###
493
+ ### Disk encryption options for this policy
494
+ ###
495
+ ### The hash looks like !{:disk_encryption_configuration_id => 3, :action => "apply"}
496
+ attr_reader :disk_encryption
497
+
498
+ ### @return [Array<Hash>]
499
+ ###
500
+ ### The printers handled by this policy
501
+ ###
502
+ ### Each Hash looks like: !{:make_default => false, :name => "torlan", :id => 3, :action => "install"}
503
+ attr_reader :printers
504
+
505
+ #####################################
506
+ ### Public Instance Methods
507
+ #####################################
508
+
509
+ ###
510
+ ### @see APIObject#initialize
511
+ ###
512
+ def initialize(args = {})
513
+
514
+ super
515
+
516
+
517
+ gen = @init_data[:general]
518
+ @category = JSS::APIObject.get_name(gen[:category])
519
+ @frequency = gen[:frequency]
520
+ @target_drive = gen[:target_drive]
521
+ @offline = gen[:offline]
522
+ @enabled = gen[:enabled]
523
+ @site = JSS::APIObject.get_name(gen[:site][:name])
524
+ @override_default_settings = gen[:override_default_settings]
525
+ @trigger = gen[:trigger ]
526
+ @trigger_events = {
527
+ :trigger_startup => gen[:trigger_startup ],
528
+ :trigger_login => gen[:trigger_login ],
529
+ :trigger_logout => gen[:trigger_logout ],
530
+ :trigger_checkin => gen[:trigger_checkin ],
531
+ :trigger_network_state_changed => gen[:trigger_network_state_changed ],
532
+ :trigger_enrollment_complete => gen[:trigger_enrollment_complete ],
533
+ :trigger_other => gen[:trigger_other ]
534
+ }
535
+
536
+ dtl = gen[:date_time_limitations]
537
+
538
+ @server_side_limitations = {
539
+ :activation => JSS.epoch_to_time(dtl[:activation_date_epoch]),
540
+ :expiration => JSS.epoch_to_time(dtl[:expiration_date_epoch])
541
+ }
542
+
543
+ @client_side_limitations = {
544
+ :no_execute_on => dtl[:no_execute_on], # NOTE- there's a bug in the JSON output, it's been reported to JAMF.
545
+ :no_execute_start => dtl[:no_execute_start], # String like "1:01 AM"
546
+ :no_execute_end => dtl[:no_execute_end], # String like "2:02 PM"
547
+ :network_requirements => gen[:network_requirements]
548
+ }
549
+
550
+ maint = @init_data[:maintenance]
551
+ @verify_startup_disk = maint[:verify]
552
+ @permissions_repair = maint[:permissions]
553
+ @recon = maint[:recon]
554
+ @fix_byhost = maint[:byhost]
555
+ @reset_name = maint[:reset_name]
556
+ @flush_system_cache = maint[:system_cache]
557
+ @install_cached_pkgs = maint[:install_all_cached_packages]
558
+ @flush_user_cache = maint[:user_cache]
559
+
560
+ amaint = @init_data[:account_maintenance]
561
+ @directory_bindings = amaint[:directory_bindings]
562
+ @open_firmware_efi_password = amaint[:open_firmware_efi_password]
563
+ @management_account = amaint[:management_account]
564
+ @accounts = amaint[:accounts]
565
+
566
+ @packages = @init_data[:package_configuration][:packages] ? @init_data[:package_configuration][:packages] : []
567
+
568
+ @scripts = @init_data[:scripts]
569
+
570
+ @self_service = @init_data[:self_service]
571
+
572
+ uint = @init_data[:user_interaction]
573
+ @user_may_defer = uint[:allow_users_to_defer]
574
+ @user_may_defer_until = JSS.parse_datetime uint[:allow_deferral_until_utc]
575
+ @user_message_start = uint[:message_start]
576
+ @user_message_finish = uint[:message_finish]
577
+
578
+ @reboot_options = @init_data[:reboot]
579
+
580
+ @files_processes = @init_data[:files_processes]
581
+
582
+ @dock_items = @init_data[:dock_items]
583
+
584
+ @disk_encryption = @init_data[:disk_encryption]
585
+
586
+ @printers = @init_data[:printers]
587
+
588
+ parse_scope
589
+
590
+ end # init
591
+
592
+ ###
593
+ ### Change the enabled state of this item
594
+ ###
595
+ ### @param new_val[Boolean] the new state.
596
+ ###
597
+ ### @return [void]
598
+ ###
599
+ def enabled= (new_val)
600
+ return nil if @enabled == new_val
601
+ raise JSS::InvalidDataError, "New value must be true or false" unless JSS::TRUE_FALSE.include? new_val
602
+ @enabled = new_val
603
+ @need_to_update = true
604
+ end
605
+
606
+ ###
607
+ ### Set a new frequency for this policy.
608
+ ###
609
+ ### @param freq[Symbol] the desired frequency, must be one of the keys of {FREQUENCIES}
610
+ ###
611
+ ### @return [void]
612
+ ###
613
+ def frequency= (freq)
614
+ raise JSS::InvalidDataError, "New frequency must be one of :#{FREQUENCIES.keys.join ", :"}" unless FREQUENCIES.keys.include? freq
615
+ @frequency = FREQUENCIES[freq]
616
+ @need_to_update = true
617
+ end
618
+
619
+ ###
620
+ ### Set a new target drive for this policy.
621
+ ###
622
+ ### @param path_to_drive[String,Pathname] the full path to the target drive, must start with a '/'
623
+ ###
624
+ ### @return [void]
625
+ ###
626
+ def target_drive= (path_to_drive)
627
+ raise JSS::InvalidDataError, "Path to target drive must be absolute" unless path_to_drive.to_s.start_with? '/'
628
+ @target_drive = path_to_drive.to_s
629
+ @need_to_update = true
630
+ end
631
+
632
+ ###
633
+ ### Set whether this policy is available offline.
634
+ ###
635
+ ### @param new_val[Boolean]
636
+ ###
637
+ ### @return [void]
638
+ ###
639
+ def offline= (new_val)
640
+ raise JSS::InvalidDataError, "New value must be boolean true or false" unless JSS::TRUE_FALSE.include? new_val
641
+ @offline = new_val
642
+ @need_to_update = true
643
+ end
644
+
645
+ ###
646
+ ### Change the category of this item, arg is a category name
647
+ ###
648
+ ### @param new_val[String] the name of the new category
649
+ ###
650
+ ### @return [void]
651
+ ###
652
+ def category= (new_val = JSS::Category::DEFAULT_CATEGORY)
653
+ return nil if @category == new_val
654
+ new_val = nil if new_val == ''
655
+ new_val ||= JSS::Category::DEFAULT_CATEGORY
656
+ raise JSS::NoSuchItemError, "No category '#{new_val}' in the JSS" unless JSS::Category.all_names(:refresh).include? new_val
657
+ @category = new_val
658
+ @need_to_update = true
659
+ end
660
+
661
+ ###
662
+ ### Change a trigger event
663
+ ###
664
+ ### @param type[Symbol] the type of trigger, one of the keys of {TRIGGER_EVENTS}
665
+ ###
666
+ ### @param new_val[Boolean] whether the type of trigger is active or not.
667
+ ###
668
+ ### @return [void]
669
+ ###
670
+ def set_trigger_event (type, new_val)
671
+ raise JSS::InvalidDataError, "Trigger type must be one of #{TRIGGER_EVENTS.keys.join(', ')}" unless TRIGGER_EVENTS.keys.include? type
672
+ if type == :custom
673
+ raise JSS::InvalidDataError, "Custom triggers must be Strings" unless new_val.kind_of? String
674
+ else
675
+ raise JSS::InvalidDataError, "Non-custom triggers must be true or false" unless JSS::TRUE_FALSE.include? new_val
676
+ end
677
+ @trigger_events[TRIGGER_EVENTS[type]] = new_val
678
+ @need_to_update = true
679
+ end
680
+
681
+ ###
682
+ ### @return [String] The unix shell command to run on ths client.
683
+ ###
684
+ def run_command ; @files_processes[:run_command] ; end
685
+
686
+ ###
687
+ ### Set the unix shell command to be run on the client
688
+ ###
689
+ ### @param command[String] the unix shell command to be run on the client
690
+ ###
691
+ ### @return [void]
692
+ ###
693
+ def run_command= (command)
694
+ raise JSS::InvalidDataError, "Command to run must be a String" unless command.is_a? String
695
+ @files_processes[:run_command] = command
696
+ @need_to_update = true
697
+ end
698
+
699
+ ###
700
+ ### @return [Boolean] Should we update the database used by the locate command?
701
+ ###
702
+ def update_locate_database? ; @files_processes[:update_locate_database] ; end
703
+
704
+ ###
705
+ ### Set whether or not to update the database used by the locate command.
706
+ ###
707
+ ### @param tf[Boolean] whether or not to update the database used by the locate command.
708
+ ###
709
+ ### @return [void]
710
+ ###
711
+ def update_locate_database= (tf)
712
+ @files_processes[:update_locate_database] = tf ? true : false
713
+ @need_to_update = true
714
+ end
715
+
716
+ ###
717
+ ### @return [String] The process name to search for on the client
718
+ ###
719
+ def search_for_process
720
+ @files_processes[:search_for_process]
721
+ end
722
+
723
+ ###
724
+ ### @return [Boolean] Should the searched-for process be killed if found.
725
+ ###
726
+ def kill_process?
727
+ @files_processes[:kill_process]
728
+ end
729
+
730
+ ###
731
+ ### Set the process name to search for, and if it should be killed if found.
732
+ ###
733
+ ### Setter methods (which end with =) can't easily take
734
+ ### multiple arguments, so we instead name them "set_blah_blah"
735
+ ### rather than "blah_blah="
736
+ ###
737
+ ### @param process[String] the process name to search for
738
+ ###
739
+ ### @param kill[Boolean] should be process be killed if found
740
+ ###
741
+ ### @return [void]
742
+ ###
743
+ def set_search_for_process (process, kill = false)
744
+ @files_processes[:search_for_process] = process.to_s
745
+ @files_processes[:kill_process] = kill ? true : false
746
+ @need_to_update = true
747
+ end
748
+
749
+ ###
750
+ ### @return [Pathname] The path to search for
751
+ ###
752
+ def search_by_path ; Pathname.new @files_processes[:search_by_path] ; end
753
+
754
+ ###
755
+ ### @return [Boolean] Should the searched-for path be deleted if found?
756
+ ###
757
+ def delete_file? ; @files_processes[:delete_file] ; end
758
+
759
+ ###
760
+ ### Set the path to search for, a String or Pathname, and whether or not to delete it if found.
761
+ ###
762
+ ### Setter methods (which end with =) can't easily take
763
+ ### multiple arguments, so we instead name them "set_blah_blah"
764
+ ### rather than "blah_blah="
765
+ ###
766
+ ### @param path[String,Pathname] the path to search for
767
+ ###
768
+ ### @param delete[Boolean] should the path be deleted if found
769
+ ###
770
+ ### @return [void]
771
+ ###
772
+ def set_search_by_path (path, delete = false)
773
+ raise JSS::InvalidDataError, "Path to search for must be a String or a Pathname" unless path.is_a? String or path.is_a? Pathname
774
+ @files_processes[:search_by_path] = path.to_s
775
+ @files_processes[:delete_file] = delete ? true : false
776
+ @need_to_update = true
777
+ end
778
+
779
+ ###
780
+ ### @return [String] The term to search for using spotlight
781
+ ###
782
+ def spotlight_search ; @files_processes[:spotlight_search] ; end
783
+
784
+ ### Set the term to seach for using spotlight
785
+ ###
786
+ ### @param term[String] the term to seach for using spotlight
787
+ ###
788
+ ### @return [void]
789
+ ###
790
+ def spotlight_search= (term)
791
+ raise JSS::InvalidDataError, "Spotlight search term must be a String" unless term.is_a? String
792
+ @files_processes[:spotlight_search] = term
793
+ @need_to_update = true
794
+ end
795
+
796
+ ###
797
+ ### @return [String] The term to seach for using the locate command
798
+ ###
799
+ def locate_file ; @files_processes[:locate_file] ; end
800
+
801
+ ### Set the term to seach for using the locate command
802
+ ###
803
+ ### @param term[String] the term to seach for using the locate command
804
+ ###
805
+ ### @return [void]
806
+ ###
807
+ def locate_file= (term)
808
+ raise JSS::InvalidDataError, "Term to locate must be a String" unless term.is_a? String
809
+ @files_processes[:locate_file] = term
810
+ @need_to_update = true
811
+ end
812
+
813
+ ### @return [Array] the id's of the packages handled by the policy
814
+ def package_ids; @packages.map{|p| p[:id]} ; end
815
+
816
+ ### @return [Array] the names of the packages handled by the policy
817
+ def package_names; @packages.map{|p| p[:name]} ; end
818
+
819
+ ### @return [Array] the id's of the scripts handled by the policy
820
+ def script_ids; @scripts.map{|p| p[:id]} ; end
821
+
822
+ ### @return [Array] the names of the scripts handled by the policy
823
+ def script_names; @scripts.map{|p| p[:name]} ; end
824
+
825
+ ### @return [Array] the id's of the directory_bindings handled by the policy
826
+ def directory_binding_ids; @directory_bindings.map{|p| p[:id]} ; end
827
+
828
+ ### @return [Array] the names of the directory_bindings handled by the policy
829
+ def directory_binding_names; @directory_bindings.map{|p| p[:name]} ; end
830
+
831
+ ### @return [Array] the id's of the dock_items handled by the policy
832
+ def dock_item_ids; @dock_items.map{|p| p[:id]} ; end
833
+
834
+ ### @return [Array] the names of the dock_items handled by the policy
835
+ def dock_item_names; @dock_items.map{|p| p[:name]} ; end
836
+
837
+ ### @return [Array] the id's of the printers handled by the policy
838
+ def printer_ids; @printers.map{|p| p[:id]} ; end
839
+
840
+ ### @return [Array] the names of the printers handled by the policy
841
+ def printer_names; @printers.map{|p| p[:name]} ; end
842
+
843
+ ### @return [Boolean] is this policy available in SelfService?
844
+ def self_service?; @self_service[:use_for_self_service] ; end
845
+
846
+ ### Try to execute this policy on this machine.
847
+ ###
848
+ ### @param show_output[Boolean] should the stdout and stderr of the
849
+ ### 'jamf policy' command be sent to stdout in realtime?
850
+ ###
851
+ ### @return [Boolean, nil] The success of the 'jamf policy' command, or nil
852
+ ### if the policy couldn't be executed (out of scope, policy disabled, etc)
853
+ ###
854
+ def run (show_output = false)
855
+ return nil unless enabled?
856
+ output = JSS::Client.run_jamf("policy", "-id #{id}", show_output)
857
+ return nil if output.include? 'No policies were found for the ID'
858
+ return $?.exitstatus == 0 ? true : false
859
+ end
860
+
861
+ ### Aliases
862
+ alias enabled? enabled
863
+ alias pkgs packages
864
+ alias command_to_run run_command
865
+ alias delete_path? delete_file?
866
+ alias execute run
867
+
868
+ #####################################
869
+ ### Private Instance Methods
870
+ #####################################
871
+ private
872
+
873
+ def rest_xml
874
+ doc = REXML::Document.new APIConnection::XML_HEADER
875
+ obj = doc.add_element RSRC_OBJECT_KEY.to_s
876
+
877
+ general = obj.add_element "general"
878
+ general.add_element('name').text = @name
879
+ general.add_element('enabled').text = @enabled
880
+ general.add_element('frequency').text = @frequency
881
+ general.add_element('target_drive').text = @target_drive
882
+ general.add_element('offline').text = @offline
883
+ general.add_element('category').add_element('name').text = @category
884
+
885
+ JSS.hash_to_rexml_array(@trigger_events).each{|t| general << t}
886
+
887
+ obj << @scope.scope_xml
888
+
889
+ files_processes = obj.add_element "files_processes"
890
+ JSS.hash_to_rexml_array(@files_processes).each{|f| files_processes << f}
891
+
892
+ return doc.to_s
893
+ end
894
+
895
+ end # class policy
896
+
897
+ end # module
898
+