|
- from __future__ import absolute_import
-
- # Import python libs
- import logging
- import os
-
- try:
- import paramiko
- HAS_PARAMIKO = True
- except:
- HAS_PARAMIKO = False
-
- # Import Salt libs
- import salt.config
- import salt.wheel
-
- LOG = logging.getLogger(__name__)
-
-
- def __virtual__():
- '''
- Only load if paramiko library exist.
- '''
- if not HAS_PARAMIKO:
- return (
- False,
- 'Can not load module saltkey: paramiko library not found')
- return True
-
-
- def key_create(id_, host, force=False):
- '''
- Generates minion keypair, accepts it on master and injects it to minion via SSH.
-
- :param id_: expected minion ID of target node
- :param host: IP address or resolvable hostname/FQDN of target node
-
- CLI Examples:
-
- .. code-block:: bash
-
- salt-call saltkey.key_create <MINION_ID> <MINION_IP_ADDRESS> force=False
- '''
- ret = {
- 'retcode': 0,
- 'msg': 'Salt Key for minion %s is already accepted' % id_,
- }
-
- opts = salt.config.master_config('/etc/salt/master')
- wheel = salt.wheel.WheelClient(opts)
- keys = wheel.cmd('key.gen_accept', arg=[id_], kwarg={'force': force})
- pub_key = keys.get('pub', None)
- priv_key = keys.get('priv', None)
-
- if pub_key and priv_key:
- ssh = paramiko.SSHClient()
- ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Establish SSH connection to minion
- try:
- ssh.connect(host)
- except paramiko.ssh_exception.AuthenticationException:
- msg = ('Could not establish SSH connection to minion "%s" on address %s, please ensure '
- 'that current user\'s SSH key is present in minions authorized_keys.') % (id_, host)
- LOG.error(msg)
- ret['retcode'] = 1
- ret['msg'] = msg
- wheel.cmd_async({'fun': 'key.delete', 'match': id_})
- return ret
- except Exception as e:
- msg = ('Unknown error occured while establishing SSH connection '
- 'to minion "%s" on address %s: %s') % (id_, host, repr(e))
- LOG.error(msg)
- ret['retcode'] = 1
- ret['msg'] = msg
- wheel.cmd_async({'fun': 'key.delete', 'match': id_})
- return ret
- # Setup the keys on minion side the ugly way, nice one didn't work
- key_path = '/etc/salt/pki/minion'
- command = ('echo "%(pub_key)s" > %(pub_path)s && chmod 644 %(pub_path)s && '
- 'echo "%(priv_key)s" > %(priv_path)s && chmod 400 %(priv_path)s && '
- 'salt-call --local service.restart salt-minion') % {
- 'pub_path': os.path.join(key_path, 'minion.pub'),
- 'pub_key': pub_key,
- 'priv_path': os.path.join(key_path, 'minion.pem'),
- 'priv_key': priv_key
- }
-
- ssh_chan = ssh.get_transport().open_session()
- ssh_chan.exec_command(command)
- # Wait for command return
- while True:
- if ssh_chan.exit_status_ready():
- exit_status = ssh_chan.recv_exit_status()
- stderr = ssh_chan.recv_stderr(1000)
- stdout = ssh_chan.recv(1000)
- break
- ssh.close()
- # Evaluate SSH command exit status
- if exit_status != 0:
- msg = 'Keypair injection to Salt minion failed on target with following error: %s' % stderr
- LOG.error(msg)
- ret['retcode'] = exit_status
- ret['msg'] = msg
- return ret
-
- ret['msg'] = 'Salt Key successfully created'
-
- return ret
|