Skip to content

Commit

Permalink
Merge pull request #4159 from terminalmage/issue4153
Browse files Browse the repository at this point in the history
Ensure that parent dir for known_hosts file exists
  • Loading branch information
thatch45 committed Mar 20, 2013
2 parents 3756e9d + fee4340 commit 2b61586
Showing 1 changed file with 49 additions and 50 deletions.
99 changes: 49 additions & 50 deletions salt/modules/ssh.py
Expand Up @@ -34,10 +34,10 @@ def _refine_enc(enc):
if using higher enc. If the type is not found, return ssh-rsa, the ssh
default.
'''
rsa = ['r', 'rsa', 'ssh-rsa']
dss = ['d', 'dsa', 'dss', 'ssh-dss']
rsa = ['r', 'rsa', 'ssh-rsa']
dss = ['d', 'dsa', 'dss', 'ssh-dss']
ecdsa = ['e', 'ecdsa', 'ecdsa-sha2-nistp521', 'ecdsa-sha2-nistp384',
'ecdsa-sha2-nistp256']
'ecdsa-sha2-nistp256']

if enc in rsa:
return 'ssh-rsa'
Expand All @@ -53,11 +53,7 @@ def _refine_enc(enc):
return 'ssh-rsa'


def _format_auth_line(
key,
enc,
comment,
options):
def _format_auth_line(key, enc, comment, options):
'''
Properly format user input.
'''
Expand All @@ -78,11 +74,7 @@ def _replace_auth_key(
'''
Replace an existing key
'''
auth_line = _format_auth_line(
key,
enc,
comment,
options or [])
auth_line = _format_auth_line(key, enc, comment, options or [])

lines = []
uinfo = __salt__['user.info'](user)
Expand Down Expand Up @@ -182,7 +174,7 @@ def _fingerprint(public_key):
except binascii.Error:
return None
ret = hashlib.md5(raw_key).hexdigest()
chunks = [ret[i:i+2] for i in range(0, len(ret), 2)]
chunks = [ret[i:i + 2] for i in range(0, len(ret), 2)]
return ':'.join(chunks)


Expand Down Expand Up @@ -250,12 +242,12 @@ def check_key_file(user, keysource, config='.ssh/authorized_keys', env='base'):
s_keys = _validate_keys(keyfile)
for key in s_keys:
ret[key] = check_key(
user,
key,
s_keys[key]['enc'],
s_keys[key]['comment'],
s_keys[key]['options'],
config)
user,
key,
s_keys[key]['enc'],
s_keys[key]['comment'],
s_keys[key]['options'],
config)
return ret


Expand All @@ -270,11 +262,10 @@ def check_key(user, key, enc, comment, options, config='.ssh/authorized_keys'):
current = auth_keys(user, config)
nline = _format_auth_line(key, enc, comment, options)
if key in current:
cline = _format_auth_line(
key,
current[key]['enc'],
current[key]['comment'],
current[key]['options'])
cline = _format_auth_line(key,
current[key]['enc'],
current[key]['comment'],
current[key]['options'])
if cline != nline:
return 'update'
else:
Expand Down Expand Up @@ -369,13 +360,13 @@ def set_auth_key_from_file(
newkey = _validate_keys(lfile)
for k in newkey:
rval += set_auth_key(
user,
k,
newkey[k]['enc'],
newkey[k]['comment'],
newkey[k]['options'],
config
)
user,
k,
newkey[k]['enc'],
newkey[k]['comment'],
newkey[k]['options'],
config
)
# Due to the ability for a single file to have multiple keys, it's
# possible for a single call to this function to have both "replace" and
# "new" as possible valid returns. I ordered the following as I thought
Expand Down Expand Up @@ -414,22 +405,12 @@ def set_auth_key(
uinfo = __salt__['user.info'](user)
status = check_key(user, key, enc, comment, options, config)
if status == 'update':
_replace_auth_key(
user,
key,
enc,
comment,
options or [],
config)
_replace_auth_key(user, key, enc, comment, options or [], config)
return 'replace'
elif status == 'exists':
return 'no change'
else:
auth_line = _format_auth_line(
key,
enc,
comment,
options)
auth_line = _format_auth_line(key, enc, comment, options)
if not os.path.isdir(uinfo['home']):
return 'fail'
fconfig = os.path.join(uinfo['home'], config)
Expand Down Expand Up @@ -520,7 +501,7 @@ def recv_known_host(user, hostname, enc=None, port=None, hash_hostname=False):


def check_known_host(user, hostname, key=None, fingerprint=None,
config='.ssh/known_hosts'):
config='.ssh/known_hosts'):
'''
Check the record in known_hosts file, either by its value or by fingerprint
(it's enough to set up either key or fingerprint, you don't need to set up
Expand Down Expand Up @@ -567,11 +548,11 @@ def rm_known_host(user, hostname, config='.ssh/known_hosts'):


def set_known_host(user, hostname,
fingerprint=None,
port=None,
enc=None,
hash_hostname=True,
config='.ssh/known_hosts'):
fingerprint=None,
port=None,
enc=None,
hash_hostname=True,
config='.ssh/known_hosts'):
'''
Download SSH public key from remote host "hostname", optionally validate
its fingerprint against "fingerprint" variable and save the record in the
Expand Down Expand Up @@ -614,6 +595,24 @@ def set_known_host(user, hostname,
full = os.path.join(uinfo['home'], config)
line = '{hostname} {enc} {key}\n'.format(**remote_host)

# ensure ~/.ssh exists
ssh_dir = os.path.dirname(full)
try:
log.debug('Ensuring ssh config dir "{0}" exists'.format(ssh_dir))
os.makedirs(ssh_dir)
except OSError as exc:
if exc[1] == 'Permission denied':
log.error('Unable to create directory {0}: '
'{1}'.format(ssh_dir, e[1]))
elif exc[1] == 'File exists':
log.debug('{0} already exists, no need to create '
'it'.format(ssh_dir))
else:
# set proper ownership/permissions
os.chown(ssh_dir, uinfo['uid'], uinfo['gid'])
os.chmod(ssh_dir, 0700)

# write line to known_hosts file
try:
with salt.utils.fopen(full, 'a') as ofile:
ofile.write(line)
Expand Down

0 comments on commit 2b61586

Please sign in to comment.