mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Add fingerpint_hash_type option to ssh_auth state and related functions
In PR #40543, the fingerprint_hash_type option was added to the state function in salt/states/ssh_known_hosts.py, as well as the function in the ssh execution module that the ssh_known_hosts states called out to. This caused issue #40878 because the fingerprint_hash_type state setting was not added to the salt/states/ssh_auth.py file. This PR adds this setting to the ssh_auth file, as well as the functions that are used in the ssh execution module. This allows the user to set the fingerprint_hash_type option so avoid the warnings about the default changing. Fixes #40878
This commit is contained in:
parent
2c681887d3
commit
48ff5d2a62
@ -169,7 +169,7 @@ def _replace_auth_key(
|
||||
)
|
||||
|
||||
|
||||
def _validate_keys(key_file):
|
||||
def _validate_keys(key_file, fingerprint_hash_type):
|
||||
'''
|
||||
Return a dict containing validated keys in the passed file
|
||||
'''
|
||||
@ -205,7 +205,7 @@ def _validate_keys(key_file):
|
||||
enc = comps[0]
|
||||
key = comps[1]
|
||||
comment = ' '.join(comps[2:])
|
||||
fingerprint = _fingerprint(key)
|
||||
fingerprint = _fingerprint(key, fingerprint_hash_type)
|
||||
if fingerprint is None:
|
||||
continue
|
||||
|
||||
@ -221,7 +221,7 @@ def _validate_keys(key_file):
|
||||
return ret
|
||||
|
||||
|
||||
def _fingerprint(public_key, fingerprint_hash_type=None):
|
||||
def _fingerprint(public_key, fingerprint_hash_type):
|
||||
'''
|
||||
Return a public key fingerprint based on its base64-encoded representation
|
||||
|
||||
@ -352,7 +352,9 @@ def host_keys(keydir=None, private=True):
|
||||
return keys
|
||||
|
||||
|
||||
def auth_keys(user=None, config='.ssh/authorized_keys'):
|
||||
def auth_keys(user=None,
|
||||
config='.ssh/authorized_keys',
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Return the authorized keys for users
|
||||
|
||||
@ -382,7 +384,7 @@ def auth_keys(user=None, config='.ssh/authorized_keys'):
|
||||
pass
|
||||
|
||||
if full and os.path.isfile(full):
|
||||
keys[u] = _validate_keys(full)
|
||||
keys[u] = _validate_keys(full, fingerprint_hash_type)
|
||||
|
||||
if old_output_when_one_user:
|
||||
if user[0] in keys:
|
||||
@ -396,7 +398,8 @@ def auth_keys(user=None, config='.ssh/authorized_keys'):
|
||||
def check_key_file(user,
|
||||
source,
|
||||
config='.ssh/authorized_keys',
|
||||
saltenv='base'):
|
||||
saltenv='base',
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Check a keyfile from a source destination against the local keys and
|
||||
return the keys to change
|
||||
@ -410,7 +413,7 @@ def check_key_file(user,
|
||||
keyfile = __salt__['cp.cache_file'](source, saltenv)
|
||||
if not keyfile:
|
||||
return {}
|
||||
s_keys = _validate_keys(keyfile)
|
||||
s_keys = _validate_keys(keyfile, fingerprint_hash_type)
|
||||
if not s_keys:
|
||||
err = 'No keys detected in {0}. Is file properly ' \
|
||||
'formatted?'.format(source)
|
||||
@ -426,12 +429,19 @@ def check_key_file(user,
|
||||
s_keys[key]['enc'],
|
||||
s_keys[key]['comment'],
|
||||
s_keys[key]['options'],
|
||||
config)
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
return ret
|
||||
|
||||
|
||||
def check_key(user, key, enc, comment, options, config='.ssh/authorized_keys',
|
||||
cache_keys=None):
|
||||
def check_key(user,
|
||||
key,
|
||||
enc,
|
||||
comment,
|
||||
options,
|
||||
config='.ssh/authorized_keys',
|
||||
cache_keys=None,
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Check to see if a key needs updating, returns "update", "add" or "exists"
|
||||
|
||||
@ -444,7 +454,9 @@ def check_key(user, key, enc, comment, options, config='.ssh/authorized_keys',
|
||||
if cache_keys is None:
|
||||
cache_keys = []
|
||||
enc = _refine_enc(enc)
|
||||
current = auth_keys(user, config)
|
||||
current = auth_keys(user,
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
nline = _format_auth_line(key, enc, comment, options)
|
||||
|
||||
# Removing existing keys from the auth_keys isn't really a good idea
|
||||
@ -473,9 +485,10 @@ def check_key(user, key, enc, comment, options, config='.ssh/authorized_keys',
|
||||
|
||||
|
||||
def rm_auth_key_from_file(user,
|
||||
source,
|
||||
config='.ssh/authorized_keys',
|
||||
saltenv='base'):
|
||||
source,
|
||||
config='.ssh/authorized_keys',
|
||||
saltenv='base',
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Remove an authorized key from the specified user's authorized key file,
|
||||
using a file as source
|
||||
@ -492,7 +505,7 @@ def rm_auth_key_from_file(user,
|
||||
'Failed to pull key file from salt file server'
|
||||
)
|
||||
|
||||
s_keys = _validate_keys(lfile)
|
||||
s_keys = _validate_keys(lfile, fingerprint_hash_type)
|
||||
if not s_keys:
|
||||
err = (
|
||||
'No keys detected in {0}. Is file properly formatted?'.format(
|
||||
@ -508,7 +521,8 @@ def rm_auth_key_from_file(user,
|
||||
rval += rm_auth_key(
|
||||
user,
|
||||
key,
|
||||
config
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type
|
||||
)
|
||||
# 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"
|
||||
@ -522,7 +536,10 @@ def rm_auth_key_from_file(user,
|
||||
return 'Key not present'
|
||||
|
||||
|
||||
def rm_auth_key(user, key, config='.ssh/authorized_keys'):
|
||||
def rm_auth_key(user,
|
||||
key,
|
||||
config='.ssh/authorized_keys',
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Remove an authorized key from the specified user's authorized key file
|
||||
|
||||
@ -532,7 +549,9 @@ def rm_auth_key(user, key, config='.ssh/authorized_keys'):
|
||||
|
||||
salt '*' ssh.rm_auth_key <user> <key>
|
||||
'''
|
||||
current = auth_keys(user, config)
|
||||
current = auth_keys(user,
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
linere = re.compile(r'^(.*?)\s?((?:ssh\-|ecds)[\w-]+\s.+)$')
|
||||
if key in current:
|
||||
# Remove the key
|
||||
@ -590,7 +609,8 @@ def rm_auth_key(user, key, config='.ssh/authorized_keys'):
|
||||
def set_auth_key_from_file(user,
|
||||
source,
|
||||
config='.ssh/authorized_keys',
|
||||
saltenv='base'):
|
||||
saltenv='base',
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Add a key to the authorized_keys file, using a file as the source.
|
||||
|
||||
@ -607,7 +627,7 @@ def set_auth_key_from_file(user,
|
||||
'Failed to pull key file from salt file server'
|
||||
)
|
||||
|
||||
s_keys = _validate_keys(lfile)
|
||||
s_keys = _validate_keys(lfile, fingerprint_hash_type)
|
||||
if not s_keys:
|
||||
err = (
|
||||
'No keys detected in {0}. Is file properly formatted?'.format(
|
||||
@ -623,11 +643,12 @@ def set_auth_key_from_file(user,
|
||||
rval += set_auth_key(
|
||||
user,
|
||||
key,
|
||||
s_keys[key]['enc'],
|
||||
s_keys[key]['comment'],
|
||||
s_keys[key]['options'],
|
||||
config,
|
||||
list(s_keys.keys())
|
||||
enc=s_keys[key]['enc'],
|
||||
comment=s_keys[key]['comment'],
|
||||
options=s_keys[key]['options'],
|
||||
config=config,
|
||||
cache_keys=list(s_keys.keys()),
|
||||
fingerprint_hash_type=fingerprint_hash_type
|
||||
)
|
||||
# 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"
|
||||
@ -650,7 +671,8 @@ def set_auth_key(
|
||||
comment='',
|
||||
options=None,
|
||||
config='.ssh/authorized_keys',
|
||||
cache_keys=None):
|
||||
cache_keys=None,
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Add a key to the authorized_keys file. The "key" parameter must only be the
|
||||
string of text that is the encoded key. If the key begins with "ssh-rsa"
|
||||
@ -677,11 +699,18 @@ def set_auth_key(
|
||||
# the same filtering done when reading the authorized_keys file. Apply
|
||||
# the same check to ensure we don't insert anything that will not
|
||||
# subsequently be read)
|
||||
key_is_valid = _fingerprint(key) is not None
|
||||
key_is_valid = _fingerprint(key, fingerprint_hash_type) is not None
|
||||
if not key_is_valid:
|
||||
return 'Invalid public key'
|
||||
|
||||
status = check_key(user, key, enc, comment, options, config, cache_keys)
|
||||
status = check_key(user,
|
||||
key,
|
||||
enc,
|
||||
comment,
|
||||
options,
|
||||
config=config,
|
||||
cache_keys=cache_keys,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
if status == 'update':
|
||||
_replace_auth_key(user, key, enc, comment, options or [], config)
|
||||
return 'replace'
|
||||
|
@ -55,7 +55,7 @@ import sys
|
||||
import salt.ext.six as six
|
||||
|
||||
|
||||
def _present_test(user, name, enc, comment, options, source, config):
|
||||
def _present_test(user, name, enc, comment, options, source, config, fingerprint_hash_type):
|
||||
'''
|
||||
Run checks for "present"
|
||||
'''
|
||||
@ -65,7 +65,8 @@ def _present_test(user, name, enc, comment, options, source, config):
|
||||
user,
|
||||
source,
|
||||
config,
|
||||
saltenv=__env__)
|
||||
saltenv=__env__,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
if keys:
|
||||
comment = ''
|
||||
for key, status in six.iteritems(keys):
|
||||
@ -111,7 +112,8 @@ def _present_test(user, name, enc, comment, options, source, config):
|
||||
enc,
|
||||
comment,
|
||||
options,
|
||||
config)
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
if check == 'update':
|
||||
comment = (
|
||||
'Key {0} for user {1} is set to be updated'
|
||||
@ -128,7 +130,7 @@ def _present_test(user, name, enc, comment, options, source, config):
|
||||
return result, comment
|
||||
|
||||
|
||||
def _absent_test(user, name, enc, comment, options, source, config):
|
||||
def _absent_test(user, name, enc, comment, options, source, config, fingerprint_hash_type):
|
||||
'''
|
||||
Run checks for "absent"
|
||||
'''
|
||||
@ -138,7 +140,8 @@ def _absent_test(user, name, enc, comment, options, source, config):
|
||||
user,
|
||||
source,
|
||||
config,
|
||||
saltenv=__env__)
|
||||
saltenv=__env__,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
if keys:
|
||||
comment = ''
|
||||
for key, status in list(keys.items()):
|
||||
@ -184,7 +187,8 @@ def _absent_test(user, name, enc, comment, options, source, config):
|
||||
enc,
|
||||
comment,
|
||||
options,
|
||||
config)
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
if check == 'update' or check == 'exists':
|
||||
comment = ('Key {0} for user {1} is set for removal').format(name, user)
|
||||
else:
|
||||
@ -202,6 +206,7 @@ def present(
|
||||
source='',
|
||||
options=None,
|
||||
config='.ssh/authorized_keys',
|
||||
fingerprint_hash_type=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Verifies that the specified SSH key is present for the specified user
|
||||
@ -243,6 +248,17 @@ def present(
|
||||
The location of the authorized keys file relative to the user's home
|
||||
directory, defaults to ".ssh/authorized_keys". Token expansion %u and
|
||||
%h for username and home path supported.
|
||||
|
||||
fingerprint_hash_type
|
||||
The public key fingerprint hash type that the public key fingerprint
|
||||
was originally hashed with. This defaults to ``md5`` if not specified.
|
||||
|
||||
.. versionadded:: 2016.11.7
|
||||
|
||||
.. note::
|
||||
|
||||
The default value of the ``fingerprint_hash_type`` will change to
|
||||
``sha256`` in Salt Nitrogen.
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
@ -279,7 +295,7 @@ def present(
|
||||
options or [],
|
||||
source,
|
||||
config,
|
||||
)
|
||||
fingerprint_hash_type)
|
||||
return ret
|
||||
|
||||
# Get only the path to the file without env referrences to check if exists
|
||||
@ -305,10 +321,11 @@ def present(
|
||||
data = __salt__['ssh.set_auth_key_from_file'](
|
||||
user,
|
||||
source,
|
||||
config,
|
||||
saltenv=__env__)
|
||||
config=config,
|
||||
saltenv=__env__,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
else:
|
||||
# Split keyline to get key und commen
|
||||
# Split keyline to get key und comment
|
||||
keyline = keyline.split(' ')
|
||||
key_type = keyline[0]
|
||||
key_value = keyline[1]
|
||||
@ -316,18 +333,20 @@ def present(
|
||||
data = __salt__['ssh.set_auth_key'](
|
||||
user,
|
||||
key_value,
|
||||
key_type,
|
||||
key_comment,
|
||||
options or [],
|
||||
config)
|
||||
enc=key_type,
|
||||
comment=key_comment,
|
||||
options=options or [],
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
else:
|
||||
data = __salt__['ssh.set_auth_key'](
|
||||
user,
|
||||
name,
|
||||
enc,
|
||||
comment,
|
||||
options or [],
|
||||
config)
|
||||
enc=enc,
|
||||
comment=comment,
|
||||
options=options or [],
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
|
||||
if data == 'replace':
|
||||
ret['changes'][name] = 'Updated'
|
||||
@ -369,7 +388,8 @@ def absent(name,
|
||||
comment='',
|
||||
source='',
|
||||
options=None,
|
||||
config='.ssh/authorized_keys'):
|
||||
config='.ssh/authorized_keys',
|
||||
fingerprint_hash_type=None):
|
||||
'''
|
||||
Verifies that the specified SSH key is absent
|
||||
|
||||
@ -401,6 +421,17 @@ def absent(name,
|
||||
directory, defaults to ".ssh/authorized_keys". Token expansion %u and
|
||||
%h for username and home path supported.
|
||||
|
||||
fingerprint_hash_type
|
||||
The public key fingerprint hash type that the public key fingerprint
|
||||
was originally hashed with. This defaults to ``md5`` if not specified.
|
||||
|
||||
.. versionadded:: 2016.11.7
|
||||
|
||||
.. note::
|
||||
|
||||
The default value of the ``fingerprint_hash_type`` will change to
|
||||
``sha256`` in Salt Nitrogen.
|
||||
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
@ -416,7 +447,7 @@ def absent(name,
|
||||
options or [],
|
||||
source,
|
||||
config,
|
||||
)
|
||||
fingerprint_hash_type)
|
||||
return ret
|
||||
|
||||
# Extract Key from file if source is present
|
||||
@ -434,13 +465,15 @@ def absent(name,
|
||||
ret['comment'] = __salt__['ssh.rm_auth_key_from_file'](user,
|
||||
source,
|
||||
config,
|
||||
saltenv=__env__)
|
||||
saltenv=__env__,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
else:
|
||||
# Split keyline to get key
|
||||
keyline = keyline.split(' ')
|
||||
ret['comment'] = __salt__['ssh.rm_auth_key'](user,
|
||||
keyline[1],
|
||||
config)
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
else:
|
||||
# Get just the key
|
||||
sshre = re.compile(r'^(.*?)\s?((?:ssh\-|ecds)[\w-]+\s.+)$')
|
||||
@ -461,7 +494,10 @@ def absent(name,
|
||||
name = comps[1]
|
||||
if len(comps) == 3:
|
||||
comment = comps[2]
|
||||
ret['comment'] = __salt__['ssh.rm_auth_key'](user, name, config)
|
||||
ret['comment'] = __salt__['ssh.rm_auth_key'](user,
|
||||
name,
|
||||
config=config,
|
||||
fingerprint_hash_type=fingerprint_hash_type)
|
||||
|
||||
if ret['comment'] == 'User authorized keys file not present':
|
||||
ret['result'] = False
|
||||
|
Loading…
Reference in New Issue
Block a user