class Jamf::DBConnection
A mysql connection to the JSS
database.
This is a singleton class, only one can exist at a time, and it is created, but not connected, automatically when the module loads.
Use it via the Jamf::DB_CNX constant (for connection metadata) and the Jamf::DB_CNX.db attribute (which contains the actual mysql query interface) for making queries
Direct MySQL access is minimal and discouraged, since it bypasses the API, and can be very dangerous. However, it’s necessary to overcome some limitations of the API or to access custom tables.
While a database connction isn’t required for most things, warnings will be sent to stderr when functionality is limited due to a lack of a database connection i.e. when Jamf::DB_CNX.connected? == false
To make a connection with credentials, just call the connect
method thus:
Jamf::DB_CNX.connect :server => 'server.company.com', :user => "user", :pw => "pw"
Other options include:
:db_name => which database to connect to, defaults to 'jamfsoftware' :port => tcp port for connection to server, defaults to the standard mysql port. :connect_timeout => seconds to wait before giving up on connection, defaults to 120 :read_timeout => seconds to wait before giving up on recieving data, defaults to 120 :write_timeout => seconds to wait before giving up on sending data, defaults to 120 :timeout => sets all three timeouts to the same value, defaults to 120
Calling Jamf::DB_CNX.connect again will re-use any values not provided. but will create a new connection.
Constants
- DEFAULT_DB_NAME
The name of the
JSS
database on the mysql server- DFT_CHARSET
The default encoding in the tables - JAMF wisely uses UTF-8
- DFT_PORT
the default MySQL port
- DFT_SOCKET
- DFT_TIMEOUT
give the connection a 60 second timeout, for really slow net connections (like… from airplanes)
- SQL_DATE_FORMAT
the strftime format for reading/writing dates in the db
Attributes
Public Class Methods
# File lib/jamf/db_connection.rb 99 def initialize 100 @mysql = Mysql.init 101 @connected = false 102 end
Public Instance Methods
Connect to the JSS
MySQL database.
@param args the keyed arguments for connection.
@option args :server Required, the hostname of the JSS
API server
@option args :port the port number to connect with, defaults to the default Mysql TCP port
@option args :socket when the server is ‘localhost’, the path to the connection socket.
@option args :db_name the name of the database to use, defaults to ‘jamfsoftware’
@option args :user Required, the mysql user to connect as
@option args :pw Required, the password for that user, or :prompt, or :stdin
If :prompt, the user is promted on the commandline to enter the password for the :user. If :stdin#, the password is read from a line of std in represented by the digit at #, so :stdin3 reads the passwd from the third line of standard input. defaults to line 2, if no digit is supplied. see {JSS.stdin}
@option args :connect_timeout the number of seconds to wait for an initial response, defaults to 120
@option args :read_timeout the number of seconds before read-request times out, defaults to 120
@option args :write_timeout the number of seconds before write-request times out, defaults to 120
@option args :timeout used for any of the timeouts that aren’t explicitly set.
@return [true] the connection was successfully made.
# File lib/jamf/db_connection.rb 135 def connect(**args) 136 begin 137 disconnect if @connected 138 rescue Mysql::ClientError::ServerGoneError 139 @connected = false 140 end 141 142 # server might come frome several places 143 # if not given in the args, use #hostname to figure out 144 # which 145 @server = args[:server] ? args[:server] : hostname 146 147 # settings from config if they aren't in the args 148 args[:port] ||= Jamf.config.db_server_port ? Jamf.config.db_server_port : Mysql::MYSQL_TCP_PORT 149 args[:socket] ||= Jamf.config.db_server_socket ? Jamf.config.db_server_socket : DFT_SOCKET 150 args[:db_name] ||= Jamf.config.db_name ? Jamf.config.db_name : DEFAULT_DB_NAME 151 args[:user] ||= Jamf.config.db_username 152 args[:connect_timeout] ||= Jamf.config.db_connect_timeout 153 args[:read_timeout] ||= Jamf.config.db_read_timeout 154 args[:write_timeout] ||= Jamf.config.db_write_timeout 155 args[:charset] ||= DFT_CHARSET 156 157 ### if one timeout was given, use it for all three 158 args[:connect_timeout] ||= args[:timeout] ? args[:timeout] : DFT_TIMEOUT 159 args[:read_timeout] ||= args[:timeout] ? args[:timeout] : DFT_TIMEOUT 160 args[:write_timeout] ||= args[:timeout] ? args[:timeout] : DFT_TIMEOUT 161 162 @port = args[:port] 163 @socket = args[:socket] 164 @mysql_name = args[:db_name] 165 @user = args[:user] 166 @connect_timeout = args[:connect_timeout] 167 @read_timeout = args[:read_timeout] 168 @write_timeout = args[:write_timeout] 169 170 # make sure we have a user, pw, server 171 raise Jamf::MissingDataError, 'No MySQL user specified, or defined in configuration.' unless args[:user] 172 raise Jamf::MissingDataError, "Missing :pw (or :prompt/:stdin) for user '#{@user}'" unless args[:pw] 173 raise Jamf::MissingDataError, 'No MySQL Server hostname specified, or listed in configuration.' unless @server 174 175 @pw = if args[:pw] == :prompt 176 JSS.prompt_for_password "Enter the password for the MySQL user #{@user}@#{@server}:" 177 elsif args[:pw].is_a?(Symbol) && args[:pw].to_s.start_with?('stdin') 178 args[:pw].to_s =~ /^stdin(\d+)$/ 179 line = Regexp.last_match(1) 180 line ||= 2 181 JSS.stdin line 182 else 183 args[:pw] 184 end 185 186 @mysql = Mysql.init 187 188 @mysql.options Mysql::OPT_CONNECT_TIMEOUT, @connect_timeout 189 @mysql.options Mysql::OPT_READ_TIMEOUT, @read_timeout 190 @mysql.options Mysql::OPT_WRITE_TIMEOUT, @write_timeout 191 @mysql.charset = args[:charset] 192 @mysql.connect @server, @user, @pw, @mysql_name, @port, @socket 193 194 @connected = true 195 196 @server 197 rescue Mysql::ServerError::NotSupportedAuthMode => e 198 raise Mysql::ServerError::AccessDeniedError, "Probable unknown MySQL user '#{@user}'. Original error was 'Mysql::ServerError::NotSupportedAuthMode: #{e}' which is sometimes raised when the user does not exist on the server." 199 end
@return [Mysql] The mysql database connection itself
# File lib/jamf/db_connection.rb 204 def db 205 raise Jamf::InvalidConnectionError, 'No database connection. Please use Jamf::DB_CNX.connect' unless Jamf::DB_CNX.connected? 206 @mysql 207 end
close the connection to the database it’ll have to be re-connected before using again
# File lib/jamf/db_connection.rb 213 def disconnect 214 @mysql.close! if @mysql.protocol 215 @server = nil 216 @port = nil 217 @socket = nil 218 @user = nil 219 @connection_timeout = DFT_TIMEOUT 220 @read_timeout = DFT_TIMEOUT 221 @write_timeout = DFT_TIMEOUT 222 @connected = false 223 nil 224 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
# File lib/jamf/db_connection.rb 263 def hostname 264 # return it if already set 265 return @server if @server 266 # otherwise, from the config 267 srvr = Jamf.config.db_server_name 268 # otherwise, assume its on the JSS server to which this client talks 269 srvr ||= Jamf::Client.jss_server 270 srvr 271 end
Test that a given hostname is a MySQL server
@param server The hostname to test
@return [Boolean] does the server host a MySQL server?
# File lib/jamf/db_connection.rb 232 def valid_server?(server, port = DFT_PORT) 233 mysql = Mysql.init 234 mysql.options Mysql::OPT_CONNECT_TIMEOUT, 60 235 mysql.charset = DFT_CHARSET 236 237 begin 238 # this connection should get an access denied error if there is 239 # a mysql server there. I'm assuming no one will use this username 240 # and pw for anything real 241 # Also with newer versions of mysql, a Mysql instance that has 242 # never authenticated will raise Mysql::ServerError::NotSupportedAuthMode 243 # rather than Mysql::ServerError::AccessDeniedError, until a 244 # successful connection is made. After that, re-connecting will 245 # raise AccessDeniedError when credentials are invalid. 246 247 mysql.connect server, 'notArealUser', "definatelyNotA#{$PROCESS_ID}password", 'not_a_db', port 248 249 rescue Mysql::ServerError::AccessDeniedError, Mysql::ServerError::NotSupportedAuthMode 250 return true 251 rescue 252 return false 253 end 254 false 255 end