jss-api 0.6.1 → 0.6.2

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.
Files changed (71) hide show
  1. data/lib/jss-api.rb +1 -191
  2. metadata +16 -146
  3. data/.yardopts +0 -7
  4. data/CHANGES.md +0 -88
  5. data/LICENSE.txt +0 -174
  6. data/README.md +0 -396
  7. data/THANKS.md +0 -6
  8. data/bin/cgrouper +0 -485
  9. data/bin/subnet-update +0 -400
  10. data/lib/jss-api/api_connection.rb +0 -400
  11. data/lib/jss-api/api_object.rb +0 -616
  12. data/lib/jss-api/api_object/advanced_search.rb +0 -389
  13. data/lib/jss-api/api_object/advanced_search/advanced_computer_search.rb +0 -95
  14. data/lib/jss-api/api_object/advanced_search/advanced_mobile_device_search.rb +0 -96
  15. data/lib/jss-api/api_object/advanced_search/advanced_user_search.rb +0 -95
  16. data/lib/jss-api/api_object/building.rb +0 -92
  17. data/lib/jss-api/api_object/category.rb +0 -147
  18. data/lib/jss-api/api_object/computer.rb +0 -852
  19. data/lib/jss-api/api_object/creatable.rb +0 -98
  20. data/lib/jss-api/api_object/criteriable.rb +0 -189
  21. data/lib/jss-api/api_object/criteriable/criteria.rb +0 -231
  22. data/lib/jss-api/api_object/criteriable/criterion.rb +0 -228
  23. data/lib/jss-api/api_object/department.rb +0 -93
  24. data/lib/jss-api/api_object/distribution_point.rb +0 -560
  25. data/lib/jss-api/api_object/extendable.rb +0 -221
  26. data/lib/jss-api/api_object/extension_attribute.rb +0 -457
  27. data/lib/jss-api/api_object/extension_attribute/computer_extension_attribute.rb +0 -362
  28. data/lib/jss-api/api_object/extension_attribute/mobile_device_extension_attribute.rb +0 -189
  29. data/lib/jss-api/api_object/extension_attribute/user_extension_attribute.rb +0 -117
  30. data/lib/jss-api/api_object/group.rb +0 -380
  31. data/lib/jss-api/api_object/group/computer_group.rb +0 -124
  32. data/lib/jss-api/api_object/group/mobile_device_group.rb +0 -139
  33. data/lib/jss-api/api_object/group/user_group.rb +0 -139
  34. data/lib/jss-api/api_object/ldap_server.rb +0 -535
  35. data/lib/jss-api/api_object/locatable.rb +0 -286
  36. data/lib/jss-api/api_object/matchable.rb +0 -97
  37. data/lib/jss-api/api_object/mobile_device.rb +0 -556
  38. data/lib/jss-api/api_object/netboot_server.rb +0 -148
  39. data/lib/jss-api/api_object/network_segment.rb +0 -414
  40. data/lib/jss-api/api_object/osx_configuration_profile.rb +0 -261
  41. data/lib/jss-api/api_object/package.rb +0 -812
  42. data/lib/jss-api/api_object/peripheral.rb +0 -335
  43. data/lib/jss-api/api_object/peripheral_type.rb +0 -295
  44. data/lib/jss-api/api_object/policy.rb +0 -898
  45. data/lib/jss-api/api_object/purchasable.rb +0 -316
  46. data/lib/jss-api/api_object/removable_macaddr.rb +0 -98
  47. data/lib/jss-api/api_object/scopable.rb +0 -136
  48. data/lib/jss-api/api_object/scopable/scope.rb +0 -621
  49. data/lib/jss-api/api_object/script.rb +0 -631
  50. data/lib/jss-api/api_object/self_servable.rb +0 -355
  51. data/lib/jss-api/api_object/site.rb +0 -93
  52. data/lib/jss-api/api_object/software_update_server.rb +0 -109
  53. data/lib/jss-api/api_object/updatable.rb +0 -117
  54. data/lib/jss-api/api_object/uploadable.rb +0 -138
  55. data/lib/jss-api/api_object/user.rb +0 -272
  56. data/lib/jss-api/client.rb +0 -504
  57. data/lib/jss-api/compatibility.rb +0 -66
  58. data/lib/jss-api/composer.rb +0 -171
  59. data/lib/jss-api/configuration.rb +0 -306
  60. data/lib/jss-api/db_connection.rb +0 -298
  61. data/lib/jss-api/exceptions.rb +0 -95
  62. data/lib/jss-api/ruby_extensions.rb +0 -35
  63. data/lib/jss-api/ruby_extensions/filetest.rb +0 -43
  64. data/lib/jss-api/ruby_extensions/hash.rb +0 -79
  65. data/lib/jss-api/ruby_extensions/ipaddr.rb +0 -91
  66. data/lib/jss-api/ruby_extensions/pathname.rb +0 -77
  67. data/lib/jss-api/ruby_extensions/string.rb +0 -59
  68. data/lib/jss-api/ruby_extensions/time.rb +0 -63
  69. data/lib/jss-api/server.rb +0 -108
  70. data/lib/jss-api/utility.rb +0 -416
  71. data/lib/jss-api/version.rb +0 -31
@@ -1,400 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- ### Copyright 2016 Pixar
4
- ###
5
- ### Licensed under the Apache License, Version 2.0 (the "Apache License")
6
- ### with the following modification; you may not use this file except in
7
- ### compliance with the Apache License and the following modification to it:
8
- ### Section 6. Trademarks. is deleted and replaced with:
9
- ###
10
- ### 6. Trademarks. This License does not grant permission to use the trade
11
- ### names, trademarks, service marks, or product names of the Licensor
12
- ### and its affiliates, except as required to comply with Section 4(c) of
13
- ### the License and to reproduce the content of the NOTICE file.
14
- ###
15
- ### You may obtain a copy of the Apache License at
16
- ###
17
- ### http://www.apache.org/licenses/LICENSE-2.0
18
- ###
19
- ### Unless required by applicable law or agreed to in writing, software
20
- ### distributed under the Apache License with the above modification is
21
- ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22
- ### KIND, either express or implied. See the Apache License for the specific
23
- ### language governing permissions and limitations under the Apache License.
24
-
25
- ##############################
26
- # == Synopsis
27
- # Add, remove, or change the Network Segments in the JSS based on data from an input file
28
- # in CSV, tab, or other delimited format.
29
- #
30
- # == Usage
31
- # subnet-update [-t | -d delimiter] [-h] file
32
- #
33
- #
34
- # == Author
35
- # Chris Lasell <chrisl@pixar.com>
36
- #
37
- # == Copyright
38
- # Copyright (c) 2014 Pixar Animation Studios
39
-
40
- ##############################
41
- # Libraries
42
- require 'jss-api'
43
- require 'getoptlong'
44
-
45
- ##############################
46
- # The app object
47
- class App
48
-
49
- ##############################
50
- # Constants
51
-
52
- USAGE = "Usage: #{File.basename($0)} [-d delim] [--header] [-c col1,col2,col3 ] [-m manual-prefix] [--help] /path/to/file"
53
-
54
- POTENTIAL_COLUMNS = [:name, :starting, :ending, :cidr]
55
-
56
- # Whenever we process a file, we store it here. The next time we
57
- # run, if the input file is identical to this, we exit witout doing anything.
58
- DEFAULT_CACHE_FILE = Pathname.new("~/.last_subnet_update").expand_path
59
-
60
- DEFAULT_DELIMITER = "\t"
61
- DEFAULT_COLUMNS = [:name, :starting, :ending]
62
- DEFAULT_MANUAL_PREFIX = "Manual-"
63
-
64
-
65
- attr_reader :debug
66
-
67
- ###############
68
- # set up
69
- def initialize(args)
70
-
71
- # set defaults
72
- @debug = false
73
-
74
- @delim = DEFAULT_DELIMITER
75
- @header = false
76
- @columns = DEFAULT_COLUMNS
77
- @cache_file = DEFAULT_CACHE_FILE
78
- @manual_prefix = DEFAULT_MANUAL_PREFIX
79
-
80
-
81
- #define the cli opts
82
- cli_opts = GetoptLong.new(
83
- [ '--help', '-H', GetoptLong::NO_ARGUMENT ],
84
- [ '--delimiter', '--delim', '-d', GetoptLong::REQUIRED_ARGUMENT],
85
- [ '--header', '-h', GetoptLong::NO_ARGUMENT],
86
- [ '--columns', '-c', GetoptLong::OPTIONAL_ARGUMENT],
87
- [ '--manual-prefix', '-m', GetoptLong::OPTIONAL_ARGUMENT],
88
- [ '--cache', GetoptLong::REQUIRED_ARGUMENT ],
89
- [ '--debug', GetoptLong::NO_ARGUMENT],
90
- [ '--server', '-S', GetoptLong::OPTIONAL_ARGUMENT],
91
- [ '--port', '-P', GetoptLong::OPTIONAL_ARGUMENT],
92
- [ '--user', '-U', GetoptLong::OPTIONAL_ARGUMENT],
93
- [ '--no-verify-cert', '-V', GetoptLong::NO_ARGUMENT],
94
- [ '--timeout', '-T', GetoptLong::OPTIONAL_ARGUMENT]
95
- )
96
-
97
- # parse the cli opts
98
- cli_opts.each do |opt, arg|
99
- case opt
100
- when '--help' then show_help
101
- when '--delimiter' then @delim = arg
102
- when '--header' then @header = true
103
- when '--columns' then @columns = arg.split(',').map{|c| c.to_sym}
104
- when '--manual-prefix' then @manual_prefix = arg
105
- when '--cache' then @cache_file = Pathname.new arg
106
- when '--debug' then @debug = true
107
- when '--server'
108
- @server = arg
109
-
110
- when '--port'
111
- @port = arg
112
-
113
- when '--user'
114
- @user = arg
115
-
116
- when '--no-verify-cert'
117
- @verify_cert = false
118
-
119
- when '--timeout'
120
- @timeout = arg
121
-
122
- end # case
123
- end # each opt arg
124
-
125
-
126
- @columns = nil if @columns and @columns.empty?
127
-
128
- @file = args.shift
129
-
130
-
131
- end # init
132
-
133
- ###############
134
- # Go!
135
- def run
136
-
137
- unless @file
138
- puts "No input file specified."
139
- puts USAGE
140
- return
141
- end
142
-
143
- @file = Pathname.new @file
144
-
145
- unless parse_file
146
- puts "File hasn't changed since last time, no changes to make!"
147
- return
148
- end
149
-
150
- # use any config settings defined....
151
- @user ||= JSS::CONFIG.api_username
152
- @server ||= JSS::CONFIG.api_server_name
153
- @getpass = $stdin.tty? ? :prompt : :stdin
154
-
155
- raise JSS::MissingDataError, "No JSS Username provided or found in the JSS gem config." unless @user
156
- raise JSS::MissingDataError, "No JSS Server provided or found in the JSS gem config." unless @server
157
-
158
- JSS::API.connect( :server => @server,
159
- :port => @port,
160
- :verify_cert => @verify_cert,
161
- :user => @user,
162
- :pw => @getpass,
163
- :stdin_line => 1,
164
- :timeout => @timeout
165
- )
166
-
167
- update_network_segments
168
-
169
- end # run
170
-
171
- #####################################
172
- ###
173
- ### Show Help
174
- ###
175
- def show_help
176
- puts <<-FULLHELP
177
- Update the JSS Network Segments from a delimited file of subnet information.
178
-
179
- #{USAGE}
180
-
181
- Options:
182
- -d, --delimiter - The field delimiter in the file, defaults to tab.
183
- -c, --columns [col1,col2,col3]
184
- - The column order in file, must include 'name', 'starting',
185
- and either 'ending' or 'cidr'
186
- -h, --header - The first line of the file is a header line,
187
- possibly defining the columns
188
- -m, --manual-prefix - Network Segment names in the JSS with this prefix are ignored.
189
- Defaults to 'Manual-'
190
- --cache /path/.. - Where read/save the input data for comparison between runs.
191
- Defaults to ~/.last_subnet_update
192
- -S, --server srvr - specify the JSS API server name
193
- -P, --port portnum - specify the JSS API port
194
- -U, --user username - specify the JSS API user
195
- -V, --no-verify-cert - Allow self-signed, unverified SSL certificate
196
- -T, --timeout secs - specify the JSS API timeout
197
- -H, --help - show this help
198
- --debug - show the ruby backtrace when errors occur
199
-
200
- This program parses the input file line by line (possibly accounting for a header line).
201
- Each line defines the name and IP-range of a subnet/network segment.
202
-
203
- - If a segment doesn't exist in the JSS, it is created.
204
- - If a segment's range has changed, it is updated in the JSS.
205
- - If a JSS segment doesn't exist in the file, it is deleted from the JSS
206
- unless its name starts with the --manual-prefix
207
-
208
- Input File:
209
- - The file must contain three columns, separated by the --delimiter,
210
- with these names, in any order:
211
- - 'name' (the network segment name)
212
- - 'starting' (the starting IP address of the network segment)
213
- - EITHER of:
214
- - 'ending' (the ending IP address of the network segment)
215
- - 'cidr' (the network range of the segment as a CIDR bitmask, e.g. '24')
216
- Notes:
217
- - The --columns option is a comma-separted list of the three
218
- column names aboveindicating the column-order in the file.
219
-
220
- - If --columns are not provided, and --header is specified, the first line
221
- is assumed to contain the column names, separated by the delimiter
222
-
223
- - If --header is provided with --columns, the first line of the file is ignored.
224
-
225
- - The raw data from the file is cached and compared to the input file at
226
- the next run. If the data is identical, no JSS connection is made.
227
-
228
- - If no API settings are provided, they will be read from /etc/jss_gem.conf
229
- and ~/.jss_gem.conf. See the JSS Gem docs for details.
230
-
231
- - The password for the connection will be read from STDIN or prompted if needed
232
-
233
- FULLHELP
234
- exit 0
235
- end
236
-
237
- ########################
238
- # parse the incoming data file.
239
- # If the file hasn't changed from the last time we processed it
240
- # then return false
241
- # otherwise parse it into @parsed_data and return true
242
- # @parsed_data is an array of hashes, each with :name, :starting, and :ending
243
- #
244
- def parse_file
245
-
246
- raise "'#{@file}' is not readable, or not a regular file" unless @file.readable? and @file.file?
247
-
248
- # read in the file
249
- @raw_data = @file.read
250
-
251
- # compare it to the one we used last time
252
- if @cache_file.readable?
253
- return false if @raw_data == @cache_file.read
254
- end
255
-
256
- # split the data into an array by newlines
257
- lines = @raw_data.split "\n"
258
-
259
- # remove the first line if its a header, and parse it into the columns
260
- # if needed
261
- if @header
262
- header = lines.shift
263
- @columns ||= header.split(/\s*#{@delim}\s*/).map{|c| c.to_sym}
264
- end
265
-
266
- # check some state
267
- raise "Columns must include 'name' and 'starting'" unless @columns.include?(:name) and @columns.include?(:starting)
268
- raise "Columns must include either 'ending' or 'cidr'" unless @columns.include?(:ending) or @columns.include?(:cidr)
269
-
270
- @use_cidr = @columns.include? :cidr
271
-
272
-
273
- # which columns are which in the file?
274
- name = @columns.index :name
275
- starting = @columns.index :starting
276
- ending = @use_cidr ? @columns.index(:cidr) : @columns.index(:ending)
277
-
278
- # split each line and convert it into a hash
279
- @parsed_data = lines.map do |line|
280
-
281
- parts = line.split(@delim).map{|f| f.strip }
282
-
283
- unless parts[name] and parts[starting] and parts[ending]
284
- puts "Skipping invalid line: #{line}"
285
- next
286
- end
287
-
288
-
289
- {:name => parts[name], :starting => parts[starting], :ending => parts[ending]}
290
- end
291
-
292
- # parsed data is now an array of hashes
293
- return true
294
- end
295
-
296
- #############################################
297
- #############################################
298
- # Update the JSS Network Segments from GIT_NETBLOCKS_URL, q.v.
299
- def update_network_segments
300
-
301
- # CREATE any that are in the parsed data but not yet in the JSS,
302
- # and UPDATE any that exist but have modified ranges.
303
- # While looping through, make a hash of JSS::NetworkSegment objects, keyed by their name.
304
- segs_from_data = {}
305
-
306
- @parsed_data.each do |pd|
307
-
308
- # skip anthing with the manual prefix
309
- next if pd[:name].start_with? @manual_prefix
310
-
311
- ender = @use_cidr ? :cidr : :ending_address
312
-
313
- begin
314
- this_seg = JSS::NetworkSegment.new(:id => :new, :name => pd[:name], :starting_address => pd[:starting], ender => pd[:ending])
315
-
316
- # If the new netsegment should have other settings (dist. point, netboot server, etc...)
317
- # here's where you should apply those settings.
318
-
319
- this_seg.create
320
- puts "Added Network Segment '#{this_seg.name}' to the JSS"
321
-
322
- # it already exists, so see if it needs any changes
323
- rescue JSS::AlreadyExistsError
324
-
325
- # there's already one with this name, so just grab it.
326
- this_seg = JSS::NetworkSegment.new( :name => pd[:name])
327
-
328
- # does the startng addres need to be changed?
329
- needs_update = this_seg.starting_address.to_s != pd[:starting].to_s
330
-
331
- # even if we don't need to update the starting, we might need to update
332
- # the ending...
333
- unless needs_update
334
- if @use_cidr
335
- needs_update = this_seg.cidr.to_i != pd[:ending].to_i
336
- else
337
- needs_update = this_seg.ending_address.to_s != pd[:ending].to_s
338
- end # if @use_cidr
339
- end #unless needs update
340
-
341
- # did we decide we need an update?
342
- if needs_update
343
- this_seg.starting_address = pd[:starting]
344
- if @use_cidr
345
- this_seg.cidr = pd[:ending].to_i
346
- else
347
- this_seg.ending_address = pd[:ending]
348
- end # if @use_cidr
349
- this_seg.update
350
- puts "Updated IP range for Network Segment '#{this_seg.name}'"
351
-
352
- else # doesn't need update
353
- puts "Network Segment '#{this_seg.name}' doesn't have any changes."
354
- end # if needs update
355
-
356
- # rescue other errors
357
- rescue
358
- raise "There was an error with NetworkSegment #{pd[:name]}: #{$!}"
359
- end # begin
360
-
361
- segs_from_data[this_seg.name] = this_seg
362
- end
363
-
364
-
365
- # DELETE those in jss, but not in parsed data,
366
- # unless the name starts with @manual_prefix
367
- JSS::NetworkSegment.map_all_ids_to(:name).each do |id,name|
368
-
369
- next if name.start_with? @manual_prefix
370
-
371
- unless segs_from_data.keys.include? name
372
- JSS::NetworkSegment.new(:id => id).delete
373
- puts "Deleted Network Segment '#{name}' from the JSS"
374
- end # unless
375
-
376
- end # jss_uids.each seg
377
-
378
- # save the data into a file for comparison next time
379
- @cache_file.jss_save @raw_data
380
-
381
- # all done
382
- return true
383
- end # update_network_segments
384
-
385
- end # app
386
-
387
- ##############################
388
- # create the app and go
389
- begin
390
- app = App.new(ARGV)
391
- app.run
392
- rescue
393
- # handle exceptions not handled elsewhere
394
- puts "An error occurred: #{$!}"
395
- puts "Backtrace:" if app.debug
396
- puts $@ if app.debug
397
-
398
- ensure
399
-
400
- end
@@ -1,400 +0,0 @@
1
- ### Copyright 2016 Pixar
2
- ###
3
- ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
- ### with the following modification; you may not use this file except in
5
- ### compliance with the Apache License and the following modification to it:
6
- ### Section 6. Trademarks. is deleted and replaced with:
7
- ###
8
- ### 6. Trademarks. This License does not grant permission to use the trade
9
- ### names, trademarks, service marks, or product names of the Licensor
10
- ### and its affiliates, except as required to comply with Section 4(c) of
11
- ### the License and to reproduce the content of the NOTICE file.
12
- ###
13
- ### You may obtain a copy of the Apache License at
14
- ###
15
- ### http://www.apache.org/licenses/LICENSE-2.0
16
- ###
17
- ### Unless required by applicable law or agreed to in writing, software
18
- ### distributed under the Apache License with the above modification is
19
- ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
- ### KIND, either express or implied. See the Apache License for the specific
21
- ### language governing permissions and limitations under the Apache License.
22
- ###
23
- ###
24
-
25
- ###
26
- module JSS
27
-
28
- #####################################
29
- ### Constants
30
- #####################################
31
-
32
- #####################################
33
- ### Module Variables
34
- #####################################
35
-
36
- #####################################
37
- ### Module Methods
38
- #####################################
39
-
40
- #####################################
41
- ### Module Classes
42
- #####################################
43
-
44
- ###
45
- ### An API connection to the JSS.
46
- ###
47
- ### This is a singleton class, only one can exist at a time.
48
- ### Its one instance is created automatically when the module loads, but it
49
- ### isn't connected to anything at that time.
50
- ###
51
- ### Use it via the {JSS::API} constant to call the #connect
52
- ### method, and the {#get_rsrc}, {#put_rsrc}, {#post_rsrc}, & {#delete_rsrc}
53
- ### methods, q.v. below.
54
- ###
55
- ### To access the underlying RestClient::Resource instance,
56
- ### use JSS::API.cnx
57
- ###
58
- class APIConnection
59
- include Singleton
60
-
61
- #####################################
62
- ### Class Constants
63
- #####################################
64
-
65
- ### The base API path in the jss URL
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
-
76
- ### The Default port
77
- HTTP_PORT = 9006
78
-
79
- ### The SSL port
80
- SSL_PORT = 8443
81
-
82
- ### The top line of an XML doc for submitting data via API
83
- XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
84
-
85
- ### Default timeouts in seconds
86
- DFT_OPEN_TIMEOUT = 60
87
- DFT_TIMEOUT = 60
88
-
89
- ### The Default SSL Version
90
- DFT_SSL_VERSION = 'TLSv1'
91
-
92
- #####################################
93
- ### Attributes
94
- #####################################
95
-
96
- ### @return [String] the username who's connected to the JSS API
97
- attr_reader :jss_user
98
-
99
- ### @return [RestClient::Resource] the underlying connection resource
100
- attr_reader :cnx
101
-
102
- ### @return [Boolean] are we connected right now?
103
- attr_reader :connected
104
-
105
- ### @return [JSS::Server] the details of the JSS to which we're connected.
106
- attr_reader :server
107
-
108
- ### @return [String] the hostname of the JSS to which we're connected.
109
- attr_reader :server_host
110
-
111
- #####################################
112
- ### Constructor
113
- #####################################
114
-
115
- ###
116
- ### To connect, use JSS::APIConnection.instance.connect
117
- ### or a shortcut, JSS::API.connect
118
- ###
119
- def initialize ()
120
- @connected = false
121
- end # init
122
-
123
- #####################################
124
- ### Class Methods
125
- #####################################
126
-
127
- ###
128
- ### Connect to the JSS API.
129
- ###
130
- ### @param args[Hash] the keyed arguments for connection.
131
- ###
132
- ### @option args :server[String] the hostname of the JSS API server, required if not defined in JSS::CONFIG
133
- ###
134
- ### @option args :port[Integer] the port number to connect with, defaults to 8443
135
- ###
136
- ### @option args :use_ssl[Boolean] should the connection be made over SSL? Defaults to true.
137
- ###
138
- ### @option args :verify_cert[Boolean] should HTTPS SSL certificates be verified. Defaults to true.
139
- ### If your connection raises RestClient::SSLCertificateNotVerified, and you don't care about the
140
- ### validity of the SSL cert. just set this explicitly to false.
141
- ###
142
- ### @option args :user[String] a JSS user who has API privs, required if not defined in JSS::CONFIG
143
- ###
144
- ### @option args :pw[String,Symbol] Required, the password for that user, or :prompt, or :stdin
145
- ### If :prompt, the user is promted on the commandline to enter the password for the :user.
146
- ### If :stdin#, the password is read from a line of std in represented by the digit at #,
147
- ### so :stdin3 reads the passwd from the third line of standard input. defaults to line 1,
148
- ### if no digit is supplied. see {JSS.stdin}
149
- ###
150
- ### @option args :open_timeout[Integer] the number of seconds to wait for an initial response, defaults to 60
151
- ###
152
- ### @option args :timeout[Integer] the number of seconds before an API call times out, defaults to 60
153
- ###
154
- ### @return [true]
155
- ###
156
- def connect (args = {})
157
-
158
- # the server, if not specified, might come from a couple places.
159
- # see #hostname
160
- args[:server] ||= hostname
161
-
162
- # settings from config if they aren't in the args
163
- args[:server] ||= JSS::CONFIG.api_server_name
164
- args[:port] ||= JSS::CONFIG.api_server_port
165
- args[:user] ||= JSS::CONFIG.api_username
166
- args[:timeout] ||= JSS::CONFIG.api_timeout
167
- args[:open_timeout] ||= JSS::CONFIG.api_timeout_open
168
- args[:ssl_version] ||= JSS::CONFIG.api_ssl_version
169
-
170
- # if verify cert given was NOT in the args....
171
- if args[:verify_cert].nil?
172
- # set it from the prefs
173
- args[:verify_cert] = JSS::CONFIG.api_verify_cert
174
- end
175
-
176
- # settings from client jamf plist if needed
177
- args[:port] ||= JSS::Client.jss_port
178
-
179
- # default settings if needed
180
- args[:port] ||= SSL_PORT
181
- args[:timeout] ||= DFT_TIMEOUT
182
- args[:open_timeout] ||= DFT_OPEN_TIMEOUT
183
-
184
- # As of Casper 9.61 we can't use SSL, must use TLS, since SSLv3 was susceptible to poodles.
185
- # NOTE - this requires rest-client v 1.7.0 or higher
186
- # which requires mime-types 2.0 or higher, which requires ruby 1.9.2 or higher!
187
- # That means that support for ruby 1.8.7 stops with Casper 9.6
188
- args[:ssl_version] ||= DFT_SSL_VERSION
189
-
190
-
191
- # must have server, user, and pw
192
- raise JSS::MissingDataError, "No JSS :server specified, or in configuration." unless args[:server]
193
- raise JSS::MissingDataError, "No JSS :user specified, or in configuration." unless args[:user]
194
- raise JSS::MissingDataError, "Missing :pw for user '#{args[:user]}'" unless args[:pw]
195
-
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
-
204
-
205
- # prep the args for passing to RestClient::Resource
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
208
-
209
- args[:password] = if args[:pw] == :prompt
210
- JSS.prompt_for_password "Enter the password for JSS user #{args[:user]}@#{args[:server]}:"
211
- elsif args[:pw].is_a?(Symbol) and args[:pw].to_s.start_with?('stdin')
212
- args[:pw].to_s =~ /^stdin(\d+)$/
213
- line = $1
214
- line ||= 1
215
- JSS.stdin line
216
- else
217
- args[:pw]
218
- end
219
-
220
- # heres our connection
221
- @cnx = RestClient::Resource.new("#{@rest_url}", args)
222
-
223
- @jss_user = args[:user]
224
- @server_host = args[:server]
225
- @connected = true
226
- @server = JSS::Server.new
227
-
228
- if @server.version < JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version]
229
- raise JSS::UnsupportedError, "Your JSS Server version, #{@server.raw_version}, is to low. Must be #{JSS::MINIMUM_SERVER_VERSION} or higher."
230
- end
231
-
232
- return @connected ? @server_host : nil
233
- end # connect
234
-
235
- ###
236
- ### Reset the response timeout for the rest connection
237
- ###
238
- ### @param timeout[Integer] the new timeout in seconds
239
- ###
240
- ### @return [void]
241
- ###
242
- def timeout= (timeout)
243
- @cnx.options[:timeout] = timeout
244
- end
245
-
246
- ###
247
- ### Reset the open-connection timeout for the rest connection
248
- ###
249
- ### @param timeout[Integer] the new timeout in seconds
250
- ###
251
- ### @return [void]
252
- ###
253
- def open_timeout= (timeout)
254
- @cnx.options[:open_timeout] = timeout
255
- end
256
-
257
-
258
- ###
259
- ### With a REST connection, there isn't any real "connection" to disconnect from
260
- ### So to disconnect, we just unset all our credentials.
261
- ###
262
- ### @return [void]
263
- ###
264
- def disconnect
265
- @jss_user = nil
266
- @rest_url = nil
267
- @server_host = nil
268
- @cnx = nil
269
- @connected = false
270
- end # disconnect
271
-
272
- ###
273
- ### Get an arbitrary JSS resource
274
- ###
275
- ### The first argument is the resource to get (the part of the API url
276
- ### after the 'JSSResource/' )
277
- ###
278
- ### By default we get the data in JSON, and parse it
279
- ### into a ruby data structure (arrays, hashes, strings, etc)
280
- ### with symbolized Hash keys.
281
- ###
282
- ### @param rsrc[String] the resource to get
283
- ### (the part of the API url after the 'JSSResource/' )
284
- ###
285
- ### @param format[Symbol] either ;json or :xml
286
- ### If the second argument is :xml, the XML data is returned as a String.
287
- ###
288
- ### @return [Hash,String] the result of the get
289
- ###
290
- def get_rsrc (rsrc, format = :json)
291
- raise JSS::InvalidConnectionError, "Not Connected. Use JSS::API.connect first." unless @connected
292
- rsrc = URI::encode rsrc
293
- data = @cnx[rsrc].get(:accept => format)
294
- return JSON.parse(data, :symbolize_names => true) if format == :json
295
- data
296
- end
297
-
298
- ###
299
- ### Change an existing JSS resource
300
- ###
301
- ### @param rsrc[String] the API resource being changed, the URL part after 'JSSResource/'
302
- ###
303
- ### @param xml[String] the xml specifying the changes.
304
- ###
305
- ### @return [String] the xml response from the server.
306
- ###
307
- def put_rsrc(rsrc,xml)
308
- raise JSS::InvalidConnectionError, "Not Connected. Use JSS::API.connect first." unless @connected
309
-
310
- ### convert CRs & to &#13;
311
- xml.gsub!(/\r/, '&#13;')
312
-
313
- ### send the data
314
- @cnx[rsrc].put(xml, :content_type => 'text/xml')
315
- end
316
-
317
- ###
318
- ### Create a new JSS resource
319
- ###
320
- ### @param rsrc[String] the API resource being created, the URL part after 'JSSResource/'
321
- ###
322
- ### @param xml[String] the xml specifying the new object.
323
- ###
324
- ### @return [String] the xml response from the server.
325
- ###
326
- def post_rsrc(rsrc,xml)
327
- raise JSS::InvalidConnectionError, "Not Connected. Use JSS::API.connect first." unless @connected
328
-
329
- ### convert CRs & to &#13;
330
- xml.gsub!(/\r/, '&#13;')
331
-
332
- ### send the data
333
- @cnx[rsrc].post xml, :content_type => 'text/xml', :accept => :json
334
- end #post_rsrc
335
-
336
- ### Delete a resource from the JSS
337
- ###
338
- ### @param rsrc[String] the resource to create, the URL part after 'JSSResource/'
339
- ###
340
- ### @return [String] the xml response from the server.
341
- ###
342
- def delete_rsrc(rsrc)
343
- raise JSS::InvalidConnectionError, "Not Connected. Use JSS::API.connect first." unless @connected
344
- raise MissingDataError, "Missing :rsrc" if rsrc.nil?
345
-
346
- ### delete the resource
347
- @cnx[rsrc].delete
348
-
349
- end #delete_rsrc
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
-
390
- ### aliases
391
- alias connected? connected
392
-
393
-
394
- end # class JSSAPIConnection
395
-
396
- ### The single instance of the APIConnection
397
- API = APIConnection.instance
398
-
399
-
400
- end # module