New version of salt-formula from Saltstack
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.5KB

  1. from __future__ import absolute_import
  2. # Import python libs
  3. import logging
  4. import os
  5. try:
  6. import paramiko
  7. HAS_PARAMIKO = True
  8. except:
  9. HAS_PARAMIKO = False
  10. # Import Salt libs
  11. import salt.config
  12. import salt.wheel
  13. LOG = logging.getLogger(__name__)
  14. def __virtual__():
  15. '''
  16. Only load if paramiko library exist.
  17. '''
  18. if not HAS_PARAMIKO:
  19. return (
  20. False,
  21. 'Can not load module saltkey: paramiko library not found')
  22. return True
  23. def key_create(id_, host, force=False):
  24. '''
  25. Generates minion keypair, accepts it on master and injects it to minion via SSH.
  26. :param id_: expected minion ID of target node
  27. :param host: IP address or resolvable hostname/FQDN of target node
  28. CLI Examples:
  29. .. code-block:: bash
  30. salt-call saltkey.key_create <MINION_ID> <MINION_IP_ADDRESS> force=False
  31. '''
  32. ret = {
  33. 'retcode': 0,
  34. 'msg': 'Salt Key for minion %s is already accepted' % id_,
  35. }
  36. opts = salt.config.master_config('/etc/salt/master')
  37. wheel = salt.wheel.WheelClient(opts)
  38. keys = wheel.cmd('key.gen_accept', arg=[id_], kwarg={'force': force})
  39. pub_key = keys.get('pub', None)
  40. priv_key = keys.get('priv', None)
  41. if pub_key and priv_key:
  42. ssh = paramiko.SSHClient()
  43. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  44. # Establish SSH connection to minion
  45. try:
  46. ssh.connect(host)
  47. except paramiko.ssh_exception.AuthenticationException:
  48. msg = ('Could not establish SSH connection to minion "%s" on address %s, please ensure '
  49. 'that current user\'s SSH key is present in minions authorized_keys.') % (id_, host)
  50. LOG.error(msg)
  51. ret['retcode'] = 1
  52. ret['msg'] = msg
  53. wheel.cmd_async({'fun': 'key.delete', 'match': id_})
  54. return ret
  55. except Exception as e:
  56. msg = ('Unknown error occured while establishing SSH connection '
  57. 'to minion "%s" on address %s: %s') % (id_, host, repr(e))
  58. LOG.error(msg)
  59. ret['retcode'] = 1
  60. ret['msg'] = msg
  61. wheel.cmd_async({'fun': 'key.delete', 'match': id_})
  62. return ret
  63. # Setup the keys on minion side the ugly way, nice one didn't work
  64. key_path = '/etc/salt/pki/minion'
  65. command = ('echo "%(pub_key)s" > %(pub_path)s && chmod 644 %(pub_path)s && '
  66. 'echo "%(priv_key)s" > %(priv_path)s && chmod 400 %(priv_path)s && '
  67. 'salt-call --local service.restart salt-minion') % {
  68. 'pub_path': os.path.join(key_path, 'minion.pub'),
  69. 'pub_key': pub_key,
  70. 'priv_path': os.path.join(key_path, 'minion.pem'),
  71. 'priv_key': priv_key
  72. }
  73. ssh_chan = ssh.get_transport().open_session()
  74. ssh_chan.exec_command(command)
  75. # Wait for command return
  76. while True:
  77. if ssh_chan.exit_status_ready():
  78. exit_status = ssh_chan.recv_exit_status()
  79. stderr = ssh_chan.recv_stderr(1000)
  80. stdout = ssh_chan.recv(1000)
  81. break
  82. ssh.close()
  83. # Evaluate SSH command exit status
  84. if exit_status != 0:
  85. msg = 'Keypair injection to Salt minion failed on target with following error: %s' % stderr
  86. LOG.error(msg)
  87. ret['retcode'] = exit_status
  88. ret['msg'] = msg
  89. return ret
  90. ret['msg'] = 'Salt Key successfully created'
  91. return ret