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