ruby-jss 1.2.9 → 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.
- checksums.yaml +4 -4
- data/CHANGES.md +196 -1
- 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 +107 -83
- data/lib/jamf/api/abstract_classes/prestage.rb +55 -30
- 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 +20 -12
- data/lib/jamf/api/connection/api_error.rb +8 -8
- data/lib/jamf/api/connection/token.rb +36 -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/department.rb +1 -1
- data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +13 -13
- 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/configuration.rb +7 -9
- data/lib/jamf/ruby_extensions.rb +1 -0
- data/lib/jamf/ruby_extensions/array.rb +1 -1
- data/lib/jamf/ruby_extensions/array/utils.rb +3 -3
- data/lib/jamf/ruby_extensions/dig.rb +52 -0
- data/lib/jamf/validate.rb +63 -24
- data/lib/jamf/version.rb +1 -1
- data/lib/jss.rb +4 -1
- data/lib/jss/api_connection.rb +110 -397
- data/lib/jss/api_object.rb +16 -13
- data/lib/jss/api_object/advanced_search.rb +27 -26
- data/lib/jss/api_object/app_store_country_codes.rb +298 -0
- data/lib/jss/api_object/categorizable.rb +1 -1
- data/lib/jss/api_object/computer.rb +5 -1
- data/lib/jss/api_object/configuration_profile.rb +34 -3
- data/lib/jss/api_object/directory_binding.rb +273 -0
- data/lib/jss/api_object/directory_binding_type.rb +96 -0
- data/lib/jss/api_object/directory_binding_type/active_directory.rb +539 -0
- data/lib/jss/api_object/directory_binding_type/admitmac.rb +594 -0
- data/lib/jss/api_object/directory_binding_type/centrify.rb +226 -0
- data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
- data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
- data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
- data/lib/jss/api_object/distribution_point.rb +97 -37
- data/lib/jss/api_object/dock_item.rb +143 -0
- data/lib/jss/api_object/ebook.rb +1 -2
- data/lib/jss/api_object/extendable.rb +68 -32
- data/lib/jss/api_object/extension_attribute.rb +4 -3
- data/lib/jss/api_object/group.rb +33 -2
- data/lib/jss/api_object/mac_application.rb +107 -8
- data/lib/jss/api_object/mobile_device.rb +3 -0
- data/lib/jss/api_object/mobile_device_application.rb +12 -0
- data/lib/jss/api_object/network_segment.rb +195 -70
- data/lib/jss/api_object/package.rb +105 -40
- data/lib/jss/api_object/patch_source.rb +10 -9
- data/lib/jss/api_object/policy.rb +491 -7
- data/lib/jss/api_object/printer.rb +446 -0
- data/lib/jss/api_object/scopable.rb +10 -15
- data/lib/jss/api_object/scopable/scope.rb +386 -71
- data/lib/jss/api_object/self_servable.rb +17 -9
- data/lib/jss/api_object/uploadable.rb +1 -1
- data/lib/jss/api_object/user.rb +42 -1
- data/lib/jss/api_object/vpp_account.rb +209 -0
- data/lib/jss/api_object/vppable.rb +169 -13
- data/lib/jss/composer.rb +1 -1
- data/lib/jss/exceptions.rb +3 -0
- data/lib/jss/server.rb +15 -0
- data/lib/jss/utility.rb +8 -22
- data/lib/jss/validate.rb +53 -10
- data/lib/jss/version.rb +1 -1
- metadata +50 -22
data/lib/jamf/configuration.rb
CHANGED
|
@@ -103,8 +103,8 @@ module Jamf
|
|
|
103
103
|
# The Pathname to the machine-wide preferences
|
|
104
104
|
GLOBAL_CONF_FILE = Pathname.new "/etc/#{CONF_FILENAME}"
|
|
105
105
|
|
|
106
|
-
# The Pathname to the user-specific preferences plist
|
|
107
|
-
USER_CONF_FILE = ENV['HOME']
|
|
106
|
+
# The Pathname to the user-specific preferences plist if there is one
|
|
107
|
+
USER_CONF_FILE = Pathname.new("#{ENV['HOME']}/.#{CONF_FILENAME}")
|
|
108
108
|
|
|
109
109
|
# The attribute keys we maintain, and the type they should be stored as
|
|
110
110
|
CONF_KEYS = {
|
|
@@ -134,7 +134,6 @@ module Jamf
|
|
|
134
134
|
# Constructor
|
|
135
135
|
#####################################
|
|
136
136
|
|
|
137
|
-
|
|
138
137
|
# Initialize!
|
|
139
138
|
#
|
|
140
139
|
def initialize
|
|
@@ -145,7 +144,6 @@ module Jamf
|
|
|
145
144
|
# Public Instance Methods
|
|
146
145
|
#####################################
|
|
147
146
|
|
|
148
|
-
|
|
149
147
|
# Clear all values
|
|
150
148
|
#
|
|
151
149
|
# @return [void]
|
|
@@ -159,7 +157,7 @@ module Jamf
|
|
|
159
157
|
# @return [void]
|
|
160
158
|
#
|
|
161
159
|
def read_global
|
|
162
|
-
read GLOBAL_CONF_FILE if GLOBAL_CONF_FILE
|
|
160
|
+
read GLOBAL_CONF_FILE if GLOBAL_CONF_FILE.file? && GLOBAL_CONF_FILE.readable?
|
|
163
161
|
end
|
|
164
162
|
|
|
165
163
|
# (Re)read the user prefs, if it exists.
|
|
@@ -167,7 +165,7 @@ module Jamf
|
|
|
167
165
|
# @return [void]
|
|
168
166
|
#
|
|
169
167
|
def read_user
|
|
170
|
-
read USER_CONF_FILE if USER_CONF_FILE
|
|
168
|
+
read USER_CONF_FILE if USER_CONF_FILE.file? && USER_CONF_FILE.readable?
|
|
171
169
|
end
|
|
172
170
|
|
|
173
171
|
# Clear the settings and reload the prefs files, or another file if provided
|
|
@@ -196,9 +194,9 @@ module Jamf
|
|
|
196
194
|
def save(file)
|
|
197
195
|
path =
|
|
198
196
|
case file
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
when :global then GLOBAL_CONF_FILE
|
|
198
|
+
when :user then USER_CONF_FILE
|
|
199
|
+
else Pathname.new(file)
|
|
202
200
|
end
|
|
203
201
|
|
|
204
202
|
raise Jamf::MissingDataError, "No HOME environment variable, can't write to user conf file." if path.nil?
|
data/lib/jamf/ruby_extensions.rb
CHANGED
|
@@ -25,6 +25,7 @@ module JamfRubyExtensions
|
|
|
25
25
|
|
|
26
26
|
module Array
|
|
27
27
|
|
|
28
|
+
# Useful monkey patches for Array
|
|
28
29
|
module Utils
|
|
29
30
|
|
|
30
31
|
# Fetch a string from an Array case-insensitively,
|
|
@@ -40,8 +41,7 @@ module JamfRubyExtensions
|
|
|
40
41
|
# nil if it doesn't exist
|
|
41
42
|
#
|
|
42
43
|
def j_ci_fetch(somestring)
|
|
43
|
-
|
|
44
|
-
each { |s| return s if s&.casecmp?(somestring) }
|
|
44
|
+
each { |s| return s if s.respond_to?(:casecmp?) && s.casecmp?(somestring) }
|
|
45
45
|
nil
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -52,7 +52,7 @@ module JamfRubyExtensions
|
|
|
52
52
|
# @return [Boolean]
|
|
53
53
|
#
|
|
54
54
|
def j_ci_include?(somestring)
|
|
55
|
-
any? { |s| s
|
|
55
|
+
any? { |s| s.respond_to?(:casecmp?) && s.casecmp?(somestring) }
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
end # module
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copyright 2020 Pixar
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
5
|
+
# with the following modification; you may not use this file except in
|
|
6
|
+
# compliance with the Apache License and the following modification to it:
|
|
7
|
+
# Section 6. Trademarks. is deleted and replaced with:
|
|
8
|
+
#
|
|
9
|
+
# 6. Trademarks. This License does not grant permission to use the trade
|
|
10
|
+
# names, trademarks, service marks, or product names of the Licensor
|
|
11
|
+
# and its affiliates, except as required to comply with Section 4(c) of
|
|
12
|
+
# the License and to reproduce the content of the NOTICE file.
|
|
13
|
+
#
|
|
14
|
+
# You may obtain a copy of the Apache License at
|
|
15
|
+
#
|
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
#
|
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
# distributed under the Apache License with the above modification is
|
|
20
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
21
|
+
# KIND, either express or implied. See the Apache License for the specific
|
|
22
|
+
# language governing permissions and limitations under the Apache License.
|
|
23
|
+
|
|
24
|
+
# Gratefully borrowed from https://github.com/Invoca/ruby_dig
|
|
25
|
+
|
|
26
|
+
# modulize monkey patches
|
|
27
|
+
module RubyDig
|
|
28
|
+
|
|
29
|
+
def dig(key, *rest)
|
|
30
|
+
value = self[key]
|
|
31
|
+
if value.nil? || rest.empty?
|
|
32
|
+
value
|
|
33
|
+
elsif value.respond_to?(:dig)
|
|
34
|
+
value.dig(*rest)
|
|
35
|
+
else
|
|
36
|
+
raise TypeError, "#{value.class} does not have #dig method"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if RUBY_VERSION < '2.3'
|
|
43
|
+
|
|
44
|
+
# arrays
|
|
45
|
+
class Array; include RubyDig; end
|
|
46
|
+
|
|
47
|
+
# hashes
|
|
48
|
+
class Hash; include RubyDig; end
|
|
49
|
+
|
|
50
|
+
# ostructs
|
|
51
|
+
class OpenStruct; include RubyDig; end
|
|
52
|
+
end
|
data/lib/jamf/validate.rb
CHANGED
|
@@ -37,7 +37,7 @@ module Jamf
|
|
|
37
37
|
module Validate
|
|
38
38
|
|
|
39
39
|
# The regular expression that matches a valid MAC address.
|
|
40
|
-
MAC_ADDR_RE = /^[a-f0-9]{2}(:[a-f0-9]{2}){5}$/i
|
|
40
|
+
MAC_ADDR_RE = /^[a-f0-9]{2}(:[a-f0-9]{2}){5}$/i.freeze
|
|
41
41
|
|
|
42
42
|
# Validate the format and content of a MAC address
|
|
43
43
|
#
|
|
@@ -50,6 +50,7 @@ module Jamf
|
|
|
50
50
|
def self.mac_address(val, msg = nil)
|
|
51
51
|
msg ||= "Not a valid MAC address: '#{val}'"
|
|
52
52
|
raise Jamf::InvalidDataError, msg unless val =~ MAC_ADDR_RE
|
|
53
|
+
|
|
53
54
|
val
|
|
54
55
|
end
|
|
55
56
|
|
|
@@ -68,10 +69,11 @@ module Jamf
|
|
|
68
69
|
ok = false unless parts.size == 4
|
|
69
70
|
parts.each { |p| ok = false unless p.j_integer? && p.to_i < 256 && p.to_i >= 0 }
|
|
70
71
|
raise Jamf::InvalidDataError, msg unless ok
|
|
72
|
+
|
|
71
73
|
val
|
|
72
74
|
end
|
|
73
75
|
|
|
74
|
-
# Does a
|
|
76
|
+
# Does a given JSONObject class have a given JSON attribute?
|
|
75
77
|
#
|
|
76
78
|
# @param klass [<JSONObject] A class descended from JSONObject
|
|
77
79
|
#
|
|
@@ -83,9 +85,24 @@ module Jamf
|
|
|
83
85
|
raise "#{klass} is not a descendent of JSONObject" unless klass < Jamf::JSONObject
|
|
84
86
|
|
|
85
87
|
raise Jamf::NoSuchItemError, "No attribute #{attr_name} for class #{klass}" unless klass::OBJECT_MODEL.key? attrib
|
|
88
|
+
|
|
86
89
|
attr_name
|
|
87
90
|
end
|
|
88
91
|
|
|
92
|
+
# Does a value exist in a given enum array?
|
|
93
|
+
#
|
|
94
|
+
# @param klass [<JSONObject] A class descended from JSONObject
|
|
95
|
+
#
|
|
96
|
+
# @param attr_name [Symbol] The attribute to validate
|
|
97
|
+
#
|
|
98
|
+
# @return [Symbol] The valid attribute
|
|
99
|
+
#
|
|
100
|
+
def self.in_enum(val, enum)
|
|
101
|
+
raise Jamf::InvalidDataError, "Value must be one of: #{enum.join ', '}" unless enum.include? val
|
|
102
|
+
|
|
103
|
+
val
|
|
104
|
+
end
|
|
105
|
+
|
|
89
106
|
# Validate that a value doesn't already exist for a given identifier of
|
|
90
107
|
# a given CollectionResource class
|
|
91
108
|
#
|
|
@@ -116,14 +133,12 @@ module Jamf
|
|
|
116
133
|
raise Jamf::AlreadyExistsError, msg
|
|
117
134
|
end
|
|
118
135
|
|
|
136
|
+
TRUE_FALSE = [true, false].freeze
|
|
137
|
+
|
|
119
138
|
# Confirm that the given value is a boolean value, accepting
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
#
|
|
124
|
-
# Accepted False values: false, 'false', :false, 'no', :no
|
|
125
|
-
#
|
|
126
|
-
# all Strings and Symbols are case insensitive
|
|
139
|
+
# strings and symbols and returning real booleans as needed
|
|
140
|
+
# Accepts: true, false, 'true', 'false', 'yes', 'no', 't','f', 'y', or 'n'
|
|
141
|
+
# as strings or symbols, case insensitive
|
|
127
142
|
#
|
|
128
143
|
# @param val [Boolean,String,Symbol] The value to validate
|
|
129
144
|
#
|
|
@@ -131,14 +146,36 @@ module Jamf
|
|
|
131
146
|
#
|
|
132
147
|
# @return [Boolean] the valid boolean
|
|
133
148
|
#
|
|
134
|
-
def self.boolean(val, msg =
|
|
135
|
-
|
|
136
|
-
return true if val.to_s =~ /^(
|
|
137
|
-
return false if val.to_s =~ /^(
|
|
149
|
+
def self.boolean(val, msg = 'Value must be true or false, or equivalent string or symbol')
|
|
150
|
+
return val if TRUE_FALSE.include? val
|
|
151
|
+
return true if val.to_s =~ /^(t(rue)?|y(es)?)$/i
|
|
152
|
+
return false if val.to_s =~ /^(f(alse)?|no?)$/i
|
|
138
153
|
|
|
139
154
|
raise Jamf::InvalidDataError, msg
|
|
140
155
|
end
|
|
141
156
|
|
|
157
|
+
# Confirm that a value provided is an integer or a string version
|
|
158
|
+
# of an integer, and return the string version
|
|
159
|
+
#
|
|
160
|
+
# The JPAPI specs say that all IDs are integers in strings
|
|
161
|
+
# tho, the endpoints are still implementing that in different versions.
|
|
162
|
+
#
|
|
163
|
+
# @param val[Object] the value to validate
|
|
164
|
+
#
|
|
165
|
+
# @param msg[String] A custom error message when the value is invalid
|
|
166
|
+
#
|
|
167
|
+
# @return [String] the valid integer-in-a-string
|
|
168
|
+
#
|
|
169
|
+
def self.j_id(val, msg = 'Value must be an Integer or an Integer in a String, e.g. "42"')
|
|
170
|
+
case val
|
|
171
|
+
when Integer
|
|
172
|
+
return val.to_s
|
|
173
|
+
when String
|
|
174
|
+
return val if val.j_integer?
|
|
175
|
+
end
|
|
176
|
+
raise Jamf::InvalidDataError, msg
|
|
177
|
+
end
|
|
178
|
+
|
|
142
179
|
# Confirm that a value is an Integer or a String representation of an
|
|
143
180
|
# Integer. Return the integer, or raise an error
|
|
144
181
|
#
|
|
@@ -148,10 +185,10 @@ module Jamf
|
|
|
148
185
|
#
|
|
149
186
|
# @return [Integer] the valid integer
|
|
150
187
|
#
|
|
151
|
-
def self.integer(val, msg =
|
|
152
|
-
msg ||= 'Value must be an Integer'
|
|
188
|
+
def self.integer(val, msg = 'Value must be an Integer')
|
|
153
189
|
val = val.to_i if val.is_a?(String) && val.j_integer?
|
|
154
190
|
raise Jamf::InvalidDataError, msg unless val.is_a? Integer
|
|
191
|
+
|
|
155
192
|
val
|
|
156
193
|
end
|
|
157
194
|
|
|
@@ -164,10 +201,10 @@ module Jamf
|
|
|
164
201
|
#
|
|
165
202
|
# @return [Float] the valid float
|
|
166
203
|
#
|
|
167
|
-
def self.float(val, msg =
|
|
168
|
-
msg ||= 'Value must be a Floating Point number'
|
|
204
|
+
def self.float(val, msg = 'Value must be a Floating Point number')
|
|
169
205
|
val = val.to_f if val.is_a?(String) && val.j_float?
|
|
170
|
-
raise Jamf::InvalidDataError, msg unless val.is_a?
|
|
206
|
+
raise Jamf::InvalidDataError, msg unless val.is_a? Float
|
|
207
|
+
|
|
171
208
|
val
|
|
172
209
|
end
|
|
173
210
|
|
|
@@ -180,11 +217,12 @@ module Jamf
|
|
|
180
217
|
#
|
|
181
218
|
# @return [String] the valid String
|
|
182
219
|
#
|
|
183
|
-
def self.string(val, msg =
|
|
184
|
-
msg ||= 'Value must be a String'
|
|
220
|
+
def self.string(val, msg = 'Value must be a String')
|
|
185
221
|
return Jamf::BLANK if val.nil?
|
|
222
|
+
|
|
186
223
|
val = val.to_s if val.is_a? Symbol
|
|
187
224
|
raise Jamf::InvalidDataError, msg unless val.is_a? String
|
|
225
|
+
|
|
188
226
|
val
|
|
189
227
|
end
|
|
190
228
|
|
|
@@ -197,10 +235,10 @@ module Jamf
|
|
|
197
235
|
#
|
|
198
236
|
# @return [String] the valid non-empty string
|
|
199
237
|
#
|
|
200
|
-
def self.non_empty_string(val, msg =
|
|
201
|
-
msg ||= 'value must be a non-empty String'
|
|
238
|
+
def self.non_empty_string(val, msg = 'value must be a non-empty String')
|
|
202
239
|
val = val.to_s if val.is_a? Symbol
|
|
203
240
|
raise Jamf::InvalidDataError, msg unless val.is_a?(String) && !val.empty?
|
|
241
|
+
|
|
204
242
|
val
|
|
205
243
|
end
|
|
206
244
|
|
|
@@ -214,11 +252,12 @@ module Jamf
|
|
|
214
252
|
#
|
|
215
253
|
# @return [String] the validated string
|
|
216
254
|
#
|
|
217
|
-
def self.script_contents(val, msg =
|
|
218
|
-
msg ||= "value must be a String starting with '#!'"
|
|
255
|
+
def self.script_contents(val, msg = "value must be a String starting with '#!'")
|
|
219
256
|
raise Jamf::InvalidDataError, msg unless val.is_a?(String) && val.start_with?(SCRIPT_SHEBANG)
|
|
257
|
+
|
|
220
258
|
val
|
|
221
259
|
end
|
|
260
|
+
|
|
222
261
|
end # module validate
|
|
223
262
|
|
|
224
263
|
end # module JSS
|
data/lib/jamf/version.rb
CHANGED
data/lib/jss.rb
CHANGED
|
@@ -58,7 +58,8 @@ module JSS
|
|
|
58
58
|
|
|
59
59
|
###################
|
|
60
60
|
### Gems
|
|
61
|
-
require '
|
|
61
|
+
require 'faraday'
|
|
62
|
+
require 'faraday_middleware'
|
|
62
63
|
require 'plist'
|
|
63
64
|
require 'immutable-struct'
|
|
64
65
|
require 'recursive-open-struct'
|
|
@@ -197,7 +198,9 @@ module JSS
|
|
|
197
198
|
class DistributionPoint < JSS::APIObject; end
|
|
198
199
|
class EBook < JSS::APIObject; end
|
|
199
200
|
class IBeacon < JSS::APIObject; end
|
|
201
|
+
class DockItem < JSS::APIObject; end
|
|
200
202
|
class LDAPServer < JSS::APIObject; end
|
|
203
|
+
class DirectoryBinding < JSS::APIObject; end
|
|
201
204
|
class MacApplication < JSS::APIObject; end
|
|
202
205
|
class MobileDevice < JSS::APIObject; end
|
|
203
206
|
class MobileDeviceApplication < JSS::APIObject; end
|
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,294 +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
|
-
@master_distribution_point = nil if refresh
|
|
900
|
-
return @master_distribution_point if @master_distribution_point
|
|
901
|
-
|
|
902
|
-
JSS::DistributionPoint.all_ids.each do |dp_id|
|
|
903
|
-
dp = JSS::DistributionPoint.fetch id: dp_id, api: self
|
|
904
|
-
if dp.master?
|
|
905
|
-
@master_distribution_point = dp
|
|
906
|
-
break
|
|
907
|
-
end
|
|
908
|
-
end
|
|
909
|
-
|
|
910
|
-
return @master_distribution_point if @master_distribution_point
|
|
911
|
-
|
|
912
|
-
# If we're here, the Cloud DP might be master, but there's no
|
|
913
|
-
# access to it in the API :/
|
|
914
|
-
raise JSS::NoSuchItemError, 'No Master Distribtion Point defined. It could be the Cloud Dist Point, which is not available in the classic API'
|
|
915
|
-
end
|
|
916
|
-
|
|
917
|
-
# Get the DistributionPoint instance for the machine running
|
|
918
|
-
# this code, based on its IP address. If none is defined for this IP address,
|
|
919
|
-
# use the result of master_distribution_point
|
|
920
|
-
#
|
|
921
|
-
# @param refresh[Boolean] should the distribution point be re-queried?
|
|
922
|
-
#
|
|
923
|
-
# @return [JSS::DistributionPoint]
|
|
924
|
-
#
|
|
925
|
-
def my_distribution_point(refresh = false)
|
|
926
|
-
@my_distribution_point = nil if refresh
|
|
927
|
-
return @my_distribution_point if @my_distribution_point
|
|
928
|
-
|
|
929
|
-
my_net_seg_id = my_network_segments[0]
|
|
930
|
-
|
|
931
|
-
if my_net_seg_id
|
|
932
|
-
my_net_seg = JSS::NetworkSegment.fetch(id: my_net_seg_id, api: self)
|
|
933
|
-
my_dp_name = my_net_seg.distribution_point
|
|
934
|
-
@my_distribution_point = JSS::DistributionPoint.fetch(name: my_dp_name) if my_dp_name
|
|
935
|
-
end # if my_net_seg_id
|
|
936
|
-
|
|
937
|
-
@my_distribution_point ||= master_distribution_point refresh
|
|
938
|
-
@my_distribution_point
|
|
939
|
-
end
|
|
940
|
-
|
|
941
|
-
# @deprecated
|
|
942
|
-
#
|
|
943
|
-
# @see {JSS::NetworkSegment.network_ranges}
|
|
944
|
-
#
|
|
945
|
-
def network_ranges(refresh = false)
|
|
946
|
-
JSS::NetworkSegment.network_ranges refresh, api: self
|
|
947
|
-
end # def network_segments
|
|
948
|
-
|
|
949
|
-
# @deprecated
|
|
950
|
-
#
|
|
951
|
-
# @see {JSS::NetworkSegment.network_segments_for_ip}
|
|
952
|
-
#
|
|
953
|
-
def network_segments_for_ip(ip, refresh = false)
|
|
954
|
-
JSS::NetworkSegment.network_segments_for_ip ip, refresh, api: self
|
|
955
|
-
end
|
|
956
|
-
|
|
957
|
-
# @deprecated
|
|
958
|
-
#
|
|
959
|
-
# @see {JSS::NetworkSegment.my_network_segments}
|
|
960
|
-
#
|
|
961
|
-
def my_network_segments
|
|
962
|
-
network_segments_for_ip JSS::Client.my_ip_address
|
|
963
|
-
end
|
|
964
|
-
|
|
965
|
-
# Send an MDM command to one or more mobile devices managed by
|
|
966
|
-
# this JSS
|
|
967
|
-
#
|
|
968
|
-
# see {JSS::MobileDevice.send_mdm_command}
|
|
969
|
-
#
|
|
970
|
-
# @deprecated Please use JSS::MobileDevice.send_mdm_command or its
|
|
971
|
-
# convenience methods. @see JSS::MDM
|
|
972
|
-
#
|
|
973
|
-
def send_mobiledevice_mdm_command(targets, command, data = {})
|
|
974
|
-
JSS::MobileDevice.send_mdm_command(targets, command, opts: data, api: self)
|
|
975
|
-
end
|
|
976
|
-
|
|
977
695
|
# Empty all cached lists from this connection
|
|
978
696
|
# then run garbage collection to clear any available memory
|
|
979
697
|
#
|
|
@@ -1079,6 +797,7 @@ module JSS
|
|
|
1079
797
|
#
|
|
1080
798
|
def apply_defaults_from_client(args)
|
|
1081
799
|
return unless JSS::Client.installed?
|
|
800
|
+
|
|
1082
801
|
# these settings can come from the jamf binary config, if this machine is a JSS client.
|
|
1083
802
|
args[:server] ||= JSS::Client.jss_server
|
|
1084
803
|
args[:port] ||= JSS::Client.jss_port.to_i
|
|
@@ -1132,11 +851,13 @@ module JSS
|
|
|
1132
851
|
# keep this basic level of info available for basic authentication
|
|
1133
852
|
# and JSS version checking.
|
|
1134
853
|
begin
|
|
1135
|
-
|
|
1136
|
-
rescue
|
|
854
|
+
data = get_rsrc('jssuser')
|
|
855
|
+
rescue JSS::AuthorizationError
|
|
1137
856
|
raise JSS::AuthenticationError, "Incorrect JSS username or password for '#{@user}@#{@server_host}:#{@port}'."
|
|
1138
857
|
end
|
|
1139
858
|
|
|
859
|
+
@server = JSS::Server.new data[:user], self
|
|
860
|
+
|
|
1140
861
|
min_vers = JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version]
|
|
1141
862
|
return if @server.version >= min_vers # we're good...
|
|
1142
863
|
|
|
@@ -1205,77 +926,68 @@ module JSS
|
|
|
1205
926
|
if SSL_PORTS.include? args[:port]
|
|
1206
927
|
args[:use_ssl] = true unless args[:use_ssl] == false
|
|
1207
928
|
end
|
|
929
|
+
return unless args[:use_ssl]
|
|
930
|
+
|
|
1208
931
|
# if verify_cert is anything but false, we will verify
|
|
1209
|
-
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
|
+
}
|
|
1210
941
|
end
|
|
1211
942
|
|
|
1212
|
-
# Parses the
|
|
1213
|
-
#
|
|
1214
|
-
# and re-raises a JSS::APIError with a more
|
|
1215
|
-
# useful error message.
|
|
1216
|
-
#
|
|
1217
|
-
# @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.
|
|
1218
945
|
#
|
|
1219
946
|
# @return [void]
|
|
1220
947
|
#
|
|
1221
|
-
def handle_http_error
|
|
1222
|
-
@last_http_response
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
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
|
|
1228
956
|
err = JSS::ConflictError
|
|
1229
|
-
|
|
1230
|
-
|
|
957
|
+
@last_http_response.body =~ /<p>(The server has not .*?)(<|$)/m
|
|
958
|
+
msg = Regexp.last_match(1)
|
|
959
|
+
when 400
|
|
1231
960
|
err = JSS::BadRequestError
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
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'
|
|
1235
969
|
else
|
|
1236
970
|
err = JSS::APIRequestError
|
|
1237
|
-
|
|
971
|
+
msg = "There was a error processing your request, status: #{@last_http_response.status}"
|
|
1238
972
|
end
|
|
1239
|
-
exception.http_body =~ msg_matcher
|
|
1240
|
-
msg = Regexp.last_match(1)
|
|
1241
|
-
msg ||= exception.http_body
|
|
1242
973
|
raise err, msg
|
|
1243
974
|
end
|
|
1244
975
|
|
|
1245
|
-
#
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
# @param payload[String] The XML to be passed with the DELETE
|
|
1255
|
-
#
|
|
1256
|
-
# @param additional_headers[Type] See RestClient::Request#execute
|
|
1257
|
-
#
|
|
1258
|
-
# @param &block[Type] See RestClient::Request#execute
|
|
1259
|
-
#
|
|
1260
|
-
# @return [String] the XML response from the server.
|
|
1261
|
-
#
|
|
1262
|
-
def delete_with_payload(rsrc, payload, additional_headers = {}, &block)
|
|
1263
|
-
headers = (@cnx.options[:headers] || {}).merge(additional_headers)
|
|
1264
|
-
@last_http_response = RestClient::Request.execute(
|
|
1265
|
-
@cnx.options.merge(
|
|
1266
|
-
method: :delete,
|
|
1267
|
-
url: @cnx[rsrc].url,
|
|
1268
|
-
payload: payload,
|
|
1269
|
-
headers: headers
|
|
1270
|
-
),
|
|
1271
|
-
&(block || @block)
|
|
1272
|
-
)
|
|
1273
|
-
rescue RestClient::ExceptionWithResponse => e
|
|
1274
|
-
handle_http_error e
|
|
1275
|
-
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
|
|
1276
985
|
|
|
1277
986
|
end # class APIConnection
|
|
1278
987
|
|
|
988
|
+
# JSS MODULE METHODS
|
|
989
|
+
######################
|
|
990
|
+
|
|
1279
991
|
# Create a new APIConnection object and use it for all
|
|
1280
992
|
# future API calls. If connection options are provided,
|
|
1281
993
|
# they are passed to the connect method immediately, otherwise
|
|
@@ -1303,6 +1015,7 @@ module JSS
|
|
|
1303
1015
|
#
|
|
1304
1016
|
def self.use_api_connection(connection)
|
|
1305
1017
|
raise 'API connections must be instances of JSS::APIConnection' unless connection.is_a? JSS::APIConnection
|
|
1018
|
+
|
|
1306
1019
|
@api = connection
|
|
1307
1020
|
end
|
|
1308
1021
|
|