jss-api 0.5.8 → 0.6.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.
- data/CHANGES.md +55 -7
- data/README.md +2 -1
- data/bin/cgrouper +1 -1
- data/bin/subnet-update +1 -1
- data/lib/jss-api.rb +2 -363
- data/lib/jss-api/api_connection.rb +78 -15
- data/lib/jss-api/api_object.rb +1 -1
- data/lib/jss-api/api_object/advanced_search.rb +1 -1
- data/lib/jss-api/api_object/advanced_search/advanced_computer_search.rb +1 -1
- data/lib/jss-api/api_object/advanced_search/advanced_mobile_device_search.rb +1 -1
- data/lib/jss-api/api_object/advanced_search/advanced_user_search.rb +1 -1
- data/lib/jss-api/api_object/building.rb +1 -1
- data/lib/jss-api/api_object/category.rb +1 -1
- data/lib/jss-api/api_object/computer.rb +1 -1
- data/lib/jss-api/api_object/creatable.rb +1 -1
- data/lib/jss-api/api_object/criteriable.rb +1 -1
- data/lib/jss-api/api_object/criteriable/criteria.rb +1 -1
- data/lib/jss-api/api_object/criteriable/criterion.rb +1 -1
- data/lib/jss-api/api_object/department.rb +1 -1
- data/lib/jss-api/api_object/distribution_point.rb +92 -22
- data/lib/jss-api/api_object/extendable.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute/user_extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/group.rb +1 -1
- data/lib/jss-api/api_object/group/computer_group.rb +1 -1
- data/lib/jss-api/api_object/group/mobile_device_group.rb +1 -1
- data/lib/jss-api/api_object/group/user_group.rb +1 -1
- data/lib/jss-api/api_object/ldap_server.rb +1 -1
- data/lib/jss-api/api_object/locatable.rb +1 -1
- data/lib/jss-api/api_object/matchable.rb +1 -1
- data/lib/jss-api/api_object/mobile_device.rb +1 -1
- data/lib/jss-api/api_object/netboot_server.rb +1 -1
- data/lib/jss-api/api_object/network_segment.rb +1 -1
- data/lib/jss-api/api_object/osx_configuration_profile.rb +1 -1
- data/lib/jss-api/api_object/package.rb +117 -64
- data/lib/jss-api/api_object/peripheral.rb +1 -1
- data/lib/jss-api/api_object/peripheral_type.rb +1 -1
- data/lib/jss-api/api_object/policy.rb +1 -1
- data/lib/jss-api/api_object/purchasable.rb +1 -1
- data/lib/jss-api/api_object/removable_macaddr.rb +1 -1
- data/lib/jss-api/api_object/scopable.rb +1 -1
- data/lib/jss-api/api_object/scopable/scope.rb +1 -1
- data/lib/jss-api/api_object/script.rb +1 -1
- data/lib/jss-api/api_object/self_servable.rb +1 -1
- data/lib/jss-api/api_object/site.rb +1 -1
- data/lib/jss-api/api_object/software_update_server.rb +1 -1
- data/lib/jss-api/api_object/updatable.rb +1 -1
- data/lib/jss-api/api_object/uploadable.rb +1 -1
- data/lib/jss-api/api_object/user.rb +1 -1
- data/lib/jss-api/client.rb +22 -21
- data/lib/jss-api/compatibility.rb +1 -1
- data/lib/jss-api/composer.rb +2 -2
- data/lib/jss-api/configuration.rb +1 -1
- data/lib/jss-api/db_connection.rb +63 -12
- data/lib/jss-api/exceptions.rb +1 -1
- data/lib/jss-api/ruby_extensions.rb +1 -1
- data/lib/jss-api/ruby_extensions/filetest.rb +1 -1
- data/lib/jss-api/ruby_extensions/hash.rb +1 -1
- data/lib/jss-api/ruby_extensions/ipaddr.rb +1 -1
- data/lib/jss-api/ruby_extensions/pathname.rb +1 -1
- data/lib/jss-api/ruby_extensions/string.rb +17 -1
- data/lib/jss-api/ruby_extensions/time.rb +1 -1
- data/lib/jss-api/server.rb +1 -1
- data/lib/jss-api/utility.rb +416 -0
- data/lib/jss-api/version.rb +8 -8
- metadata +3 -2
@@ -1,4 +1,4 @@
|
|
1
|
-
### Copyright
|
1
|
+
### Copyright 2016 Pixar
|
2
2
|
###
|
3
3
|
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
4
4
|
### with the following modification; you may not use this file except in
|
@@ -63,8 +63,16 @@ module JSS
|
|
63
63
|
#####################################
|
64
64
|
|
65
65
|
### The base API path in the jss URL
|
66
|
-
|
67
|
-
|
66
|
+
RSRC_BASE = "JSSResource"
|
67
|
+
|
68
|
+
### A url path to load to see if there's an API available at a host.
|
69
|
+
### This just loads the API resource docs page
|
70
|
+
TEST_PATH = "api"
|
71
|
+
|
72
|
+
### If the test path loads correctly from a casper server, it'll contain
|
73
|
+
### this text
|
74
|
+
TEST_CONTENT = "<title>JSS REST API Resource Documentation</title>"
|
75
|
+
|
68
76
|
### The Default port
|
69
77
|
HTTP_PORT = 9006
|
70
78
|
|
@@ -97,6 +105,9 @@ module JSS
|
|
97
105
|
### @return [JSS::Server] the details of the JSS to which we're connected.
|
98
106
|
attr_reader :server
|
99
107
|
|
108
|
+
### @return [String] the hostname of the JSS to which we're connected.
|
109
|
+
attr_reader :server_host
|
110
|
+
|
100
111
|
#####################################
|
101
112
|
### Constructor
|
102
113
|
#####################################
|
@@ -122,6 +133,8 @@ module JSS
|
|
122
133
|
###
|
123
134
|
### @option args :port[Integer] the port number to connect with, defaults to 8443
|
124
135
|
###
|
136
|
+
### @option args :use_ssl[Boolean] should the connection be made over SSL? Defaults to true.
|
137
|
+
###
|
125
138
|
### @option args :verify_cert[Boolean] should HTTPS SSL certificates be verified. Defaults to true.
|
126
139
|
### If your connection raises RestClient::SSLCertificateNotVerified, and you don't care about the
|
127
140
|
### validity of the SSL cert. just set this explicitly to false.
|
@@ -141,7 +154,11 @@ module JSS
|
|
141
154
|
### @return [true]
|
142
155
|
###
|
143
156
|
def connect (args = {})
|
144
|
-
|
157
|
+
|
158
|
+
# the server, if not specified, might come from a couple places.
|
159
|
+
# see #hostname
|
160
|
+
args[:server] ||= hostname
|
161
|
+
|
145
162
|
# settings from config if they aren't in the args
|
146
163
|
args[:server] ||= JSS::CONFIG.api_server_name
|
147
164
|
args[:port] ||= JSS::CONFIG.api_server_port
|
@@ -155,7 +172,10 @@ module JSS
|
|
155
172
|
# set it from the prefs
|
156
173
|
args[:verify_cert] = JSS::CONFIG.api_verify_cert
|
157
174
|
end
|
158
|
-
|
175
|
+
|
176
|
+
# settings from client jamf plist if needed
|
177
|
+
args[:port] ||= JSS::Client.jss_port
|
178
|
+
|
159
179
|
# default settings if needed
|
160
180
|
args[:port] ||= SSL_PORT
|
161
181
|
args[:timeout] ||= DFT_TIMEOUT
|
@@ -173,13 +193,18 @@ module JSS
|
|
173
193
|
raise JSS::MissingDataError, "No JSS :user specified, or in configuration." unless args[:user]
|
174
194
|
raise JSS::MissingDataError, "Missing :pw for user '#{args[:user]}'" unless args[:pw]
|
175
195
|
|
176
|
-
# ssl
|
177
|
-
|
178
|
-
|
196
|
+
# we're using ssl if 1) args[:use_ssl] is anything but false
|
197
|
+
# or 2) the port is the default casper ssl port.
|
198
|
+
args[:use_ssl] = (not args[:use_ssl] == false) or (args[:port] == SSL_PORT)
|
199
|
+
|
200
|
+
# and here's the URL
|
201
|
+
ssl = args[:use_ssl] ? "s" : ''
|
202
|
+
@rest_url = URI::encode "http#{ssl}://#{args[:server]}:#{args[:port]}/#{RSRC_BASE}"
|
203
|
+
|
179
204
|
|
180
205
|
# prep the args for passing to RestClient::Resource
|
181
|
-
# if verify_cert is
|
182
|
-
args[:verify_ssl] = (args[:verify_cert]
|
206
|
+
# if verify_cert is anything but false, we will verify
|
207
|
+
args[:verify_ssl] = (args[:verify_cert] == false) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
183
208
|
|
184
209
|
args[:password] = if args[:pw] == :prompt
|
185
210
|
JSS.prompt_for_password "Enter the password for JSS user #{args[:user]}@#{args[:server]}:"
|
@@ -192,12 +217,11 @@ module JSS
|
|
192
217
|
args[:pw]
|
193
218
|
end
|
194
219
|
|
195
|
-
|
196
|
-
|
197
220
|
# heres our connection
|
198
221
|
@cnx = RestClient::Resource.new("#{@rest_url}", args)
|
199
222
|
|
200
223
|
@jss_user = args[:user]
|
224
|
+
@server_host = args[:server]
|
201
225
|
@connected = true
|
202
226
|
@server = JSS::Server.new
|
203
227
|
|
@@ -205,7 +229,7 @@ module JSS
|
|
205
229
|
raise JSS::UnsupportedError, "Your JSS Server version, #{@server.raw_version}, is to low. Must be #{JSS::MINIMUM_SERVER_VERSION} or higher."
|
206
230
|
end
|
207
231
|
|
208
|
-
return
|
232
|
+
return @connected ? @server_host : nil
|
209
233
|
end # connect
|
210
234
|
|
211
235
|
###
|
@@ -240,6 +264,7 @@ module JSS
|
|
240
264
|
def disconnect
|
241
265
|
@jss_user = nil
|
242
266
|
@rest_url = nil
|
267
|
+
@server_host = nil
|
243
268
|
@cnx = nil
|
244
269
|
@connected = false
|
245
270
|
end # disconnect
|
@@ -308,7 +333,6 @@ module JSS
|
|
308
333
|
@cnx[rsrc].post xml, :content_type => 'text/xml', :accept => :json
|
309
334
|
end #post_rsrc
|
310
335
|
|
311
|
-
###
|
312
336
|
### Delete a resource from the JSS
|
313
337
|
###
|
314
338
|
### @param rsrc[String] the resource to create, the URL part after 'JSSResource/'
|
@@ -323,7 +347,46 @@ module JSS
|
|
323
347
|
@cnx[rsrc].delete
|
324
348
|
|
325
349
|
end #delete_rsrc
|
326
|
-
|
350
|
+
|
351
|
+
|
352
|
+
### Test that a given hostname & port is a JSS API server
|
353
|
+
###
|
354
|
+
### @param server[String] The hostname to test,
|
355
|
+
###
|
356
|
+
### @param port[Integer] The port to try connecting on
|
357
|
+
###
|
358
|
+
### @return [Boolean] does the server host a JSS API?
|
359
|
+
###
|
360
|
+
def valid_server? (server, port = SSL_PORT)
|
361
|
+
# try ssl first
|
362
|
+
begin
|
363
|
+
return true if open("https://#{server}:#{port}/#{TEST_PATH}", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read.include? TEST_CONTENT
|
364
|
+
rescue
|
365
|
+
# then regular http
|
366
|
+
begin
|
367
|
+
return true if open("http://#{server}:#{port}/#{TEST_PATH}").read.include? TEST_CONTENT
|
368
|
+
rescue
|
369
|
+
# any errors = no API
|
370
|
+
return false
|
371
|
+
end # begin
|
372
|
+
end #begin
|
373
|
+
# if we're here, no API
|
374
|
+
return false
|
375
|
+
end
|
376
|
+
|
377
|
+
### The server to which we are connected, or will
|
378
|
+
### try connecting to if none is specified with the
|
379
|
+
### call to #connect
|
380
|
+
###
|
381
|
+
### @return [String] the hostname of the server
|
382
|
+
###
|
383
|
+
def hostname
|
384
|
+
return @server_host if @server_host
|
385
|
+
srvr = JSS::CONFIG.api_server_name
|
386
|
+
srvr ||= JSS::Client.jss_server
|
387
|
+
return srvr
|
388
|
+
end
|
389
|
+
|
327
390
|
### aliases
|
328
391
|
alias connected? connected
|
329
392
|
|
data/lib/jss-api/api_object.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
### Copyright
|
2
|
-
###
|
1
|
+
### Copyright 2016 Pixar
|
2
|
+
###
|
3
3
|
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
4
4
|
### with the following modification; you may not use this file except in
|
5
5
|
### compliance with the Apache License and the following modification to it:
|
6
6
|
### Section 6. Trademarks. is deleted and replaced with:
|
7
|
-
###
|
7
|
+
###
|
8
8
|
### 6. Trademarks. This License does not grant permission to use the trade
|
9
9
|
### names, trademarks, service marks, or product names of the Licensor
|
10
10
|
### and its affiliates, except as required to comply with Section 4(c) of
|
11
11
|
### the License and to reproduce the content of the NOTICE file.
|
12
|
-
###
|
12
|
+
###
|
13
13
|
### You may obtain a copy of the Apache License at
|
14
|
-
###
|
14
|
+
###
|
15
15
|
### http://www.apache.org/licenses/LICENSE-2.0
|
16
|
-
###
|
16
|
+
###
|
17
17
|
### Unless required by applicable law or agreed to in writing, software
|
18
18
|
### distributed under the Apache License with the above modification is
|
19
19
|
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
20
20
|
### KIND, either express or implied. See the Apache License for the specific
|
21
21
|
### language governing permissions and limitations under the Apache License.
|
22
|
-
###
|
22
|
+
###
|
23
23
|
###
|
24
24
|
|
25
25
|
###
|
@@ -120,7 +120,7 @@ module JSS
|
|
120
120
|
when 1
|
121
121
|
self.new :id => self.all_ids[0]
|
122
122
|
else
|
123
|
-
self.new :master
|
123
|
+
self.new :id => :master
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -244,7 +244,7 @@ module JSS
|
|
244
244
|
###
|
245
245
|
### You can also do this more easily by calling JSS.master_distribution_point
|
246
246
|
###
|
247
|
-
def initialize(args)
|
247
|
+
def initialize(args = {})
|
248
248
|
|
249
249
|
@init_data = nil
|
250
250
|
|
@@ -343,6 +343,75 @@ module JSS
|
|
343
343
|
sha256 == Digest::SHA2.new(256).update(pw).to_s
|
344
344
|
end
|
345
345
|
|
346
|
+
### Check to see if this dist point is reachable for downloads (read-only)
|
347
|
+
### via either http, if available, or filesharing.
|
348
|
+
###
|
349
|
+
### @param pw[String] the read-only password to use for checking the connection
|
350
|
+
### If http downloads are enabled, and no http password is required
|
351
|
+
### this can be omitted.
|
352
|
+
###
|
353
|
+
### @param check_http[Boolean] should we try the http download first, if enabled?
|
354
|
+
### If you're intentionally using the ro password for filesharing, and want to check
|
355
|
+
### only filesharing, then set this to false.
|
356
|
+
###
|
357
|
+
### @return [FalseClass, Symbol] false if not reachable, otherwise :http or :mountable
|
358
|
+
###
|
359
|
+
def reachable_for_download? (pw = '', check_http = true)
|
360
|
+
pw ||= ''
|
361
|
+
http_checked = ""
|
362
|
+
if check_http && http_downloads_enabled
|
363
|
+
if @username_password_required
|
364
|
+
# we don't check the pw here, because if the connection fails, we'll
|
365
|
+
# drop down below to try the password for mounting.
|
366
|
+
# we'll escape all the chars that aren't unreserved
|
367
|
+
reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]")
|
368
|
+
user_pass = "#{URI.escape @http_username,reserved_chars}:#{URI.escape ro_pw, reserved_chars}@"
|
369
|
+
url = @http_url.sub "://#{@ip_address}", "://#{user_pass}#{@ip_address}"
|
370
|
+
else
|
371
|
+
url = @http_url
|
372
|
+
end
|
373
|
+
|
374
|
+
begin
|
375
|
+
open(url).read
|
376
|
+
return :http
|
377
|
+
rescue
|
378
|
+
http_checked = "http and "
|
379
|
+
end
|
380
|
+
end # if check_http && http_downloads_enabled
|
381
|
+
|
382
|
+
return :mountable if mounted?
|
383
|
+
|
384
|
+
return false unless check_pw :ro , pw
|
385
|
+
|
386
|
+
begin
|
387
|
+
mount pw, :ro
|
388
|
+
return :mountable
|
389
|
+
rescue
|
390
|
+
return false
|
391
|
+
ensure
|
392
|
+
unmount
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
### Check to see if this dist point is reachable for uploads (read-write)
|
397
|
+
### via filesharing.
|
398
|
+
###
|
399
|
+
### @param pw[String] the read-write password to use for checking the connection
|
400
|
+
###
|
401
|
+
### @return [FalseClass, Symbol] false if not reachable, otherwise :mountable
|
402
|
+
###
|
403
|
+
def reachable_for_upload? (pw)
|
404
|
+
return :mountable if mounted?
|
405
|
+
return false unless check_pw :rw , pw
|
406
|
+
begin
|
407
|
+
mount pw, :rw
|
408
|
+
return :mountable
|
409
|
+
rescue
|
410
|
+
return false
|
411
|
+
ensure
|
412
|
+
unmount
|
413
|
+
end
|
414
|
+
end
|
346
415
|
|
347
416
|
|
348
417
|
###
|
@@ -350,19 +419,19 @@ module JSS
|
|
350
419
|
###
|
351
420
|
### @param pw[String,Symbol] the read-only or read-write password for this DistributionPoint
|
352
421
|
### If :prompt, the user is promted on the commandline to enter the password for the :user.
|
353
|
-
### If :stdin#, the password is read from a line of std in represented by the
|
354
|
-
### so :stdin3 reads the passwd from the third line of standard input. defaults to line 2,
|
422
|
+
### If :stdin#, the password is read from a line of std in represented by the digits at #,
|
423
|
+
### so :stdin3 reads the passwd from the third line of standard input. defaults to line 2,
|
355
424
|
### if no digit is supplied. see {JSS.stdin}
|
356
425
|
###
|
357
426
|
### @param access[Symbol] how to mount the DistributionPoint, and which password to expect.
|
358
|
-
### :ro = read-only, :rw
|
427
|
+
### :ro (or anything else) = read-only, :rw = read-write
|
359
428
|
###
|
360
429
|
### @return [Pathname] the mountpoint.
|
361
430
|
###
|
362
|
-
def mount(pw = nil, access = :
|
431
|
+
def mount(pw = nil, access = :ro)
|
363
432
|
return @mountpoint if mounted?
|
364
|
-
access = :
|
365
|
-
|
433
|
+
access = :ro unless access == :rw
|
434
|
+
|
366
435
|
password = if pw == :prompt
|
367
436
|
JSS.prompt_for_password "Enter the password for the #{access} user '#{access == :ro ? @read_only_username : @read_write_username }':"
|
368
437
|
elsif pw.is_a?(Symbol) and pw.to_s.start_with?('stdin')
|
@@ -373,7 +442,7 @@ module JSS
|
|
373
442
|
else
|
374
443
|
pw
|
375
444
|
end
|
376
|
-
|
445
|
+
|
377
446
|
pwok = check_pw(access, password)
|
378
447
|
unless pwok
|
379
448
|
msg = pwok.nil? ? "No #{access} password set in the JSS" : "Incorrect password for #{access} account"
|
@@ -393,13 +462,14 @@ module JSS
|
|
393
462
|
|
394
463
|
@mountpoint.mkpath
|
395
464
|
|
396
|
-
|
397
|
-
if
|
465
|
+
mount_out = `#{@mnt_cmd} -o '#{MOUNT_OPTIONS}' '#{@mount_url}' '#{@mountpoint}' 2>&1`
|
466
|
+
if $?.exitstatus == 0 and @mountpoint.mountpoint?
|
467
|
+
#if system @mnt_cmd.to_s, *['-o', MOUNT_OPTIONS, @mount_url, @mountpoint.to_s]
|
398
468
|
@mounted = access
|
399
469
|
else
|
400
470
|
@mountpoint.rmdir if @mountpoint.directory?
|
401
471
|
@mounted = nil
|
402
|
-
raise JSS::FileServiceError, "
|
472
|
+
raise JSS::FileServiceError, "Can't mount #{@ip_address}: #{mount_out}"
|
403
473
|
end
|
404
474
|
return @mountpoint
|
405
475
|
end # mount
|
@@ -421,7 +491,7 @@ module JSS
|
|
421
491
|
end
|
422
492
|
nil
|
423
493
|
end # unmount
|
424
|
-
|
494
|
+
|
425
495
|
|
426
496
|
###
|
427
497
|
### Is this thing mounted right now?
|
@@ -431,8 +501,8 @@ module JSS
|
|
431
501
|
def mounted?
|
432
502
|
@mountpoint.directory? and @mountpoint.mountpoint?
|
433
503
|
end
|
434
|
-
|
435
|
-
|
504
|
+
|
505
|
+
|
436
506
|
#### aliases
|
437
507
|
alias hostname ip_address
|
438
508
|
alias umount unmount
|