ruby-jss 1.4.1 → 1.5.1
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.
- checksums.yaml +4 -4
- data/CHANGES.md +38 -0
- data/lib/jamf.rb +10 -3
- data/lib/jamf/api/abstract_classes/collection_resource.rb +329 -150
- data/lib/jamf/api/abstract_classes/generic_reference.rb +9 -1
- data/lib/jamf/api/abstract_classes/json_object.rb +106 -82
- data/lib/jamf/api/abstract_classes/prestage.rb +54 -29
- data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +21 -0
- data/lib/jamf/api/abstract_classes/resource.rb +4 -4
- data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
- data/lib/jamf/api/connection.rb +13 -9
- data/lib/jamf/api/connection/api_error.rb +8 -8
- data/lib/jamf/api/connection/token.rb +16 -15
- data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +14 -1
- data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
- data/lib/jamf/api/json_objects/device_enrollment_device_sync_state.rb +81 -0
- data/lib/jamf/api/json_objects/locale.rb +59 -0
- data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
- data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
- data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
- data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
- data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
- data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
- data/lib/jamf/api/mixins/change_log.rb +201 -51
- data/lib/jamf/api/mixins/filterable.rb +51 -0
- data/lib/jamf/api/mixins/pageable.rb +208 -0
- data/lib/jamf/api/mixins/sortable.rb +59 -0
- data/lib/jamf/api/resources/collection_resources/building.rb +19 -8
- data/lib/jamf/api/resources/collection_resources/category.rb +5 -3
- data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +11 -4
- data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +10 -10
- data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
- data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +24 -22
- data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
- data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
- data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +14 -14
- data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
- data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
- data/lib/jamf/validate.rb +63 -24
- data/lib/jamf/version.rb +1 -1
- data/lib/jss.rb +2 -1
- data/lib/jss/api_connection.rb +110 -370
- data/lib/jss/api_object.rb +3 -19
- data/lib/jss/api_object/categorizable.rb +1 -1
- data/lib/jss/api_object/configuration_profile.rb +34 -3
- data/lib/jss/api_object/directory_binding_type.rb +66 -60
- data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
- data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
- data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
- data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
- data/lib/jss/api_object/distribution_point.rb +2 -2
- data/lib/jss/api_object/dock_item.rb +102 -96
- data/lib/jss/api_object/extendable.rb +1 -1
- data/lib/jss/api_object/group.rb +33 -2
- data/lib/jss/api_object/network_segment.rb +43 -12
- data/lib/jss/api_object/patch_source.rb +10 -9
- data/lib/jss/api_object/printer.rb +10 -4
- data/lib/jss/api_object/scopable.rb +10 -15
- data/lib/jss/exceptions.rb +3 -0
- data/lib/jss/server.rb +15 -0
- data/lib/jss/version.rb +1 -1
- metadata +37 -22
data/lib/jamf/version.rb
CHANGED
data/lib/jss.rb
CHANGED
data/lib/jss/api_connection.rb
CHANGED
@@ -25,18 +25,6 @@
|
|
25
25
|
###
|
26
26
|
module JSS
|
27
27
|
|
28
|
-
# Constants
|
29
|
-
#####################################
|
30
|
-
|
31
|
-
# Module Variables
|
32
|
-
#####################################
|
33
|
-
|
34
|
-
# Module Methods
|
35
|
-
#####################################
|
36
|
-
|
37
|
-
# Classes
|
38
|
-
#####################################
|
39
|
-
|
40
28
|
# Instances of this class represent a REST connection to a JSS API.
|
41
29
|
#
|
42
30
|
# For most cases, a single connection to a single JSS is all you need, and
|
@@ -271,7 +259,7 @@ module JSS
|
|
271
259
|
# {#get_rsrc}, {#put_rsrc}, {#post_rsrc}, & {#delete_rsrc}
|
272
260
|
# documented below.
|
273
261
|
#
|
274
|
-
# For even lower-level work, you can access the underlying
|
262
|
+
# For even lower-level work, you can access the underlying Faraday::Connection
|
275
263
|
# inside the APIConnection via the connection's {#cnx} attribute.
|
276
264
|
#
|
277
265
|
# APIConnection instances also have a {#server} attribute which contains an
|
@@ -330,6 +318,12 @@ module JSS
|
|
330
318
|
# values for the format param of get_rsrc
|
331
319
|
GET_FORMATS = %i[json xml].freeze
|
332
320
|
|
321
|
+
HTTP_ACCEPT_HEADER = 'Accept'.freeze
|
322
|
+
HTTP_CONTENT_TYPE_HEADER = 'Content-Type'.freeze
|
323
|
+
|
324
|
+
MIME_JSON = 'application/json'.freeze
|
325
|
+
MIME_XML = 'application/xml'.freeze
|
326
|
+
|
333
327
|
# Attributes
|
334
328
|
#####################################
|
335
329
|
|
@@ -337,7 +331,7 @@ module JSS
|
|
337
331
|
attr_reader :user
|
338
332
|
alias jss_user user
|
339
333
|
|
340
|
-
# @return [
|
334
|
+
# @return [Faraday::Connection] the underlying connection resource
|
341
335
|
attr_reader :cnx
|
342
336
|
|
343
337
|
# @return [Boolean] are we connected right now?
|
@@ -359,7 +353,7 @@ module JSS
|
|
359
353
|
# @return [String] the protocol being used: http or https
|
360
354
|
attr_reader :protocol
|
361
355
|
|
362
|
-
# @return [
|
356
|
+
# @return [Faraday::Response] The response from the most recent API call
|
363
357
|
attr_reader :last_http_response
|
364
358
|
|
365
359
|
# @return [String] The base URL to to the current REST API
|
@@ -453,8 +447,6 @@ module JSS
|
|
453
447
|
# @option args :use_ssl[Boolean] should the connection be made over SSL? Defaults to true.
|
454
448
|
#
|
455
449
|
# @option args :verify_cert[Boolean] should HTTPS SSL certificates be verified. Defaults to true.
|
456
|
-
# If your connection raises RestClient::SSLCertificateNotVerified, and you don't care about the
|
457
|
-
# validity of the SSL cert. just set this explicitly to false.
|
458
450
|
#
|
459
451
|
# @option args :user[String] a JSS user who has API privs, required if not defined in JSS::CONFIG
|
460
452
|
#
|
@@ -494,7 +486,7 @@ module JSS
|
|
494
486
|
args[:password] = acquire_password args
|
495
487
|
|
496
488
|
# heres our connection
|
497
|
-
@cnx =
|
489
|
+
@cnx = create_connection args[:password]
|
498
490
|
|
499
491
|
verify_server_version
|
500
492
|
|
@@ -543,8 +535,7 @@ module JSS
|
|
543
535
|
@connected = false
|
544
536
|
end # disconnect
|
545
537
|
|
546
|
-
# Get
|
547
|
-
#
|
538
|
+
# Get a JSS resource
|
548
539
|
# The first argument is the resource to get (the part of the API url
|
549
540
|
# after the 'JSSResource/' ) The resource must be properly URL escaped
|
550
541
|
# beforehand. Note: URL.encode is deprecated, use CGI.escape
|
@@ -572,14 +563,19 @@ module JSS
|
|
572
563
|
validate_connected
|
573
564
|
raise JSS::InvalidDataError, 'format must be :json or :xml' unless GET_FORMATS.include? format
|
574
565
|
|
575
|
-
|
576
|
-
@
|
577
|
-
|
566
|
+
@last_http_response =
|
567
|
+
@cnx.get(rsrc) do |req|
|
568
|
+
req.headers[HTTP_ACCEPT_HEADER] = format == :json ? MIME_JSON : MIME_XML
|
569
|
+
end
|
578
570
|
|
579
|
-
|
580
|
-
|
581
|
-
|
571
|
+
unless @last_http_response.success?
|
572
|
+
handle_http_error
|
573
|
+
return
|
582
574
|
end
|
575
|
+
|
576
|
+
return JSON.parse(@last_http_response.body, symbolize_names: true) if format == :json && !raw_json
|
577
|
+
|
578
|
+
@last_http_response.body
|
583
579
|
end
|
584
580
|
|
585
581
|
# Update an existing JSS resource
|
@@ -597,10 +593,18 @@ module JSS
|
|
597
593
|
xml.gsub!(/\r/, ' ')
|
598
594
|
|
599
595
|
# send the data
|
600
|
-
@last_http_response =
|
596
|
+
@last_http_response =
|
597
|
+
@cnx.put(rsrc) do |req|
|
598
|
+
req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
|
599
|
+
req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
|
600
|
+
req.body = xml
|
601
|
+
end
|
602
|
+
unless @last_http_response.success?
|
603
|
+
handle_http_error
|
604
|
+
return
|
605
|
+
end
|
606
|
+
|
601
607
|
@last_http_response.body
|
602
|
-
rescue RestClient::ExceptionWithResponse => e
|
603
|
-
handle_http_error e
|
604
608
|
end
|
605
609
|
|
606
610
|
# Create a new JSS resource
|
@@ -611,17 +615,24 @@ module JSS
|
|
611
615
|
#
|
612
616
|
# @return [String] the xml response from the server.
|
613
617
|
#
|
614
|
-
def post_rsrc(rsrc, xml
|
618
|
+
def post_rsrc(rsrc, xml)
|
615
619
|
validate_connected
|
616
620
|
|
617
621
|
# convert CRs & to
|
618
|
-
xml
|
622
|
+
xml&.gsub!(/\r/, ' ')
|
619
623
|
|
620
624
|
# send the data
|
621
|
-
@last_http_response =
|
625
|
+
@last_http_response =
|
626
|
+
@cnx.post(rsrc) do |req|
|
627
|
+
req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
|
628
|
+
req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
|
629
|
+
req.body = xml
|
630
|
+
end
|
631
|
+
unless @last_http_response.success?
|
632
|
+
handle_http_error
|
633
|
+
return
|
634
|
+
end
|
622
635
|
@last_http_response.body
|
623
|
-
rescue RestClient::ExceptionWithResponse => e
|
624
|
-
handle_http_error e
|
625
636
|
end # post_rsrc
|
626
637
|
|
627
638
|
# Delete a resource from the JSS
|
@@ -630,18 +641,23 @@ module JSS
|
|
630
641
|
#
|
631
642
|
# @return [String] the xml response from the server.
|
632
643
|
#
|
633
|
-
def delete_rsrc(rsrc
|
644
|
+
def delete_rsrc(rsrc)
|
634
645
|
validate_connected
|
635
646
|
raise MissingDataError, 'Missing :rsrc' if rsrc.nil?
|
636
647
|
|
637
|
-
# payload?
|
638
|
-
return delete_with_payload rsrc, xml if xml
|
639
|
-
|
640
648
|
# delete the resource
|
641
|
-
@last_http_response =
|
649
|
+
@last_http_response =
|
650
|
+
@cnx.delete(rsrc) do |req|
|
651
|
+
req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
|
652
|
+
req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
|
653
|
+
end
|
654
|
+
|
655
|
+
unless @last_http_response.success?
|
656
|
+
handle_http_error
|
657
|
+
return
|
658
|
+
end
|
659
|
+
|
642
660
|
@last_http_response.body
|
643
|
-
rescue RestClient::ExceptionWithResponse => e
|
644
|
-
handle_http_error e
|
645
661
|
end # delete_rsrc
|
646
662
|
|
647
663
|
# Test that a given hostname & port is a JSS API server
|
@@ -657,25 +673,8 @@ module JSS
|
|
657
673
|
# ssl_options like :OP_NO_SSLv2 and :OP_NO_SSLv3 will take time to figure out..
|
658
674
|
return true if `/usr/bin/curl -s 'https://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
|
659
675
|
return true if `/usr/bin/curl -s 'http://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
|
660
|
-
false
|
661
676
|
|
662
|
-
|
663
|
-
# # NOTE: doesn't work if we can't disallow SSLv3 or force TLSv1
|
664
|
-
# # See cheat above.
|
665
|
-
# begin
|
666
|
-
# return true if open("https://#{server}:#{port}/#{TEST_PATH}", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read.include? TEST_CONTENT
|
667
|
-
#
|
668
|
-
# rescue
|
669
|
-
# # then regular http
|
670
|
-
# begin
|
671
|
-
# return true if open("http://#{server}:#{port}/#{TEST_PATH}").read.include? TEST_CONTENT
|
672
|
-
# rescue
|
673
|
-
# # any errors = no API
|
674
|
-
# return false
|
675
|
-
# end # begin
|
676
|
-
# end # begin
|
677
|
-
# # if we're here, no API
|
678
|
-
# false
|
677
|
+
false
|
679
678
|
end
|
680
679
|
|
681
680
|
# The server to which we are connected, or will
|
@@ -686,267 +685,13 @@ module JSS
|
|
686
685
|
#
|
687
686
|
def hostname
|
688
687
|
return @server_host if @server_host
|
688
|
+
|
689
689
|
srvr = JSS::CONFIG.api_server_name
|
690
690
|
srvr ||= JSS::Client.jss_server
|
691
691
|
srvr
|
692
692
|
end
|
693
693
|
alias host hostname
|
694
694
|
|
695
|
-
#################
|
696
|
-
|
697
|
-
# Call one of the 'all*' methods on a JSS::APIObject subclass
|
698
|
-
# using this APIConnection.
|
699
|
-
#
|
700
|
-
#
|
701
|
-
# @deprecated please use the .all class method of the desired class
|
702
|
-
#
|
703
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
704
|
-
# see {JSS.api_object_class}
|
705
|
-
#
|
706
|
-
# @param refresh[Boolean] Should the data be re-read from the API?
|
707
|
-
#
|
708
|
-
# @param only[String,Symbol] Limit the output to subset or data. All
|
709
|
-
# APIObject subclasses can take :ids or :names, which calls the .all_ids
|
710
|
-
# and .all_names methods. Some subclasses can take other options, e.g.
|
711
|
-
# MobileDevice can take :udids
|
712
|
-
#
|
713
|
-
# @return [Array] The list of items for the class
|
714
|
-
#
|
715
|
-
def all(class_name, refresh = false, only: nil)
|
716
|
-
the_class = JSS.api_object_class(class_name)
|
717
|
-
list_method = only ? :"all_#{only}" : :all
|
718
|
-
|
719
|
-
raise ArgumentError, "Unknown identifier: #{only} for #{the_class}" unless
|
720
|
-
the_class.respond_to? list_method
|
721
|
-
|
722
|
-
the_class.send list_method, refresh, api: self
|
723
|
-
end
|
724
|
-
|
725
|
-
# Call the 'map_all_ids_to' method on a JSS::APIObject subclass
|
726
|
-
# using this APIConnection.
|
727
|
-
#
|
728
|
-
# @deprecated please use the .map_all_ids_to class method of the desired class
|
729
|
-
#
|
730
|
-
#
|
731
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
732
|
-
# see {JSS.api_object_class}
|
733
|
-
#
|
734
|
-
# @param refresh[Boolean] Should the data be re-read from the API?
|
735
|
-
#
|
736
|
-
# @param to[String,Symbol] the value to which the ids should be mapped
|
737
|
-
#
|
738
|
-
# @return [Hash] The ids for the class keyed to the requested identifier
|
739
|
-
#
|
740
|
-
def map_all_ids(class_name, refresh = false, to: nil)
|
741
|
-
raise "'to:' value must be provided for mapping ids." unless to
|
742
|
-
the_class = JSS.api_object_class(class_name)
|
743
|
-
the_class.map_all_ids_to to, refresh, api: self
|
744
|
-
end
|
745
|
-
|
746
|
-
# Call the 'valid_id' method on a JSS::APIObject subclass
|
747
|
-
# using this APIConnection. See {JSS::APIObject.valid_id}
|
748
|
-
#
|
749
|
-
# @deprecated please use the .valid_id class method of the desired class
|
750
|
-
#
|
751
|
-
#
|
752
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass,
|
753
|
-
# see {JSS.api_object_class}
|
754
|
-
#
|
755
|
-
# @param identifier[String,Symbol] the value to which the ids should be mapped
|
756
|
-
#
|
757
|
-
# @param refresh[Boolean] Should the data be re-read from the API?
|
758
|
-
#
|
759
|
-
# @return [Integer, nil] the id of the matching object of the class,
|
760
|
-
# or nil if there isn't one
|
761
|
-
#
|
762
|
-
def valid_id(class_name, identifier, refresh = true)
|
763
|
-
the_class = JSS.api_object_class(class_name)
|
764
|
-
the_class.valid_id identifier, refresh, api: self
|
765
|
-
end
|
766
|
-
|
767
|
-
# Call the 'exist?' method on a JSS::APIObject subclass
|
768
|
-
# using this APIConnection. See {JSS::APIObject.exist?}
|
769
|
-
#
|
770
|
-
# @deprecated please use the .exist class method of the desired class
|
771
|
-
#
|
772
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
773
|
-
# see {JSS.api_object_class}
|
774
|
-
#
|
775
|
-
# @param identifier[String,Symbol] the value to which the ids should be mapped
|
776
|
-
#
|
777
|
-
# @param refresh[Boolean] Should the data be re-read from the API?
|
778
|
-
#
|
779
|
-
# @return [Boolean] Is there an object of this class in the JSS matching
|
780
|
-
# this indentifier?
|
781
|
-
#
|
782
|
-
def exist?(class_name, identifier, refresh = false)
|
783
|
-
!valid_id(class_name, identifier, refresh).nil?
|
784
|
-
end
|
785
|
-
|
786
|
-
# Call {Matchable.match} for the given class.
|
787
|
-
#
|
788
|
-
# See {Matchable.match}
|
789
|
-
#
|
790
|
-
# @deprecated Please use the .match class method of the desired class
|
791
|
-
#
|
792
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
793
|
-
# see {JSS.api_object_class}
|
794
|
-
#
|
795
|
-
# @return (see Matchable.match)
|
796
|
-
#
|
797
|
-
def match(class_name, term)
|
798
|
-
the_class = JSS.api_object_class(class_name)
|
799
|
-
raise JSS::UnsupportedError, "Class #{the_class} is not matchable" unless the_class.respond_to? :match
|
800
|
-
the_class.match term, api: self
|
801
|
-
end
|
802
|
-
|
803
|
-
# Retrieve an object of a given class from the API
|
804
|
-
# See {APIObject.fetch}
|
805
|
-
#
|
806
|
-
# @deprecated Please use the .fetch class method of the desired class
|
807
|
-
#
|
808
|
-
#
|
809
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
810
|
-
# see {JSS.api_object_class}
|
811
|
-
#
|
812
|
-
# @return [APIObject] The ruby-instance of the object.
|
813
|
-
#
|
814
|
-
def fetch(class_name, arg)
|
815
|
-
the_class = JSS.api_object_class(class_name)
|
816
|
-
the_class.fetch arg, api: self
|
817
|
-
end
|
818
|
-
|
819
|
-
# Make a ruby instance of a not-yet-existing APIObject
|
820
|
-
# of the given class
|
821
|
-
# See {APIObject.make}
|
822
|
-
#
|
823
|
-
# @deprecated Please use the .make class method of the desired class
|
824
|
-
#
|
825
|
-
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
826
|
-
# see {JSS.api_object_class}
|
827
|
-
#
|
828
|
-
# @return [APIObject] The un-created ruby-instance of the object.
|
829
|
-
#
|
830
|
-
def make(class_name, **args)
|
831
|
-
the_class = JSS.api_object_class(class_name)
|
832
|
-
args[:api] = self
|
833
|
-
the_class.make args
|
834
|
-
end
|
835
|
-
|
836
|
-
# Call {JSS::Computer.checkin_settings} q.v., passing this API
|
837
|
-
# connection
|
838
|
-
# @deprecated Please use JSS::Computer.checkin_settings
|
839
|
-
#
|
840
|
-
def computer_checkin_settings
|
841
|
-
JSS::Computer.checkin_settings api: self
|
842
|
-
end
|
843
|
-
|
844
|
-
# Call {JSS::Computer.inventory_collection_settings} q.v., passing this API
|
845
|
-
# connection
|
846
|
-
# @deprecated Please use JSS::Computer.inventory_collection_settings
|
847
|
-
#
|
848
|
-
def computer_inventory_collection_settings
|
849
|
-
JSS::Computer.inventory_collection_settings api: self
|
850
|
-
end
|
851
|
-
|
852
|
-
# Call {JSS::Computer.application_usage} q.v., passing this API
|
853
|
-
# connection
|
854
|
-
# @deprecated Please use JSS::Computer.application_usage
|
855
|
-
#
|
856
|
-
def computer_application_usage(ident, start_date, end_date = nil)
|
857
|
-
JSS::Computer.application_usage ident, start_date, end_date, api: self
|
858
|
-
end
|
859
|
-
|
860
|
-
# Call {JSS::Computer.management_data} q.v., passing this API
|
861
|
-
# connection
|
862
|
-
#
|
863
|
-
# @deprecated Please use JSS::Computer.management_data
|
864
|
-
#
|
865
|
-
def computer_management_data(ident, subset: nil, only: nil)
|
866
|
-
JSS::Computer.management_data ident, subset: subset, only: only, api: self
|
867
|
-
end
|
868
|
-
|
869
|
-
# Call {JSS::Computer.history} q.v., passing this API
|
870
|
-
# connection
|
871
|
-
#
|
872
|
-
# @deprecated Please use JSS::Computer.management_history or its
|
873
|
-
# convenience methods. @see JSS::ManagementHistory
|
874
|
-
#
|
875
|
-
def computer_history(ident, subset: nil)
|
876
|
-
JSS::Computer.history ident, subset, api: self
|
877
|
-
end
|
878
|
-
|
879
|
-
# Call {JSS::Computer.send_mdm_command} q.v., passing this API
|
880
|
-
# connection
|
881
|
-
#
|
882
|
-
# @deprecated Please use JSS::Computer.send_mdm_command or its
|
883
|
-
# convenience methods. @see JSS::MDM
|
884
|
-
#
|
885
|
-
def send_computer_mdm_command(targets, command, passcode = nil)
|
886
|
-
opts = passcode ? { passcode: passcode } : {}
|
887
|
-
JSS::Computer.send_mdm_command targets, command, opts: opts, api: self
|
888
|
-
end
|
889
|
-
|
890
|
-
# Get the DistributionPoint instance for the master
|
891
|
-
# distribution point in the JSS. If there's only one
|
892
|
-
# in the JSS, return it even if not marked as master.
|
893
|
-
#
|
894
|
-
# @param refresh[Boolean] re-read from the API?
|
895
|
-
#
|
896
|
-
# @return [JSS::DistributionPoint]
|
897
|
-
#
|
898
|
-
def master_distribution_point(refresh = false)
|
899
|
-
JSS::DistributionPoint.master_distribution_point refresh, api: self
|
900
|
-
end
|
901
|
-
|
902
|
-
# Get the DistributionPoint instance for the machine running
|
903
|
-
# this code, based on its IP address. If none is defined for this IP address,
|
904
|
-
# use the result of master_distribution_point
|
905
|
-
#
|
906
|
-
# @param refresh[Boolean] should the distribution point be re-queried?
|
907
|
-
#
|
908
|
-
# @return [JSS::DistributionPoint]
|
909
|
-
#
|
910
|
-
def my_distribution_point(refresh = false)
|
911
|
-
JSS::DistributionPoint.my_distribution_point refresh, api: self
|
912
|
-
end
|
913
|
-
|
914
|
-
# @deprecated
|
915
|
-
#
|
916
|
-
# @see {JSS::NetworkSegment.network_ranges}
|
917
|
-
#
|
918
|
-
def network_ranges(refresh = false)
|
919
|
-
JSS::NetworkSegment.network_ranges refresh, api: self
|
920
|
-
end # def network_segments
|
921
|
-
|
922
|
-
# @deprecated
|
923
|
-
#
|
924
|
-
# @see {JSS::NetworkSegment.network_segments_for_ip}
|
925
|
-
#
|
926
|
-
def network_segments_for_ip(ip, refresh = false)
|
927
|
-
JSS::NetworkSegment.network_segments_for_ip ip, refresh, api: self
|
928
|
-
end
|
929
|
-
|
930
|
-
# @deprecated
|
931
|
-
#
|
932
|
-
# @see {JSS::NetworkSegment.my_network_segments}
|
933
|
-
#
|
934
|
-
def my_network_segments
|
935
|
-
network_segments_for_ip JSS::Client.my_ip_address
|
936
|
-
end
|
937
|
-
|
938
|
-
# Send an MDM command to one or more mobile devices managed by
|
939
|
-
# this JSS
|
940
|
-
#
|
941
|
-
# see {JSS::MobileDevice.send_mdm_command}
|
942
|
-
#
|
943
|
-
# @deprecated Please use JSS::MobileDevice.send_mdm_command or its
|
944
|
-
# convenience methods. @see JSS::MDM
|
945
|
-
#
|
946
|
-
def send_mobiledevice_mdm_command(targets, command, data = {})
|
947
|
-
JSS::MobileDevice.send_mdm_command(targets, command, opts: data, api: self)
|
948
|
-
end
|
949
|
-
|
950
695
|
# Empty all cached lists from this connection
|
951
696
|
# then run garbage collection to clear any available memory
|
952
697
|
#
|
@@ -1052,6 +797,7 @@ module JSS
|
|
1052
797
|
#
|
1053
798
|
def apply_defaults_from_client(args)
|
1054
799
|
return unless JSS::Client.installed?
|
800
|
+
|
1055
801
|
# these settings can come from the jamf binary config, if this machine is a JSS client.
|
1056
802
|
args[:server] ||= JSS::Client.jss_server
|
1057
803
|
args[:port] ||= JSS::Client.jss_port.to_i
|
@@ -1105,11 +851,13 @@ module JSS
|
|
1105
851
|
# keep this basic level of info available for basic authentication
|
1106
852
|
# and JSS version checking.
|
1107
853
|
begin
|
1108
|
-
|
1109
|
-
rescue
|
854
|
+
data = get_rsrc('jssuser')
|
855
|
+
rescue JSS::AuthorizationError
|
1110
856
|
raise JSS::AuthenticationError, "Incorrect JSS username or password for '#{@user}@#{@server_host}:#{@port}'."
|
1111
857
|
end
|
1112
858
|
|
859
|
+
@server = JSS::Server.new data[:user], self
|
860
|
+
|
1113
861
|
min_vers = JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version]
|
1114
862
|
return if @server.version >= min_vers # we're good...
|
1115
863
|
|
@@ -1178,77 +926,68 @@ module JSS
|
|
1178
926
|
if SSL_PORTS.include? args[:port]
|
1179
927
|
args[:use_ssl] = true unless args[:use_ssl] == false
|
1180
928
|
end
|
929
|
+
return unless args[:use_ssl]
|
930
|
+
|
1181
931
|
# if verify_cert is anything but false, we will verify
|
1182
|
-
args[:verify_ssl] = args[:verify_cert]
|
932
|
+
args[:verify_ssl] = args[:verify_cert] != false
|
933
|
+
|
934
|
+
# ssl version if not specified
|
935
|
+
args[:ssl_version] ||= DFT_SSL_VERSION
|
936
|
+
|
937
|
+
@ssl_options = {
|
938
|
+
verify: args[:verify_ssl],
|
939
|
+
version: args[:ssl_version]
|
940
|
+
}
|
1183
941
|
end
|
1184
942
|
|
1185
|
-
# Parses the
|
1186
|
-
#
|
1187
|
-
# and re-raises a JSS::APIError with a more
|
1188
|
-
# useful error message.
|
1189
|
-
#
|
1190
|
-
# @param exception[RestClient::ExceptionWithResponse] the exception to parse
|
943
|
+
# Parses the @last_http_response
|
944
|
+
# and raises a JSS::APIError with a useful error message.
|
1191
945
|
#
|
1192
946
|
# @return [void]
|
1193
947
|
#
|
1194
|
-
def handle_http_error
|
1195
|
-
@last_http_response
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
948
|
+
def handle_http_error
|
949
|
+
return if @last_http_response.success?
|
950
|
+
|
951
|
+
case @last_http_response.status
|
952
|
+
when 404
|
953
|
+
err = JSS::NoSuchItemError
|
954
|
+
msg = 'Not Found'
|
955
|
+
when 409
|
1201
956
|
err = JSS::ConflictError
|
1202
|
-
|
1203
|
-
|
957
|
+
@last_http_response.body =~ /<p>(The server has not .*?)(<|$)/m
|
958
|
+
msg = Regexp.last_match(1)
|
959
|
+
when 400
|
1204
960
|
err = JSS::BadRequestError
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
961
|
+
@last_http_response.body =~ %r{>Bad Request</p>\n<p>(.*?)</p>\n<p>You can get technical detail}m
|
962
|
+
msg = Regexp.last_match(1)
|
963
|
+
when 401
|
964
|
+
err = JSS::AuthorizationError
|
965
|
+
msg = 'You are not authorized to do that.'
|
966
|
+
when (500..599)
|
967
|
+
err = JSS::APIRequestError
|
968
|
+
msg = 'There was an internal server error'
|
1208
969
|
else
|
1209
970
|
err = JSS::APIRequestError
|
1210
|
-
|
971
|
+
msg = "There was a error processing your request, status: #{@last_http_response.status}"
|
1211
972
|
end
|
1212
|
-
exception.http_body =~ msg_matcher
|
1213
|
-
msg = Regexp.last_match(1)
|
1214
|
-
msg ||= exception.http_body
|
1215
973
|
raise err, msg
|
1216
974
|
end
|
1217
975
|
|
1218
|
-
#
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
# @param payload[String] The XML to be passed with the DELETE
|
1228
|
-
#
|
1229
|
-
# @param additional_headers[Type] See RestClient::Request#execute
|
1230
|
-
#
|
1231
|
-
# @param &block[Type] See RestClient::Request#execute
|
1232
|
-
#
|
1233
|
-
# @return [String] the XML response from the server.
|
1234
|
-
#
|
1235
|
-
def delete_with_payload(rsrc, payload, additional_headers = {}, &block)
|
1236
|
-
headers = (@cnx.options[:headers] || {}).merge(additional_headers)
|
1237
|
-
@last_http_response = RestClient::Request.execute(
|
1238
|
-
@cnx.options.merge(
|
1239
|
-
method: :delete,
|
1240
|
-
url: @cnx[rsrc].url,
|
1241
|
-
payload: payload,
|
1242
|
-
headers: headers
|
1243
|
-
),
|
1244
|
-
&(block || @block)
|
1245
|
-
)
|
1246
|
-
rescue RestClient::ExceptionWithResponse => e
|
1247
|
-
handle_http_error e
|
1248
|
-
end # delete_with_payload
|
976
|
+
# create the faraday connection object
|
977
|
+
def create_connection(pw)
|
978
|
+
Faraday.new(@rest_url, ssl: @ssl_options) do |cnx|
|
979
|
+
cnx.basic_auth @user, pw
|
980
|
+
cnx.options[:timeout] = @timeout
|
981
|
+
cnx.options[:open_timeout] = @open_timeout
|
982
|
+
cnx.adapter Faraday::Adapter::NetHttp
|
983
|
+
end
|
984
|
+
end
|
1249
985
|
|
1250
986
|
end # class APIConnection
|
1251
987
|
|
988
|
+
# JSS MODULE METHODS
|
989
|
+
######################
|
990
|
+
|
1252
991
|
# Create a new APIConnection object and use it for all
|
1253
992
|
# future API calls. If connection options are provided,
|
1254
993
|
# they are passed to the connect method immediately, otherwise
|
@@ -1276,6 +1015,7 @@ module JSS
|
|
1276
1015
|
#
|
1277
1016
|
def self.use_api_connection(connection)
|
1278
1017
|
raise 'API connections must be instances of JSS::APIConnection' unless connection.is_a? JSS::APIConnection
|
1018
|
+
|
1279
1019
|
@api = connection
|
1280
1020
|
end
|
1281
1021
|
|