community.general/lib/ansible/modules/network/nxos/nxos_aaa_server.py
Peter Sprygada 21d993a4b8 refactors nxos module to use persistent connections (#21470)
This completes the refactor of the nxos modules to use the persistent
connection.  It also updates all of the nxos modules to use the
new connection module and preserves use of nxapi as well.
2017-02-15 11:43:09 -05:00

381 lines
12 KiB
Python

#!/usr/bin/python
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
ANSIBLE_METADATA = {'status': ['preview'],
'supported_by': 'community',
'version': '1.0'}
DOCUMENTATION = '''
---
module: nxos_aaa_server
version_added: "2.2"
short_description: Manages AAA server global configuration.
description:
- Manages AAA server global configuration
author:
- Jason Edelman (@jedelman8)
notes:
- The server_type parameter is always required.
- If encrypt_type is not supplied, the global AAA server key will be
stored as encrypted (type 7).
- Changes to the global AAA server key with encrypt_type=0
are not idempotent.
- If global AAA server key is not found, it's shown as "unknown"
- state=default will set the supplied parameters to their default values.
The parameters that you want to default must also be set to default.
If global_key=default, the global key will be removed.
options:
server_type:
description:
- The server type is either radius or tacacs.
required: true
choices: ['radius', 'tacacs']
global_key:
description:
- Global AAA shared secret.
required: false
default: null
encrypt_type:
description:
- The state of encryption applied to the entered global key.
O clear text, 7 encrypted. Type-6 encryption is not supported.
required: false
default: null
choices: ['0', '7']
deadtime:
description:
- Duration for which a non-reachable AAA server is skipped,
in minutes. Range is 1-1440. Device default is 0.
required: false
default: null
server_timeout:
description:
- Global AAA server timeout period, in seconds. Range is 1-60.
Device default is 5.
required: false
default: null
directed_request:
description:
- Enables direct authentication requests to AAA server.
Device default is disabled.
required: false
default: null
choices: ['enabled', 'disabled']
state:
description:
- Manage the state of the resource.
required: true
default: present
choices: ['present','default']
'''
EXAMPLES = '''
# Radius Server Basic settings
- name: "Radius Server Basic settings"
nxos_aaa_server:
server_type: radius
server_timeout: 9
deadtime: 20
directed_request: enabled
host: inventory_hostname }}
username: un }}
password: pwd }}
# Tacacs Server Basic settings
- name: "Tacacs Server Basic settings"
nxos_aaa_server:
server_type: tacacs
server_timeout: 8
deadtime: 19
directed_request: disabled
host: inventory_hostname }}
username: un }}
password: pwd }}
# Setting Global Key
- name: "AAA Server Global Key"
nxos_aaa_server:
server_type: radius
global_key: test_key
host: inventory_hostname }}
username: un }}
password: pwd }}
'''
RETURN = '''
proposed:
description: k/v pairs of parameters passed into module
returned: always
type: dict
sample: {"deadtime": "22", "directed_request": "enabled",
"server_type": "radius", "server_timeout": "11"}
existing:
description:
- k/v pairs of existing aaa server
type: dict
sample: {"deadtime": "0", "directed_request": "disabled",
"global_key": "unknown", "server_timeout": "5"}
end_state:
description: k/v pairs of aaa params after module execution
returned: always
type: dict
sample: {"deadtime": "22", "directed_request": "enabled",
"global_key": "unknown", "server_timeout": "11"}
state:
description: state as sent in from the playbook
returned: always
type: string
sample: "present"
updates:
description: command sent to the device
returned: always
type: list
sample: ["radius-server deadtime 22", "radius-server timeout 11",
"radius-server directed-request"]
changed:
description: check to see if a change was made on the device
returned: always
type: boolean
sample: true
'''
import re
from ansible.module_utils.nxos import load_config, run_commands
from ansible.module_utils.nxos import nxos_argument_spec, check_args
from ansible.module_utils.basic import AnsibleModule
def execute_show_command(command, module, command_type='cli_show'):
cmds = [command]
if module.params['transport'] == 'cli':
body = run_commands(module, cmds)
elif module.params['transport'] == 'nxapi':
body = run_commands(module, cmds)
return body
def flatten_list(command_lists):
flat_command_list = []
for command in command_lists:
if isinstance(command, list):
flat_command_list.extend(command)
else:
flat_command_list.append(command)
return flat_command_list
def get_aaa_server_info(server_type, module):
aaa_server_info = {}
server_command = 'show {0}-server'.format(server_type)
request_command = 'show {0}-server directed-request'.format(server_type)
global_key_command = 'show run | sec {0}'.format(server_type)
aaa_regex = '.*{0}-server\skey\s\d\s+(?P<key>\S+).*'.format(server_type)
server_body = execute_show_command(
server_command, module, command_type='cli_show_ascii')[0]
split_server = server_body.splitlines()
for line in split_server:
if line.startswith('timeout'):
aaa_server_info['server_timeout'] = line.split(':')[1]
elif line.startswith('deadtime'):
aaa_server_info['deadtime'] = line.split(':')[1]
request_body = execute_show_command(
request_command, module, command_type='cli_show_ascii')[0]
aaa_server_info['directed_request'] = request_body.replace('\n', '')
key_body = execute_show_command(
global_key_command, module, command_type='cli_show_ascii')[0]
try:
match_global_key = re.match(aaa_regex, key_body, re.DOTALL)
group_key = match_global_key.groupdict()
aaa_server_info['global_key'] = group_key["key"].replace('\"', '')
except (AttributeError, TypeError):
aaa_server_info['global_key'] = 'unknown'
return aaa_server_info
def set_aaa_server_global_key(encrypt_type, key, server_type):
if not encrypt_type:
encrypt_type = ''
return '{0}-server key {1} {2}'.format(
server_type, encrypt_type, key)
def config_aaa_server(params, server_type):
cmds = []
deadtime = params.get('deadtime')
server_timeout = params.get('server_timeout')
directed_request = params.get('directed_request')
encrypt_type = params.get('encrypt_type', '7')
global_key = params.get('global_key')
if deadtime is not None:
cmds.append('{0}-server deadtime {1}'.format(server_type, deadtime))
if server_timeout is not None:
cmds.append('{0}-server timeout {1}'.format(server_type, server_timeout))
if directed_request is not None:
if directed_request == 'enabled':
cmds.append('{0}-server directed-request'.format(server_type))
elif directed_request == 'disabled':
cmds.append('no {0}-server directed-request'.format(server_type))
if global_key is not None:
cmds.append('{0}-server key {1} {2}'.format(server_type, encrypt_type,
global_key))
return cmds
def default_aaa_server(existing, params, server_type):
cmds = []
deadtime = params.get('deadtime')
server_timeout = params.get('server_timeout')
directed_request = params.get('directed_request')
global_key = params.get('global_key')
existing_key = existing.get('global_key')
if deadtime is not None:
cmds.append('no {0}-server deadtime 1'.format(server_type))
if server_timeout is not None:
cmds.append('no {0}-server timeout 1'.format(server_type))
if directed_request is not None:
cmds.append('no {0}-server directed-request'.format(server_type))
if global_key is not None and existing_key is not None:
cmds.append('no {0}-server key 7 {1}'.format(server_type, existing_key))
return cmds
def main():
argument_spec = dict(
server_type=dict(type='str',
choices=['radius', 'tacacs'], required=True),
global_key=dict(type='str'),
encrypt_type=dict(type='str', choices=['0', '7']),
deadtime=dict(type='str'),
server_timeout=dict(type='str'),
directed_request=dict(type='str',
choices=['enabled', 'disabled', 'default']),
state=dict(choices=['default', 'present'], default='present'),
)
argument_spec.update(nxos_argument_spec)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
warnings = list()
check_args(module, warnings)
server_type = module.params['server_type']
global_key = module.params['global_key']
encrypt_type = module.params['encrypt_type']
deadtime = module.params['deadtime']
server_timeout = module.params['server_timeout']
directed_request = module.params['directed_request']
state = module.params['state']
if encrypt_type and not global_key:
module.fail_json(msg='encrypt_type must be used with global_key.')
args = dict(server_type=server_type, global_key=global_key,
encrypt_type=encrypt_type, deadtime=deadtime,
server_timeout=server_timeout, directed_request=directed_request)
changed = False
proposed = dict((k, v) for k, v in args.items() if v is not None)
existing = get_aaa_server_info(server_type, module)
end_state = existing
commands = []
if state == 'present':
if deadtime:
try:
if int(deadtime) < 0 or int(deadtime) > 1440:
raise ValueError
except ValueError:
module.fail_json(
msg='deadtime must be an integer between 0 and 1440')
if server_timeout:
try:
if int(server_timeout) < 1 or int(server_timeout) > 60:
raise ValueError
except ValueError:
module.fail_json(
msg='server_timeout must be an integer between 1 and 60')
delta = dict(set(proposed.items()).difference(
existing.items()))
if delta:
command = config_aaa_server(delta, server_type)
if command:
commands.append(command)
elif state == 'default':
for key, value in proposed.items():
if key != 'server_type' and value != 'default':
module.fail_json(
msg='Parameters must be set to "default"'
'when state=default')
command = default_aaa_server(existing, proposed, server_type)
if command:
commands.append(command)
cmds = flatten_list(commands)
if cmds:
if module.check_mode:
module.exit_json(changed=True, commands=cmds)
else:
changed = True
load_config(module, cmds)
end_state = get_aaa_server_info(server_type, module)
if 'configure' in cmds:
cmds.pop(0)
results = {}
results['proposed'] = proposed
results['existing'] = existing
results['updates'] = cmds
results['changed'] = changed
results['warnings'] = warnings
results['end_state'] = end_state
module.exit_json(**results)
if __name__ == '__main__':
main()