Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue #38366 salt-ssh support private key's passphrase #47238

Merged
merged 13 commits into from
Jun 4, 2018
6 changes: 6 additions & 0 deletions salt/client/ssh/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ def __init__(self, opts):
salt.config.DEFAULT_MASTER_OPTS['ssh_passwd']
),
'priv': priv,
'priv_passwd': self.opts.get(
'ssh_priv_passwd',
salt.config.DEFAULT_MASTER_OPTS['ssh_priv_passwd']
),
'timeout': self.opts.get(
'ssh_timeout',
salt.config.DEFAULT_MASTER_OPTS['ssh_timeout']
Expand Down Expand Up @@ -821,6 +825,7 @@ def __init__(
port=None,
passwd=None,
priv=None,
priv_passwd=None,
timeout=30,
sudo=False,
tty=False,
Expand Down Expand Up @@ -882,6 +887,7 @@ def __init__(
'port': port,
'passwd': passwd,
'priv': priv,
'priv_pass': priv_passwd,
'timeout': timeout,
'sudo': sudo,
'tty': tty,
Expand Down
8 changes: 8 additions & 0 deletions salt/client/ssh/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

SSH_PASSWORD_PROMPT_RE = re.compile(r'(?:.*)[Pp]assword(?: for .*)?:', re.M)
KEY_VALID_RE = re.compile(r'.*\(yes\/no\).*')
SSH_PRIVATE_KEY_PASSWORD_PROMPT_RE = re.compile(r'Enter passphrase for key', re.M)

# Keep these in sync with ./__init__.py
RSTR = '_edbc7885e4f9aac9b83b35999b68d015148caf467b78fa39c05f669c0ff89878'
Expand Down Expand Up @@ -76,6 +77,7 @@ def __init__(
port=None,
passwd=None,
priv=None,
priv_passwd=None,
timeout=None,
sudo=False,
tty=False,
Expand All @@ -92,6 +94,7 @@ def __init__(
self.port = port
self.passwd = six.text_type(passwd) if passwd else passwd
self.priv = priv
self.priv_passwd = priv_passwd
self.timeout = timeout
self.sudo = sudo
self.tty = tty
Expand Down Expand Up @@ -399,6 +402,11 @@ def _run_cmd(self, cmd, key_accept=False, passwd_retries=3):
if buff and RSTR_RE.search(buff):
# We're getting results back, don't try to send passwords
send_password = False
if buff and SSH_PRIVATE_KEY_PASSWORD_PROMPT_RE.search(buff):
if not self.priv_passwd:
return '', 'Private key file need passphrase', 254
term.sendline(self.priv_passwd)
continue
if buff and SSH_PASSWORD_PROMPT_RE.search(buff) and send_password:
if not self.passwd:
return '', 'Permission denied, no authentication information', 254
Expand Down
1 change: 1 addition & 0 deletions salt/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1764,6 +1764,7 @@ def _gather_buffer_space():
'syndic_jid_forward_cache_hwm': 100,
'regen_thin': False,
'ssh_passwd': '',
'ssh_priv_passwd': '',
'ssh_port': '22',
'ssh_sudo': False,
'ssh_sudo_user': '',
Expand Down
3 changes: 3 additions & 0 deletions salt/config/schemas/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class RosterEntryConfig(Schema):
priv = StringItem(title='Private Key',
description='File path to ssh private key, defaults to salt-ssh.rsa',
min_length=1)
priv_passwd = StringItem(title='Private Key passphrase',
description='Passphrase for private key file',
min_length=1)
passwd_or_priv_requirement = AnyOfItem(items=(RequirementsItem(requirements=['passwd']),
RequirementsItem(requirements=['priv'])))(flatten=True)
sudo = BooleanItem(title='Sudo',
Expand Down
6 changes: 6 additions & 0 deletions salt/utils/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3023,6 +3023,12 @@ def _mixin_setup(self):
dest='ssh_priv',
help='Ssh private key file.'
)
auth_group.add_option(
'--priv-passwd',
dest='ssh_priv_passwd',
default='',
help='Passphrase for ssh private key file.'
)
auth_group.add_option(
'-i',
'--ignore-host-keys',
Expand Down