ruby-jss 1.2.4a4 → 1.3.3

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 (248) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +185 -1
  3. data/README.md +3 -1
  4. data/bin/cgrouper +1 -1
  5. data/bin/jamfHelperBackgrounder +1 -1
  6. data/bin/netseg-update +1 -1
  7. data/data/ruby-jss.conf.example +1 -1
  8. data/lib/jamf.rb +1 -1
  9. data/lib/jamf/api/abstract_classes/advanced_search.rb +1 -1
  10. data/lib/jamf/api/abstract_classes/collection_resource.rb +31 -26
  11. data/lib/jamf/api/abstract_classes/generic_reference.rb +1 -1
  12. data/lib/jamf/api/abstract_classes/json_object.rb +15 -5
  13. data/lib/jamf/api/abstract_classes/prestage.rb +2 -2
  14. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +1 -1
  15. data/lib/jamf/api/abstract_classes/resource.rb +1 -1
  16. data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
  17. data/lib/jamf/api/attribute_classes/ip_address.rb +1 -1
  18. data/lib/jamf/api/attribute_classes/timestamp.rb +1 -1
  19. data/lib/jamf/api/connection.rb +106 -60
  20. data/lib/jamf/api/connection/api_error.rb +1 -1
  21. data/lib/jamf/api/connection/api_error_styleguide.rb +1 -1
  22. data/lib/jamf/api/connection/token.rb +80 -13
  23. data/lib/jamf/api/json_objects/account_prefs.rb +1 -1
  24. data/lib/jamf/api/json_objects/android_details.rb +1 -1
  25. data/lib/jamf/api/json_objects/appletv_details.rb +1 -1
  26. data/lib/jamf/api/json_objects/attachment.rb +1 -1
  27. data/lib/jamf/api/json_objects/cellular_network.rb +1 -1
  28. data/lib/jamf/api/json_objects/change_log_entry.rb +1 -1
  29. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +1 -1
  30. data/lib/jamf/api/json_objects/country.rb +1 -1
  31. data/lib/jamf/api/json_objects/criterion.rb +1 -1
  32. data/lib/jamf/api/json_objects/device_enrollment_device.rb +1 -1
  33. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  34. data/lib/jamf/api/json_objects/extension_attribute_value.rb +1 -1
  35. data/lib/jamf/api/json_objects/installed_application.rb +1 -1
  36. data/lib/jamf/api/json_objects/installed_certificate.rb +1 -1
  37. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +1 -1
  38. data/lib/jamf/api/json_objects/installed_ebook.rb +1 -1
  39. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +1 -1
  40. data/lib/jamf/api/json_objects/inventory_preload_extension_attribute.rb +1 -1
  41. data/lib/jamf/api/json_objects/ios_details.rb +1 -1
  42. data/lib/jamf/api/json_objects/location.rb +1 -1
  43. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  44. data/lib/jamf/api/json_objects/md_prestage_names.rb +1 -1
  45. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +1 -1
  46. data/lib/jamf/api/json_objects/mobile_device_details.rb +1 -1
  47. data/lib/jamf/api/json_objects/mobile_device_security.rb +1 -1
  48. data/lib/jamf/api/json_objects/prestage_assignment.rb +1 -1
  49. data/lib/jamf/api/json_objects/prestage_location.rb +1 -1
  50. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +1 -1
  51. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  52. data/lib/jamf/api/json_objects/prestage_sync_status.rb +1 -1
  53. data/lib/jamf/api/json_objects/purchasing_data.rb +1 -1
  54. data/lib/jamf/api/mixins/abstract.rb +1 -1
  55. data/lib/jamf/api/mixins/bulk_deletable.rb +1 -1
  56. data/lib/jamf/api/mixins/change_log.rb +1 -1
  57. data/lib/jamf/api/mixins/extendable.rb +1 -1
  58. data/lib/jamf/api/mixins/immutable.rb +1 -1
  59. data/lib/jamf/api/mixins/locatable.rb +1 -1
  60. data/lib/jamf/api/mixins/lockable.rb +1 -1
  61. data/lib/jamf/api/mixins/referable.rb +1 -1
  62. data/lib/jamf/api/mixins/searchable.rb +1 -1
  63. data/lib/jamf/api/mixins/uncreatable.rb +1 -1
  64. data/lib/jamf/api/mixins/undeletable.rb +1 -1
  65. data/lib/jamf/api/resources/collection_resources/account.rb +1 -1
  66. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +1 -1
  67. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +1 -1
  68. data/lib/jamf/api/resources/collection_resources/building.rb +1 -1
  69. data/lib/jamf/api/resources/collection_resources/category.rb +1 -1
  70. data/lib/jamf/api/resources/collection_resources/computer.rb +1 -1
  71. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +1 -1
  72. data/lib/jamf/api/resources/collection_resources/department.rb +1 -1
  73. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +1 -1
  74. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +1 -1
  75. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +9 -2
  76. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +1 -1
  77. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +1 -1
  78. data/lib/jamf/api/resources/collection_resources/script.rb +1 -1
  79. data/lib/jamf/api/resources/collection_resources/site.rb +1 -1
  80. data/lib/jamf/api/resources/collection_resources/time_zone.rb +1 -1
  81. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +1 -1
  82. data/lib/jamf/api/resources/singleton_resources/authorization.rb +1 -1
  83. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +1 -1
  84. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +1 -1
  85. data/lib/jamf/client.rb +1 -1
  86. data/lib/jamf/client/jamf_binary.rb +1 -1
  87. data/lib/jamf/client/jamf_helper.rb +1 -1
  88. data/lib/jamf/client/management_action.rb +1 -1
  89. data/lib/jamf/compatibility.rb +1 -1
  90. data/lib/jamf/composer.rb +1 -1
  91. data/lib/jamf/configuration.rb +8 -10
  92. data/lib/jamf/exceptions.rb +6 -1
  93. data/lib/jamf/ruby_extensions.rb +2 -1
  94. data/lib/jamf/ruby_extensions/array.rb +2 -2
  95. data/lib/jamf/ruby_extensions/array/predicates.rb +1 -1
  96. data/lib/jamf/ruby_extensions/array/utils.rb +4 -4
  97. data/lib/jamf/ruby_extensions/dig.rb +52 -0
  98. data/lib/jamf/ruby_extensions/filetest.rb +1 -1
  99. data/lib/jamf/ruby_extensions/filetest/predicates.rb +1 -1
  100. data/lib/jamf/ruby_extensions/hash.rb +1 -1
  101. data/lib/jamf/ruby_extensions/hash/backports.rb +2 -2
  102. data/lib/jamf/ruby_extensions/ipaddr.rb +1 -1
  103. data/lib/jamf/ruby_extensions/ipaddr/utils.rb +1 -1
  104. data/lib/jamf/ruby_extensions/object.rb +1 -1
  105. data/lib/jamf/ruby_extensions/object/predicates.rb +1 -1
  106. data/lib/jamf/ruby_extensions/pathname.rb +1 -1
  107. data/lib/jamf/ruby_extensions/pathname/predicates.rb +1 -1
  108. data/lib/jamf/ruby_extensions/pathname/utils.rb +1 -1
  109. data/lib/jamf/ruby_extensions/string.rb +1 -1
  110. data/lib/jamf/ruby_extensions/string/backports.rb +1 -1
  111. data/lib/jamf/ruby_extensions/string/conversions.rb +1 -1
  112. data/lib/jamf/ruby_extensions/string/predicates.rb +14 -4
  113. data/lib/jamf/utility.rb +1 -1
  114. data/lib/jamf/validate.rb +1 -1
  115. data/lib/jamf/version.rb +2 -2
  116. data/lib/jpapi.rb +1 -1
  117. data/lib/jss-api.rb +1 -1
  118. data/lib/jss.rb +5 -2
  119. data/lib/jss/api_connection.rb +3 -30
  120. data/lib/jss/api_object.rb +16 -3
  121. data/lib/jss/api_object/account.rb +1 -1
  122. data/lib/jss/api_object/advanced_search.rb +1 -1
  123. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +1 -1
  124. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +1 -1
  125. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +1 -1
  126. data/lib/jss/api_object/building.rb +1 -1
  127. data/lib/jss/api_object/categorizable.rb +1 -1
  128. data/lib/jss/api_object/category.rb +1 -1
  129. data/lib/jss/api_object/computer.rb +12 -6
  130. data/lib/jss/api_object/computer/application_installs.rb +1 -1
  131. data/lib/jss/api_object/computer_invitation.rb +1 -1
  132. data/lib/jss/api_object/configuration_profile.rb +4 -2
  133. data/lib/jss/api_object/configuration_profile/mobile_device_configuration_profile.rb +1 -1
  134. data/lib/jss/api_object/configuration_profile/osx_configuration_profile.rb +1 -1
  135. data/lib/jss/api_object/creatable.rb +1 -1
  136. data/lib/jss/api_object/criteriable.rb +10 -5
  137. data/lib/jss/api_object/criteriable/criteria.rb +26 -10
  138. data/lib/jss/api_object/criteriable/criterion.rb +1 -1
  139. data/lib/jss/api_object/department.rb +1 -1
  140. data/lib/jss/api_object/directory_binding.rb +273 -0
  141. data/lib/jss/api_object/directory_binding_type.rb +90 -0
  142. data/lib/jss/api_object/directory_binding_type/active_directory.rb +502 -0
  143. data/lib/jss/api_object/directory_binding_type/admitmac.rb +525 -0
  144. data/lib/jss/api_object/directory_binding_type/centrify.rb +212 -0
  145. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  146. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  147. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  148. data/lib/jss/api_object/distribution_point.rb +96 -36
  149. data/lib/jss/api_object/dock_item.rb +137 -0
  150. data/lib/jss/api_object/ebook.rb +1 -1
  151. data/lib/jss/api_object/extendable.rb +67 -28
  152. data/lib/jss/api_object/extension_attribute.rb +1 -1
  153. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
  154. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
  155. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +1 -1
  156. data/lib/jss/api_object/group.rb +1 -1
  157. data/lib/jss/api_object/group/computer_group.rb +1 -1
  158. data/lib/jss/api_object/group/mobile_device_group.rb +1 -1
  159. data/lib/jss/api_object/group/user_group.rb +1 -1
  160. data/lib/jss/api_object/ibeacon.rb +1 -1
  161. data/lib/jss/api_object/ldap_server.rb +1 -1
  162. data/lib/jss/api_object/locatable.rb +1 -1
  163. data/lib/jss/api_object/mac_application.rb +1 -1
  164. data/lib/jss/api_object/management_history.rb +23 -22
  165. data/lib/jss/api_object/management_history/audit_event.rb +1 -1
  166. data/lib/jss/api_object/management_history/casper_imaging_log.rb +1 -1
  167. data/lib/jss/api_object/management_history/casper_remote_log.rb +1 -1
  168. data/lib/jss/api_object/management_history/computer_usage_log.rb +1 -1
  169. data/lib/jss/api_object/management_history/ebook.rb +1 -1
  170. data/lib/jss/api_object/management_history/hashlike.rb +1 -1
  171. data/lib/jss/api_object/management_history/mac_app_store_app.rb +1 -1
  172. data/lib/jss/api_object/management_history/mdm_command.rb +1 -1
  173. data/lib/jss/api_object/management_history/mobile_device_app.rb +1 -1
  174. data/lib/jss/api_object/management_history/policy_log.rb +1 -1
  175. data/lib/jss/api_object/management_history/screen_sharing_log.rb +1 -1
  176. data/lib/jss/api_object/management_history/user_location_change.rb +1 -1
  177. data/lib/jss/api_object/matchable.rb +1 -1
  178. data/lib/jss/api_object/mdm.rb +1 -1
  179. data/lib/jss/api_object/mobile_device.rb +29 -6
  180. data/lib/jss/api_object/mobile_device_application.rb +13 -1
  181. data/lib/jss/api_object/netboot_server.rb +1 -1
  182. data/lib/jss/api_object/network_segment.rb +153 -59
  183. data/lib/jss/api_object/package.rb +106 -41
  184. data/lib/jss/api_object/patch_policy.rb +1 -1
  185. data/lib/jss/api_object/patch_source.rb +1 -1
  186. data/lib/jss/api_object/patch_source/patch_external_source.rb +1 -1
  187. data/lib/jss/api_object/patch_source/patch_internal_source.rb +1 -1
  188. data/lib/jss/api_object/patch_title.rb +1 -1
  189. data/lib/jss/api_object/patch_title/version.rb +1 -1
  190. data/lib/jss/api_object/peripheral.rb +1 -1
  191. data/lib/jss/api_object/peripheral_type.rb +1 -1
  192. data/lib/jss/api_object/policy.rb +380 -5
  193. data/lib/jss/api_object/printer.rb +440 -0
  194. data/lib/jss/api_object/purchasable.rb +1 -1
  195. data/lib/jss/api_object/removable_macaddr.rb +1 -1
  196. data/lib/jss/api_object/restricted_software.rb +1 -1
  197. data/lib/jss/api_object/scopable.rb +1 -1
  198. data/lib/jss/api_object/scopable/scope.rb +257 -37
  199. data/lib/jss/api_object/script.rb +1 -1
  200. data/lib/jss/api_object/self_servable.rb +7 -7
  201. data/lib/jss/api_object/self_servable/icon.rb +1 -1
  202. data/lib/jss/api_object/sitable.rb +6 -2
  203. data/lib/jss/api_object/site.rb +1 -1
  204. data/lib/jss/api_object/software_update_server.rb +1 -1
  205. data/lib/jss/api_object/updatable.rb +1 -1
  206. data/lib/jss/api_object/uploadable.rb +1 -1
  207. data/lib/jss/api_object/user.rb +5 -3
  208. data/lib/jss/api_object/vppable.rb +1 -1
  209. data/lib/jss/api_object/webhook.rb +1 -1
  210. data/lib/jss/client.rb +1 -1
  211. data/lib/jss/client/jamf_binary.rb +1 -1
  212. data/lib/jss/client/jamf_helper.rb +1 -1
  213. data/lib/jss/client/management_action.rb +1 -1
  214. data/lib/jss/compatibility.rb +1 -1
  215. data/lib/jss/composer.rb +2 -2
  216. data/lib/jss/configuration.rb +1 -1
  217. data/lib/jss/db_connection.rb +1 -1
  218. data/lib/jss/exceptions.rb +1 -1
  219. data/lib/jss/ruby_extensions.rb +1 -1
  220. data/lib/jss/ruby_extensions/array.rb +1 -1
  221. data/lib/jss/ruby_extensions/filetest.rb +1 -1
  222. data/lib/jss/ruby_extensions/hash.rb +1 -1
  223. data/lib/jss/ruby_extensions/ipaddr.rb +1 -1
  224. data/lib/jss/ruby_extensions/pathname.rb +1 -1
  225. data/lib/jss/ruby_extensions/string.rb +1 -1
  226. data/lib/jss/ruby_extensions/string/backports.rb +1 -1
  227. data/lib/jss/ruby_extensions/string/conversions.rb +1 -1
  228. data/lib/jss/ruby_extensions/string/predicates.rb +14 -4
  229. data/lib/jss/ruby_extensions/time.rb +1 -1
  230. data/lib/jss/server.rb +1 -1
  231. data/lib/jss/utility.rb +9 -23
  232. data/lib/jss/validate.rb +1 -1
  233. data/lib/jss/version.rb +2 -2
  234. data/lib/jss/xml_workaround.rb +1 -1
  235. data/lib/ruby-jss.rb +1 -1
  236. data/test/bin/runtests +1 -1
  237. data/test/lib/testhelper.rb +1 -1
  238. data/test/lib/testhelper/auth.rb +1 -1
  239. data/test/lib/testhelper/patch_mgmt.rb +1 -1
  240. data/test/specs/api_connection_spec.rb +1 -1
  241. data/test/specs/patch01_source_spec.rb +1 -1
  242. data/test/specs/patch02_internal_source_spec.rb +1 -1
  243. data/test/specs/patch03_external_source_spec.rb +1 -1
  244. data/test/specs/patch04_titles_spec.rb +1 -1
  245. data/test/specs/patch05_policies_spec.rb +1 -1
  246. data/test/specs/patch06_cleanup_spec.rb +1 -1
  247. data/test/specs/policy_spec.rb +1 -1
  248. metadata +15 -4
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -48,7 +48,7 @@ module Jamf
48
48
  RSRC_BASE = 'uapi'.freeze
49
49
 
50
50
  # The API version must be this or higher
51
- MIN_API_VERSION = Gem::Version.new('1.0')
51
+ MIN_JAMF_VERSION = Gem::Version.new('10.15.0')
52
52
 
53
53
  HTTPS_SCHEME = 'https'.freeze
54
54
 
@@ -111,6 +111,7 @@ module Jamf
111
111
  @login_time
112
112
  @keep_alive
113
113
  @token_refresh
114
+ @pw_fallback
114
115
  ].freeze
115
116
 
116
117
  # Attributes
@@ -140,6 +141,10 @@ module Jamf
140
141
  # @return [String, nil]
141
142
  attr_reader :base_url
142
143
 
144
+ # @return [Boolean] if token refresh/keepaliave fails, try to get a new one
145
+ # with the passwd used with .connect. Defaults to true
146
+ attr_reader :pw_fallback
147
+
143
148
  # @return [Boolean]
144
149
  attr_reader :connected
145
150
  alias connected? connected
@@ -227,14 +232,13 @@ module Jamf
227
232
  # ### Tokens
228
233
  # Instead of a user and password, you may specify a valid 'token:', either:
229
234
  #
230
- # A Jamf::Connection::Token object, which can be extracted from an active
235
+ # A Jamf::Connection::Token object, which can be extracted from an active
231
236
  # Jamf::Connection via its #token method
232
237
  #
233
238
  # or
234
239
  #
235
240
  # A token string e.g. "eyJhdXR...6EKoo" from any source can also be used.
236
241
  #
237
- #
238
242
  # Any values available via Jamf.config will be used if they are not provided
239
243
  # in the parameters.
240
244
  #
@@ -251,6 +255,19 @@ module Jamf
251
255
  #
252
256
  # @param token: [Jamf::Connection::Token, String] An existing, valid token.
253
257
  # When used, there's no need to provide user: or pw:.
258
+ # NOTE if using pw_fallback:true (the default) while providing a token
259
+ # you will also need to provide the password for the token user in the pw:
260
+ # parameter, or be prompted for it. If you don't have the pw for the
261
+ # token user, be sure to set pw_fallback to false.
262
+ #
263
+ # @param token_refresh: [Integer] Refresh the token this many seconds before
264
+ # it expires. Must be >= DFT_TOKEN_REFRESH
265
+ #
266
+ # @pararm pw_fallback: [Boolean] Default is true. Use the password provided
267
+ # to refresh the token if regular refresh doesn't work (e.g. token is expired).
268
+ # NOTE: This causes the password to be kept in memory. If you don't want
269
+ # this, explicitly set pw_fallback to false, however long-running processes
270
+ # may lose connection if token refresh fails for any reason.
254
271
  #
255
272
  # @param open_timeout: [Integer] The number of seconds for initial contact
256
273
  # with the host.
@@ -268,7 +285,8 @@ module Jamf
268
285
  # This sets all the instance vars to nil, and flushes/creates the caches
269
286
  disconnect
270
287
 
271
- # This sets @token, and adds host, port, user to params from a Token object
288
+ # If there's a Token object in :token, this sets @token,
289
+ # and adds host, port, user from that token
272
290
  parse_token params
273
291
 
274
292
  # Get host, port, user and pw from a URL, add to params if needed
@@ -277,6 +295,8 @@ module Jamf
277
295
  # apply defaults from config, client, and then this class.
278
296
  apply_connection_defaults params
279
297
 
298
+ # Once we're here, all params have been parsed & defaulted into the
299
+ # params hash, so
280
300
  # make sure we have the minimum needed params for a connection
281
301
  verify_basic_params params
282
302
 
@@ -285,15 +305,20 @@ module Jamf
285
305
 
286
306
  # if no @token already, get one from from
287
307
  # either a token string or a pw
288
- @token ||=
308
+ unless @token
289
309
  if params[:token].is_a? String
290
- tk = token_from :token_string, params[:token]
310
+ @token = token_from :token_string, params[:token]
291
311
  # get the user from the token
292
- @user = tk.user
293
- tk
312
+ @user = @toke.user
313
+ # if @pw_fallback, the pw must be acquired, since it isn't in
314
+ # the token
315
+ @pw = acquire_password(params[:pw]) if @pw_fallback
294
316
  else
295
- token_from :pw, acquire_password(params[:pw])
317
+ pw = acquire_password(params[:pw])
318
+ @token = token_from :pw, pw
319
+ @pw = pw if @pw_fallback
296
320
  end
321
+ end
297
322
 
298
323
  # Now get some values from our token
299
324
  @base_url = @token.base_url
@@ -303,43 +328,49 @@ module Jamf
303
328
  @rest_cnx = create_connection
304
329
 
305
330
  # make sure versions are good
306
- validate_api_version
331
+ validate_jamf_version
307
332
 
308
333
  @connected = true
309
334
 
310
335
  # start keepalive if needed
311
- @keep_alive = params[:keep_alive].nil? ? false : params[:keep_alive]
312
336
  start_keep_alive if @keep_alive
313
337
 
314
338
  # return our string output
315
339
  to_s
316
340
  end # connect
317
341
 
342
+ # reset all values to nil or empty
318
343
  def disconnect
319
- # reset everything except the timeouts
320
- stop_keep_alive
321
-
322
344
  @connected = false
323
345
  @name = NOT_CONNECTED
324
346
  @login_time = nil
347
+
348
+ stop_keep_alive
349
+
325
350
  @host = nil
326
351
  @port = nil
327
352
  @user = nil
328
- @token = nil
353
+ @timeout = nil
354
+ @open_timeout = nil
329
355
  @base_url = nil
356
+ @token = nil
330
357
  @rest_cnx = nil
331
358
  @ssl_options = {}
332
359
  @keep_alive = nil
360
+ @token_refresh = nil
361
+ @pw_fallback = nil
362
+ @pw = nil
333
363
 
334
364
  flushcache
335
365
  end
336
366
 
337
- # Same as disconnect, but invalidates the token
367
+ # Same as disconnect, but invalidates the token on the server first
338
368
  def logout
339
369
  @token.destroy
340
370
  disconnect
341
371
  end
342
372
 
373
+ # Get a resource
343
374
  def get(rsrc)
344
375
  validate_connected
345
376
  resp = @rest_cnx.get rsrc
@@ -423,7 +454,9 @@ module Jamf
423
454
 
424
455
  # Are we keeping the connection alive?
425
456
  def keep_alive?
426
- @keep_alive_thread&.alive? || false
457
+ return false unless @keep_alive_thread
458
+
459
+ @keep_alive_thread.alive?
427
460
  end
428
461
 
429
462
  # @return [Jamf::Timestamp, nil]
@@ -461,8 +494,12 @@ module Jamf
461
494
  @token_refresh = secs
462
495
  end
463
496
 
464
- def api_version
465
- @token.api_version
497
+ def jamf_version
498
+ @token.jamf_version
499
+ end
500
+
501
+ def jamf_build
502
+ @token.jamf_build
466
503
  end
467
504
 
468
505
  # Flush the collection and/or ea cache for the given class,
@@ -503,11 +540,11 @@ module Jamf
503
540
  end
504
541
 
505
542
  # raise exception if API version is too low.
506
- def validate_api_version
507
- vers = api_version
508
- return if Gem::Version.new(vers) >= MIN_API_VERSION
543
+ def validate_jamf_version
544
+ vers = jamf_version
545
+ return if Gem::Version.new(vers) >= MIN_JAMF_VERSION
509
546
 
510
- raise Jamf::InvalidConnectionError, "API version '#{vers}' too low, must be >= '#{MIN_API_VERSION}'"
547
+ raise Jamf::InvalidConnectionError, "API version '#{vers}' too low, must be >= '#{MIN_JAMF_VERSION}'"
511
548
  end
512
549
 
513
550
  ##### Parse Params
@@ -537,7 +574,7 @@ module Jamf
537
574
  raise "Cannot use token: it expires in less than #{TOKEN_REUSE_MIN_LIFE} seconds" if token.secs_remaining < TOKEN_REUSE_MIN_LIFE
538
575
  end
539
576
 
540
- # Get host, port, user and pw from a URL, unless they are already in the params
577
+ # Get host, port, user and pw from a URL, overriding any already in the params
541
578
  #
542
579
  # @return [String, nil] the pw if present
543
580
  #
@@ -547,27 +584,29 @@ module Jamf
547
584
  url = URI.parse url.to_s
548
585
  raise ArgumentError, 'Invalid url, scheme must be https' unless url.scheme == HTTPS_SCHEME
549
586
 
550
- params[:host] ||= url.host
551
- params[:port] ||= url.port
552
- params[:user] ||= url.user if url.user
553
- params[:pw] ||= url.password if url.password
587
+ params[:host] = url.host
588
+ params[:port] = url.port
589
+ params[:user] = url.user if url.user
590
+ params[:pw] = url.password if url.password
554
591
  end
555
592
 
556
- # Apply defaults from the Jamf.config,
557
- # then from the Jamf::Client,
593
+ # Apply defaults to the unset params for the #connect method
594
+ # First apply them from from the Jamf.config,
595
+ # then from the Jamf::Client (read from the jamf binary config),
558
596
  # then from the Jamf module defaults
559
- # to the unset params for the #connect method
560
597
  #
561
598
  # @param params[Hash] The params for #connect
562
599
  #
563
600
  # @return [Hash] The params with defaults applied
564
601
  #
565
602
  def apply_connection_defaults(params)
566
- # if no port given, either directly or via URL, and the host
567
- # is a jamfcloud host, always set the port to 443
568
- # This should happen before the config is applied, so
569
- # on-prem users can still get to jamfcoud without specifying the port
570
- params[:port] = JAMFCLOUD_PORT if params[:port].nil? && params[:host].to_s.end_with?(JAMFCLOUD_DOMAIN)
603
+ # must have a host, but accept legacy :server as well as :host
604
+ params[:host] ||= params[:server]
605
+
606
+ # if we have no port set by this point, set to cloud port
607
+ # if host is a cloud host. But leave port nil for other hosts
608
+ # (will be set via client defaults or module defaults)
609
+ params[:port] ||= JAMFCLOUD_PORT if params[:host].to_s.end_with?(JAMFCLOUD_DOMAIN)
571
610
 
572
611
  apply_defaults_from_config(params)
573
612
 
@@ -621,11 +660,12 @@ module Jamf
621
660
  # @return [Hash] The params with defaults applied
622
661
  #
623
662
  def apply_module_defaults(params)
624
- # if we have no port set by this point, assume on-prem
663
+ # if we have no port set by this point, assume on-prem.
625
664
  params[:port] ||= ON_PREM_SSL_PORT
626
665
  params[:timeout] ||= DFT_TIMEOUT
627
666
  params[:open_timeout] ||= DFT_OPEN_TIMEOUT
628
667
  params[:ssl_version] ||= DFT_SSL_VERSION
668
+ params[:token_refresh] ||= DFT_TOKEN_REFRESH
629
669
  # if we have a TTY, pw defaults to :prompt
630
670
  params[:pw] ||= :prompt if STDIN.tty?
631
671
  end
@@ -641,36 +681,38 @@ module Jamf
641
681
  # and is already parsed
642
682
  return if @token
643
683
 
644
- # must have a host, but accept legacy :server as well as :host
645
- params[:host] ||= params[:server]
684
+ # must have a host
646
685
  raise Jamf::MissingDataError, 'No Jamf :host specified, or in configuration.' unless params[:host]
647
686
 
648
687
  # no need for user or pass if using a token string
649
688
  return if params[:token].is_a? String
650
689
 
690
+ # must have user and pw
651
691
  raise Jamf::MissingDataError, 'No Jamf :user specified, or in configuration.' unless params[:user]
652
692
  raise Jamf::MissingDataError, "No :pw specified for user '#{params[:user]}'" unless params[:pw]
653
693
  end
654
694
 
695
+ # Turn the connection parameters into instance vars
655
696
  def parse_connect_params(params)
656
697
  @host = params[:host]
657
698
  @port = params[:port]
658
- @port ||= @host.end_with?(JAMFCLOUD_DOMAIN) ? JAMFCLOUD_PORT : ON_PREM_SSL_PORT
659
699
  @user = params[:user]
660
700
 
661
- @token_refresh = params[:token_refresh].to_i || DFT_TOKEN_REFRESH
662
- # token refresh must be at least DFT_TOKEN_REFRESH
663
- @token_refresh = DFT_TOKEN_REFRESH if @token_refresh < DFT_TOKEN_REFRESH
701
+ @keep_alive = params[:keep_alive].nil? ? false : params[:keep_alive]
702
+ @pw_fallback = params[:pw_fallback].nil? ? true : params[:pw_fallback]
703
+ @token_refresh = params[:token_refresh].to_i
664
704
 
665
- @timeout = params[:timeout] || DFT_TIMEOUT
666
- @open_timeout = params[:open_timeout] || DFT_TIMEOUT
705
+ @timeout = params[:timeout]
706
+ @open_timeout = params[:open_timeout]
667
707
  @base_url = URI.parse "https://#{@host}:#{@port}/#{RSRC_BASE}"
708
+
668
709
  # ssl opts for faraday
669
710
  # TODO: implement all of faraday's options
670
711
  @ssl_options = {
671
712
  verify: params[:verify_cert],
672
713
  version: params[:ssl_version]
673
714
  }
715
+
674
716
  @name = "#{@user}@#{@host}:#{@port}" if @name == NOT_CONNECTED
675
717
  end
676
718
 
@@ -701,16 +743,18 @@ module Jamf
701
743
  # @return [String] The password for the connection
702
744
  #
703
745
  def acquire_password(param_pw)
704
- if param_pw == :prompt
705
- Jamf.prompt_for_password "Enter the password for Jamf user #{@user}@#{@host}:"
706
- elsif param_pw.is_a?(Symbol) && param_pw.to_s.start_with?('stdin')
707
- param_pw.to_s =~ /^stdin(\d+)$/
708
- line = Regexp.last_match(1)
709
- line ||= 1
710
- Jamf.stdin line
711
- else
712
- param_pw
713
- end # if
746
+ pw =
747
+ if param_pw == :prompt
748
+ Jamf.prompt_for_password "Enter the password for Jamf user #{@user}@#{@host}:"
749
+ elsif param_pw.is_a?(Symbol) && param_pw.to_s.start_with?('stdin')
750
+ param_pw.to_s =~ /^stdin(\d+)$/
751
+ line = Regexp.last_match(1)
752
+ line ||= 1
753
+ Jamf.stdin line
754
+ else
755
+ param_pw
756
+ end # if
757
+ pw
714
758
  end # acquire pw
715
759
 
716
760
  # create the faraday connection object
@@ -747,11 +791,11 @@ module Jamf
747
791
  begin
748
792
  next if @token.secs_remaining > @token_refresh
749
793
 
750
- @token.refresh
794
+ @token.refresh @pw
751
795
  # make sure faraday uses the new token
752
796
  @rest_cnx.headers[:authorization] = @token.auth_token
753
797
  rescue
754
- # TODO: Some kind of error reporting??
798
+ # TODO: Some kind of error reporting
755
799
  next
756
800
  end
757
801
  end # loop
@@ -764,7 +808,9 @@ module Jamf
764
808
  # @return [void]
765
809
  #
766
810
  def stop_keep_alive
767
- @keep_alive_thread&.kill
811
+ return unless @keep_alive_thread
812
+
813
+ @keep_alive_thread.kill if @keep_alive_thread.alive?
768
814
  @keep_alive_thread = nil
769
815
  end
770
816
 
@@ -811,7 +857,7 @@ module Jamf
811
857
  end
812
858
 
813
859
  def self.disconnect
814
- @active_connection&.disconnect
860
+ @active_connection.disconnect if @active_connection
815
861
  end
816
862
 
817
863
  end # module Jamf
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -30,6 +30,8 @@ module Jamf
30
30
  # A token used for a JSS connection
31
31
  class Token
32
32
 
33
+ JAMF_VERSION_RSRC = 'v1/jamf-pro-version'.freeze
34
+
33
35
  AUTH_RSRC = 'auth'.freeze
34
36
 
35
37
  NEW_TOKEN_RSRC = "#{AUTH_RSRC}/tokens".freeze
@@ -56,9 +58,22 @@ module Jamf
56
58
  # @return [URI] The base API url, e.g. https://myjamf.jamfcloud.com/uapi
57
59
  attr_reader :base_url
58
60
 
59
- # when was this token created?
61
+ # @return [Jamf::Timestamp] when was this token created?
60
62
  attr_reader :login_time
61
63
 
64
+ # What happened the last time we tried to refresh?
65
+ # :expired_refreshed - token was expired, a new token was created with the pw
66
+ # :expired_pw_failed - token was expired, pw failed to make a new token
67
+ # :expired_no_pw - token was expired, but no pw was given to make a new one
68
+ # :refreshed - the token refresh worked with no need for the pw
69
+ # :refresh_failed - the token refresh failed, and no pw was given to make a new one
70
+ # :refreshed_with_pw - the token refresh failed, pw worked to make a new token
71
+ # :refresh_failed_no_pw - the token refresh failed, pw also failed to make a new token
72
+ # nil - no refresh has been attempted for this token.
73
+ #
74
+ # @return [Symbol, nil] :refreshed, :pw, :expired,:failed, or nil if never refreshed
75
+ attr_reader :last_refresh_result
76
+
62
77
  def initialize(**params)
63
78
  @valid = false
64
79
  @user = params[:user]
@@ -90,7 +105,7 @@ module Jamf
90
105
  raise Jamf::AuthenticationError, 'Incorrect name or password'
91
106
  else
92
107
  # TODO: better error reporting here
93
- raise 'An error occurred while authenticating'
108
+ raise Jamf::AuthenticationError, 'An error occurred while authenticating'
94
109
  end
95
110
  end # init_from_pw
96
111
 
@@ -118,8 +133,13 @@ module Jamf
118
133
  end
119
134
 
120
135
  # @return [String]
121
- def api_version
122
- token_connection(Jamf::Connection::SLASH, token: @auth_token).get.body[:version]
136
+ def jamf_version
137
+ raw_jamf_version.split('-').first
138
+ end
139
+
140
+ # @return [String]
141
+ def jamf_build
142
+ raw_jamf_version.split('-').last
123
143
  end
124
144
 
125
145
  # @return [Boolean]
@@ -165,18 +185,39 @@ module Jamf
165
185
  @account = Jamf::APIAccount.new resp.body
166
186
  end
167
187
 
168
- # Use this token to get a fresh one
169
- # TODO: better error reporting
170
- def refresh
171
- raise 'Token has expired' if expired?
188
+ # Use this token to get a fresh one. If a pw is provided
189
+ # try to use it to get a new token if a proper refresh fails.
190
+ #
191
+ # @param pw [String] Optional password to use if token refresh fails.
192
+ # Must be the correct passwd or the token's user (obviously)
193
+ #
194
+ # @return [Jamf::Timestamp] the new expiration time
195
+ #
196
+ def refresh(pw = nil)
197
+ # gotta have a pw if expired
198
+ if expired?
199
+ # try the passwd
200
+ return refresh_with_passwd(pw, :expired_refreshed, :expired_pw_failed) if pw
201
+
202
+ # no passwd? no chance!
203
+ @last_refresh_result = :expired_no_pw
204
+ raise Jamf::InvalidTokenError, 'Token has expired'
205
+ end
172
206
 
207
+ # Now try a normal refresh of our non-expired token
173
208
  keep_alive_token_resp = token_connection(KEEP_ALIVE_RSRC, token: @auth_token).post
209
+ if keep_alive_token_resp.success?
210
+ parse_token_from_response keep_alive_token_resp
211
+ @last_refresh_result = :refreshed
212
+ return expires
213
+ end
174
214
 
175
- raise 'An error occurred while authenticating' unless keep_alive_token_resp.success?
215
+ # if we're here, the normal refresh failed, so try the pw
216
+ return refresh_with_passwd(pw, :refreshed_with_pw, :refresh_failed_no_pw) if pw
176
217
 
177
- parse_token_from_response keep_alive_token_resp
178
- # parse_token_from_response keep_alive_rsrc.post('')
179
- expires
218
+ # if we're here, no pw? no chance!
219
+ @last_refresh_result = :refresh_failed
220
+ raise 'An error occurred while refreshing the token' unless pw
180
221
  end
181
222
  alias keep_alive refresh
182
223
 
@@ -190,6 +231,32 @@ module Jamf
190
231
  #################################
191
232
  private
192
233
 
234
+ # refresh a token using a password, return a result
235
+ # @param pw[String] the password to use
236
+ # @return [JamfTimestamp] the new expiration
237
+ def refresh_with_passwd(pw, success, failure)
238
+ init_from_pw(pw)
239
+ @last_refresh_result = success
240
+ expires
241
+ rescue => e
242
+ @last_refresh_result = failure
243
+ raise e, "#{e}. Status: :#{failure}"
244
+ end
245
+
246
+ # @return [String]
247
+ def raw_jamf_version
248
+ # TODO: Remove this once we require Jamf Pro 10.19 and up
249
+ # the rsrc for getting the version used to be nothing (the
250
+ # base url itself returnedit) but now its JAMF_VERSION_RSRC
251
+ resp = token_connection(Jamf::BLANK, token: @auth_token).get # .body # [:version]
252
+ return resp.body[:version] if resp.success?
253
+
254
+ resp = token_connection(JAMF_VERSION_RSRC, token: @auth_token).get
255
+ return resp.body[:version] if resp.success?
256
+
257
+ raise Jamf::InvalidConnectionError, 'Unable to read Jamf version from the API'
258
+ end
259
+
193
260
  # a generic, one-time Faraday connection for token
194
261
  # acquision & manipulation
195
262
  #