Revision 3dc66ebc

b/tools/setup-ssh
210 210
    stderr_handler.setLevel(logging.WARNING)
211 211

  
212 212
  root_logger = logging.getLogger("")
213
  root_logger.setLevel(logging.INFO)
213
  root_logger.setLevel(logging.NOTSET)
214 214
  root_logger.addHandler(stderr_handler)
215 215
  root_logger.addHandler(file_handler)
216 216

  
......
221 221
  paramiko_logger.setLevel(logging.WARNING)
222 222

  
223 223

  
224
def main():
225
  """Main routine.
224
def LoadPrivateKeys(options):
225
  """Load the list of available private keys
226 226

  
227
  """
228
  (options, args) = ParseOptions()
227
  It loads the standard ssh key from disk and then tries to connect to
228
  the ssh agent too.
229 229

  
230
  SetupLogging(options)
230
  @rtype: list
231
  @return: a list of C{paramiko.PKey}
231 232

  
233
  """
232 234
  if options.key_type == "rsa":
233 235
    pkclass = paramiko.RSAKey
234 236
  elif options.key_type == "dsa":
......
244 246
    logging.critical("Can't load private key %s: %s", options.private_key, err)
245 247
    sys.exit(1)
246 248

  
249
  try:
250
    agent = paramiko.Agent()
251
    agent_keys = agent.get_keys()
252
  except paramiko.SSHException, err:
253
    # this will only be seen when the agent is broken/uses invalid
254
    # protocol; for non-existing agent, get_keys() will just return an
255
    # empty tuple
256
    logging.warning("Can't connect to the ssh agent: %s; skipping its use",
257
                    err)
258
    agent_keys = []
259

  
260
  return [private_key] + list(agent_keys)
261

  
262

  
263
def LoginViaKeys(transport, username, keys):
264
  """Try to login on the given transport via a list of keys.
265

  
266
  @param transport: the transport to use
267
  @param username: the username to login as
268
  @type keys: list
269
  @param keys: list of C{paramiko.PKey} to use for authentication
270
  @rtype: boolean
271
  @return: True or False depending on whether the login was
272
      successfull or not
273

  
274
  """
275
  for private_key in keys:
276
    try:
277
      transport.auth_publickey(username, private_key)
278
      fpr = ":".join("%02x" % ord(i) for i in private_key.get_fingerprint())
279
      if isinstance(private_key, paramiko.AgentKey):
280
        logging.debug("Authentication via the ssh-agent key %s", fpr)
281
      else:
282
        logging.debug("Authenticated via public key %s", fpr)
283
      return True
284
    except paramiko.SSHException:
285
      continue
286
  else:
287
    # all keys exhausted
288
    return False
289

  
290

  
291
def main():
292
  """Main routine.
293

  
294
  """
295
  (options, args) = ParseOptions()
296

  
297
  SetupLogging(options)
298

  
299
  all_keys = LoadPrivateKeys(options)
300

  
247 301
  passwd = None
248 302
  username = constants.GANETI_RUNAS
249 303
  ssh_port = netutils.GetDaemonPort("ssh")
......
261 315
    transport = paramiko.Transport((host, ssh_port))
262 316
    transport.start_client()
263 317
    try:
264
      try:
265
        transport.auth_publickey(username, private_key)
318
      if LoginViaKeys(transport, username, all_keys):
266 319
        logging.info("Authenticated to %s via public key", host)
267
      except paramiko.SSHException:
320
      else:
268 321
        logging.warning("Authentication to %s via public key failed, trying"
269 322
                        " password", host)
270 323
        if passwd is None:

Also available in: Unified diff