Add support for hashed password (#49464)

* Add support for hashed password

Signed-off-by: NilashishC <nilashishchakraborty8@gmail.com>

* Fix Shippable errors

Signed-off-by: NilashishC <nilashishchakraborty8@gmail.com>

* Make pwd options mutually exclusive

Signed-off-by: NilashishC <nilashishchakraborty8@gmail.com>
This commit is contained in:
Nilashish Chakraborty 2018-12-12 22:22:15 +05:30 committed by GitHub
parent 7bdca72713
commit d729614d72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 1 deletions

View file

@ -73,6 +73,21 @@ options:
default: secret default: secret
choices: ['secret', 'password'] choices: ['secret', 'password']
version_added: "2.8" version_added: "2.8"
hashed_password:
description:
- This option allows configuring hashed passwords on Cisco IOS devices.
suboptions:
type:
description:
- Specifies the type of hash (e.g., 5 for MD5, 8 for PBKDF2, etc.)
- For this to work, the device needs to support the desired hash type
type: int
required: True
value:
description:
- The actual hashed password to be configured on the device
required: True
version_added: "2.8"
privilege: privilege:
description: description:
- The C(privilege) argument configures the privilege level of the - The C(privilege) argument configures the privilege level of the
@ -170,6 +185,13 @@ EXAMPLES = """
configured_password: "{{ new_password }}" configured_password: "{{ new_password }}"
password_type: password password_type: password
- name: Add a user with MD5 hashed password
ios_user:
name: ansibletest5
hashed_password:
type: 5
value: $3$8JcDilcYgFZi.yz4ApaqkHG2.8/
- name: Delete users with aggregate - name: Delete users with aggregate
ios_user: ios_user:
aggregate: aggregate:
@ -191,6 +213,7 @@ commands:
from copy import deepcopy from copy import deepcopy
import re import re
import ast
import base64 import base64
import hashlib import hashlib
@ -245,6 +268,10 @@ def map_obj_to_commands(updates, module):
def add(command, want, x): def add(command, want, x):
command.append('username %s %s' % (want['name'], x)) command.append('username %s %s' % (want['name'], x))
def add_hashed_password(command, want, x):
command.append('username %s secret %s %s' % (want['name'], ast.literal_eval(x)['type'],
ast.literal_eval(x)['value']))
def add_ssh(command, want, x=None): def add_ssh(command, want, x=None):
command.append('ip ssh pubkey-chain') command.append('ip ssh pubkey-chain')
if x: if x:
@ -280,6 +307,9 @@ def map_obj_to_commands(updates, module):
' Please choose one or the other.') ' Please choose one or the other.')
add(commands, want, '%s %s' % (password_type, want['configured_password'])) add(commands, want, '%s %s' % (password_type, want['configured_password']))
if needs_update(want, have, 'hashed_password'):
add_hashed_password(commands, want, want['hashed_password'])
if needs_update(want, have, 'nopassword'): if needs_update(want, have, 'nopassword'):
if want['nopassword']: if want['nopassword']:
add(commands, want, 'nopassword') add(commands, want, 'nopassword')
@ -335,6 +365,7 @@ def map_config_to_obj(module):
'state': 'present', 'state': 'present',
'nopassword': 'nopassword' in cfg, 'nopassword': 'nopassword' in cfg,
'configured_password': None, 'configured_password': None,
'hashed_password': None,
'password_type': parse_password_type(cfg), 'password_type': parse_password_type(cfg),
'sshkey': parse_sshkey(sshcfg), 'sshkey': parse_sshkey(sshcfg),
'privilege': parse_privilege(cfg), 'privilege': parse_privilege(cfg),
@ -389,6 +420,7 @@ def map_params_to_obj(module):
for item in aggregate: for item in aggregate:
get_value = partial(get_param_value, item=item, module=module) get_value = partial(get_param_value, item=item, module=module)
item['configured_password'] = get_value('configured_password') item['configured_password'] = get_value('configured_password')
item['hashed_password'] = get_value('hashed_password')
item['nopassword'] = get_value('nopassword') item['nopassword'] = get_value('nopassword')
item['privilege'] = get_value('privilege') item['privilege'] = get_value('privilege')
item['view'] = get_value('view') item['view'] = get_value('view')
@ -415,10 +447,16 @@ def update_objects(want, have):
def main(): def main():
""" main entry point for module execution """ main entry point for module execution
""" """
hashed_password_spec = dict(
type=dict(type='int', required=True),
value=dict(no_log=True, required=True)
)
element_spec = dict( element_spec = dict(
name=dict(), name=dict(),
configured_password=dict(no_log=True), configured_password=dict(no_log=True),
hashed_password=dict(no_log=True, elements='dict', options=hashed_password_spec),
nopassword=dict(type='bool'), nopassword=dict(type='bool'),
update_password=dict(default='always', choices=['on_create', 'always']), update_password=dict(default='always', choices=['on_create', 'always']),
password_type=dict(default='secret', choices=['secret', 'password']), password_type=dict(default='secret', choices=['secret', 'password']),
@ -444,7 +482,7 @@ def main():
argument_spec.update(element_spec) argument_spec.update(element_spec)
argument_spec.update(ios_argument_spec) argument_spec.update(ios_argument_spec)
mutually_exclusive = [('name', 'aggregate')] mutually_exclusive = [('name', 'aggregate'), ('nopassword', 'hashed_password', 'configured_password')]
module = AnsibleModule(argument_spec=argument_spec, module = AnsibleModule(argument_spec=argument_spec,
mutually_exclusive=mutually_exclusive, mutually_exclusive=mutually_exclusive,

View file

@ -7,6 +7,7 @@
- name: ansibletest3 - name: ansibletest3
- name: ansibletest4 - name: ansibletest4
- name: ansibletest5 - name: ansibletest5
- name: ansibletest6
state: absent state: absent
provider: "{{ cli }}" provider: "{{ cli }}"
@ -94,6 +95,20 @@
- 'result.changed == true' - 'result.changed == true'
- "'username ansibleuser5 secret' in result.commands[0]" - "'username ansibleuser5 secret' in result.commands[0]"
- name: Create user with hashed_password
ios_user:
name: ansibleuser6
hashed_password:
type: 5
value: $3$8JcDilcYgFZi.yz4ApaqkHG2.8/
state: present
register: result
- assert:
that:
- 'result.changed == true'
- "'username ansibleuser6 secret' in result.commands[0]"
- name: tearDown - name: tearDown
ios_user: ios_user:
aggregate: aggregate:
@ -102,6 +117,7 @@
- name: ansibletest3 - name: ansibletest3
- name: ansibletest4 - name: ansibletest4
- name: ansibletest5 - name: ansibletest5
- name: ansibletest6
state: absent state: absent
provider: "{{ cli }}" provider: "{{ cli }}"
register: result register: result