lib/jss-api/api_connection.rb in jss-api-0.5.8 vs lib/jss-api/api_connection.rb in jss-api-0.6.1

- old
+ new

@@ -1,6 +1,6 @@ -### Copyright 2014 Pixar +### Copyright 2016 Pixar ### ### Licensed under the Apache License, Version 2.0 (the "Apache License") ### with the following modification; you may not use this file except in ### compliance with the Apache License and the following modification to it: ### Section 6. Trademarks. is deleted and replaced with: @@ -61,12 +61,20 @@ ##################################### ### Class Constants ##################################### ### The base API path in the jss URL - RSRC = "JSSResource" - + RSRC_BASE = "JSSResource" + + ### A url path to load to see if there's an API available at a host. + ### This just loads the API resource docs page + TEST_PATH = "api" + + ### If the test path loads correctly from a casper server, it'll contain + ### this text + TEST_CONTENT = "<title>JSS REST API Resource Documentation</title>" + ### The Default port HTTP_PORT = 9006 ### The SSL port SSL_PORT = 8443 @@ -95,10 +103,13 @@ attr_reader :connected ### @return [JSS::Server] the details of the JSS to which we're connected. attr_reader :server + ### @return [String] the hostname of the JSS to which we're connected. + attr_reader :server_host + ##################################### ### Constructor ##################################### ### @@ -120,10 +131,12 @@ ### ### @option args :server[String] the hostname of the JSS API server, required if not defined in JSS::CONFIG ### ### @option args :port[Integer] the port number to connect with, defaults to 8443 ### + ### @option args :use_ssl[Boolean] should the connection be made over SSL? Defaults to true. + ### ### @option args :verify_cert[Boolean] should HTTPS SSL certificates be verified. Defaults to true. ### If your connection raises RestClient::SSLCertificateNotVerified, and you don't care about the ### validity of the SSL cert. just set this explicitly to false. ### ### @option args :user[String] a JSS user who has API privs, required if not defined in JSS::CONFIG @@ -139,11 +152,15 @@ ### @option args :timeout[Integer] the number of seconds before an API call times out, defaults to 60 ### ### @return [true] ### def connect (args = {}) - + + # the server, if not specified, might come from a couple places. + # see #hostname + args[:server] ||= hostname + # settings from config if they aren't in the args args[:server] ||= JSS::CONFIG.api_server_name args[:port] ||= JSS::CONFIG.api_server_port args[:user] ||= JSS::CONFIG.api_username args[:timeout] ||= JSS::CONFIG.api_timeout @@ -153,11 +170,14 @@ # if verify cert given was NOT in the args.... if args[:verify_cert].nil? # set it from the prefs args[:verify_cert] = JSS::CONFIG.api_verify_cert end - + + # settings from client jamf plist if needed + args[:port] ||= JSS::Client.jss_port + # default settings if needed args[:port] ||= SSL_PORT args[:timeout] ||= DFT_TIMEOUT args[:open_timeout] ||= DFT_OPEN_TIMEOUT @@ -171,17 +191,22 @@ # must have server, user, and pw raise JSS::MissingDataError, "No JSS :server specified, or in configuration." unless args[:server] raise JSS::MissingDataError, "No JSS :user specified, or in configuration." unless args[:user] raise JSS::MissingDataError, "Missing :pw for user '#{args[:user]}'" unless args[:pw] - # ssl or not? - ssl = SSL_PORT == args[:port].to_i ? "s" : '' - @rest_url = URI::encode "http#{ssl}://#{args[:server]}:#{args[:port]}/#{RSRC}" + # we're using ssl if 1) args[:use_ssl] is anything but false + # or 2) the port is the default casper ssl port. + args[:use_ssl] = (not args[:use_ssl] == false) or (args[:port] == SSL_PORT) + + # and here's the URL + ssl = args[:use_ssl] ? "s" : '' + @rest_url = URI::encode "http#{ssl}://#{args[:server]}:#{args[:port]}/#{RSRC_BASE}" + # prep the args for passing to RestClient::Resource - # if verify_cert is nil (unset) or non-false, then we will verify - args[:verify_ssl] = (args[:verify_cert].nil? or args[:verify_cert]) ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE + # if verify_cert is anything but false, we will verify + args[:verify_ssl] = (args[:verify_cert] == false) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER args[:password] = if args[:pw] == :prompt JSS.prompt_for_password "Enter the password for JSS user #{args[:user]}@#{args[:server]}:" elsif args[:pw].is_a?(Symbol) and args[:pw].to_s.start_with?('stdin') args[:pw].to_s =~ /^stdin(\d+)$/ @@ -190,24 +215,23 @@ JSS.stdin line else args[:pw] end - - # heres our connection @cnx = RestClient::Resource.new("#{@rest_url}", args) @jss_user = args[:user] + @server_host = args[:server] @connected = true @server = JSS::Server.new if @server.version < JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version] raise JSS::UnsupportedError, "Your JSS Server version, #{@server.raw_version}, is to low. Must be #{JSS::MINIMUM_SERVER_VERSION} or higher." end - return true + return @connected ? @server_host : nil end # connect ### ### Reset the response timeout for the rest connection ### @@ -238,10 +262,11 @@ ### @return [void] ### def disconnect @jss_user = nil @rest_url = nil + @server_host = nil @cnx = nil @connected = false end # disconnect ### @@ -306,11 +331,10 @@ ### send the data @cnx[rsrc].post xml, :content_type => 'text/xml', :accept => :json end #post_rsrc - ### ### Delete a resource from the JSS ### ### @param rsrc[String] the resource to create, the URL part after 'JSSResource/' ### ### @return [String] the xml response from the server. @@ -321,10 +345,49 @@ ### delete the resource @cnx[rsrc].delete end #delete_rsrc - + + + ### Test that a given hostname & port is a JSS API server + ### + ### @param server[String] The hostname to test, + ### + ### @param port[Integer] The port to try connecting on + ### + ### @return [Boolean] does the server host a JSS API? + ### + def valid_server? (server, port = SSL_PORT) + # try ssl first + begin + return true if open("https://#{server}:#{port}/#{TEST_PATH}", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read.include? TEST_CONTENT + rescue + # then regular http + begin + return true if open("http://#{server}:#{port}/#{TEST_PATH}").read.include? TEST_CONTENT + rescue + # any errors = no API + return false + end # begin + end #begin + # if we're here, no API + return false + end + + ### The server to which we are connected, or will + ### try connecting to if none is specified with the + ### call to #connect + ### + ### @return [String] the hostname of the server + ### + def hostname + return @server_host if @server_host + srvr = JSS::CONFIG.api_server_name + srvr ||= JSS::Client.jss_server + return srvr + end + ### aliases alias connected? connected end # class JSSAPIConnection