mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 12:50:22 -07:00
ios_user module - implement sshkey option (#38782)
* ios_user module - add sshkey support * ios_user - Add version_added to sshkey option * ios_user - pep8 indentation fixes in unit tests * ios_user - use b64decode method that works on python 2 and 3
This commit is contained in:
parent
0ca61e9d87
commit
7c318d4e30
6 changed files with 141 additions and 7 deletions
|
@ -78,6 +78,11 @@ options:
|
|||
defining the view name. This argument does not check if the view
|
||||
has been configured on the device.
|
||||
aliases: ['role']
|
||||
sshkey:
|
||||
description:
|
||||
- Specifies the SSH public key to configure
|
||||
for the given username. This argument accepts a valid SSH key value.
|
||||
version_added: "2.6"
|
||||
nopassword:
|
||||
description:
|
||||
- Defines the username without assigning
|
||||
|
@ -109,6 +114,7 @@ EXAMPLES = """
|
|||
ios_user:
|
||||
name: ansible
|
||||
nopassword: True
|
||||
sshkey: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||||
state: present
|
||||
|
||||
- name: remove all users except admin
|
||||
|
@ -165,6 +171,8 @@ from copy import deepcopy
|
|||
|
||||
import re
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
|
||||
from functools import partial
|
||||
|
||||
|
@ -189,6 +197,22 @@ def user_del_cmd(username):
|
|||
}
|
||||
|
||||
|
||||
def sshkey_fingerprint(sshkey):
|
||||
# IOS will accept a MD5 fingerprint of the public key
|
||||
# and is easier to configure in a single line
|
||||
# we calculate this fingerprint here
|
||||
if not sshkey:
|
||||
return None
|
||||
if ' ' in sshkey:
|
||||
# ssh-rsa AAA...== comment
|
||||
keyparts = sshkey.split(' ')
|
||||
keyparts[1] = hashlib.md5(base64.b64decode(keyparts[1])).hexdigest().upper()
|
||||
return ' '.join(keyparts)
|
||||
else:
|
||||
# just the key, assume rsa type
|
||||
return 'ssh-rsa %s' % hashlib.md5(base64.b64decode(sshkey)).hexdigest().upper()
|
||||
|
||||
|
||||
def map_obj_to_commands(updates, module):
|
||||
commands = list()
|
||||
state = module.params['state']
|
||||
|
@ -200,11 +224,21 @@ def map_obj_to_commands(updates, module):
|
|||
def add(command, want, x):
|
||||
command.append('username %s %s' % (want['name'], x))
|
||||
|
||||
def add_ssh(command, want, x=None):
|
||||
command.append('ip ssh pubkey-chain')
|
||||
command.append(' no username %s' % want['name'])
|
||||
if x:
|
||||
command.append(' username %s' % want['name'])
|
||||
command.append(' key-hash %s' % x)
|
||||
command.append(' exit')
|
||||
command.append(' exit')
|
||||
|
||||
for update in updates:
|
||||
want, have = update
|
||||
|
||||
if want['state'] == 'absent':
|
||||
commands.append(user_del_cmd(want['name']))
|
||||
add_ssh(commands, want)
|
||||
continue
|
||||
|
||||
if needs_update(want, have, 'view'):
|
||||
|
@ -213,6 +247,9 @@ def map_obj_to_commands(updates, module):
|
|||
if needs_update(want, have, 'privilege'):
|
||||
add(commands, want, 'privilege %s' % want['privilege'])
|
||||
|
||||
if needs_update(want, have, 'sshkey'):
|
||||
add_ssh(commands, want, want['sshkey'])
|
||||
|
||||
if needs_update(want, have, 'configured_password'):
|
||||
if update_password == 'always' or not have:
|
||||
add(commands, want, 'secret %s' % want['configured_password'])
|
||||
|
@ -232,6 +269,12 @@ def parse_view(data):
|
|||
return match.group(1)
|
||||
|
||||
|
||||
def parse_sshkey(data):
|
||||
match = re.search(r'key-hash (\S+ \S+(?: .+)?)$', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def parse_privilege(data):
|
||||
match = re.search(r'privilege (\S+)', data, re.M)
|
||||
if match:
|
||||
|
@ -251,11 +294,15 @@ def map_config_to_obj(module):
|
|||
regex = r'username %s .+$' % user
|
||||
cfg = re.findall(regex, data, re.M)
|
||||
cfg = '\n'.join(cfg)
|
||||
sshregex = r'username %s\n\s+key-hash .+$' % user
|
||||
sshcfg = re.findall(sshregex, data, re.M)
|
||||
sshcfg = '\n'.join(sshcfg)
|
||||
obj = {
|
||||
'name': user,
|
||||
'state': 'present',
|
||||
'nopassword': 'nopassword' in cfg,
|
||||
'configured_password': None,
|
||||
'sshkey': parse_sshkey(sshcfg),
|
||||
'privilege': parse_privilege(cfg),
|
||||
'view': parse_view(cfg)
|
||||
}
|
||||
|
@ -311,6 +358,7 @@ def map_params_to_obj(module):
|
|||
item['nopassword'] = get_value('nopassword')
|
||||
item['privilege'] = get_value('privilege')
|
||||
item['view'] = get_value('view')
|
||||
item['sshkey'] = sshkey_fingerprint(get_value('sshkey'))
|
||||
item['state'] = get_value('state')
|
||||
objects.append(item)
|
||||
|
||||
|
@ -343,6 +391,8 @@ def main():
|
|||
privilege=dict(type='int'),
|
||||
view=dict(aliases=['role']),
|
||||
|
||||
sshkey=dict(),
|
||||
|
||||
state=dict(default='present', choices=['present', 'absent'])
|
||||
)
|
||||
aggregate_spec = deepcopy(element_spec)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue