summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/ansible/modules/network/nxos/nxos_aaa_server_host.py150
-rw-r--r--test/integration/targets/nxos_aaa_server_host/tests/common/radius.yaml68
-rw-r--r--test/integration/targets/nxos_aaa_server_host/tests/common/tacacs.yaml61
3 files changed, 190 insertions, 89 deletions
diff --git a/lib/ansible/modules/network/nxos/nxos_aaa_server_host.py b/lib/ansible/modules/network/nxos/nxos_aaa_server_host.py
index 8cfb2951cd..0c1d6bc6f4 100644
--- a/lib/ansible/modules/network/nxos/nxos_aaa_server_host.py
+++ b/lib/ansible/modules/network/nxos/nxos_aaa_server_host.py
@@ -33,7 +33,7 @@ description:
author: Jason Edelman (@jedelman8)
notes:
- Tested against NXOSv 7.3.(0)D1(1) on VIRL
- - Changes to the AAA server host key (shared secret) are not idempotent.
+ - Changes to the host key (shared secret) are not idempotent for type 0.
- If C(state=absent) removes the whole host configuration.
options:
server_type:
@@ -47,7 +47,7 @@ options:
required: true
key:
description:
- - Shared secret for the specified host.
+ - Shared secret for the specified host or keyword 'default'.
encrypt_type:
description:
- The state of encryption applied to the entered key.
@@ -56,16 +56,17 @@ options:
choices: ['0', '7']
host_timeout:
description:
- - Timeout period for specified host, in seconds. Range is 1-60.
+ - Timeout period for specified host, in seconds or keyword 'default.
+ Range is 1-60.
auth_port:
description:
- - Alternate UDP port for RADIUS authentication.
+ - Alternate UDP port for RADIUS authentication or keyword 'default'.
acct_port:
description:
- - Alternate UDP port for RADIUS accounting.
+ - Alternate UDP port for RADIUS accounting or keyword 'default'.
tacacs_port:
description:
- - Alternate TCP port TACACS Server.
+ - Alternate TCP port TACACS Server or keyword 'default'.
state:
description:
- Manage the state of the resource.
@@ -147,13 +148,11 @@ from ansible.module_utils.network.nxos.nxos import get_capabilities, nxos_argume
from ansible.module_utils.basic import AnsibleModule
-def execute_show_command(command, module, command_type='cli_show'):
+def execute_show_command(command, module):
device_info = get_capabilities(module)
network_api = device_info.get('network_api', 'nxapi')
if network_api == 'cliconf':
- if 'show run' not in command:
- command += ' | json'
cmds = [command]
body = run_commands(module, cmds)
elif network_api == 'nxapi':
@@ -173,40 +172,36 @@ def flatten_list(command_lists):
return flat_command_list
-def _match_dict(match_list, key_map):
- no_blanks = []
- match_dict = {}
-
- for match_set in match_list:
- match_set = tuple(v for v in match_set if v)
- no_blanks.append(match_set)
-
- for info in no_blanks:
- words = info[0].strip().split()
- length = len(words)
- alt_key = key_map.get(words[0])
- first = alt_key or words[0]
- last = words[length - 1]
- match_dict[first] = last.replace('\"', '')
-
- return match_dict
-
-
def get_aaa_host_info(module, server_type, address):
aaa_host_info = {}
command = 'show run | inc {0}-server.host.{1}'.format(server_type, address)
- body = execute_show_command(command, module, command_type='cli_show_ascii')
-
- if body[0]:
+ body = execute_show_command(command, module)[0]
+ if body:
try:
- pattern = (r'(acct-port \d+)|(timeout \d+)|(auth-port \d+)|'
- r'(key 7 "\w+")|( port \d+)')
- raw_match = re.findall(pattern, body[0])
- aaa_host_info = _match_dict(raw_match, {'acct-port': 'acct_port',
- 'auth-port': 'auth_port',
- 'port': 'tacacs_port',
- 'timeout': 'host_timeout'})
+ if 'radius' in body:
+ pattern = (r'\S+ host \S+(?:\s+key 7\s+(\S+))?(?:\s+auth-port (\d+))?'
+ r'(?:\s+acct-port (\d+))?(?:\s+authentication)?'
+ r'(?:\s+accounting)?(?:\s+timeout (\d+))?')
+ match = re.search(pattern, body)
+ aaa_host_info['key'] = match.group(1)
+ if aaa_host_info['key']:
+ aaa_host_info['key'] = aaa_host_info['key'].replace('"', '')
+ aaa_host_info['encrypt_type'] = '7'
+ aaa_host_info['auth_port'] = match.group(2)
+ aaa_host_info['acct_port'] = match.group(3)
+ aaa_host_info['host_timeout'] = match.group(4)
+ elif 'tacacs' in body:
+ pattern = (r'\S+ host \S+(?:\s+key 7\s+(\S+))?(?:\s+port (\d+))?'
+ r'(?:\s+timeout (\d+))?')
+ match = re.search(pattern, body)
+ aaa_host_info['key'] = match.group(1)
+ if aaa_host_info['key']:
+ aaa_host_info['key'] = aaa_host_info['key'].replace('"', '')
+ aaa_host_info['encrypt_type'] = '7'
+ aaa_host_info['tacacs_port'] = match.group(2)
+ aaa_host_info['host_timeout'] = match.group(3)
+
aaa_host_info['server_type'] = server_type
aaa_host_info['address'] = address
except TypeError:
@@ -217,35 +212,41 @@ def get_aaa_host_info(module, server_type, address):
return aaa_host_info
-def config_aaa_host(server_type, address, params, clear=False):
+def config_aaa_host(server_type, address, params, existing):
cmds = []
-
- if clear:
- cmds.append('no {0}-server host {1}'.format(server_type, address))
-
cmd_str = '{0}-server host {1}'.format(server_type, address)
+ cmd_no_str = 'no ' + cmd_str
key = params.get('key')
enc_type = params.get('encrypt_type', '')
- host_timeout = params.get('host_timeout')
- auth_port = params.get('auth_port')
- acct_port = params.get('acct_port')
- port = params.get('tacacs_port')
-
- if auth_port:
- cmd_str += ' auth-port {0}'.format(auth_port)
- if acct_port:
- cmd_str += ' acct-port {0}'.format(acct_port)
- if port:
- cmd_str += ' port {0}'.format(port)
- if host_timeout:
- cmd_str += ' timeout {0}'.format(host_timeout)
+
+ defval = False
+ nondef = False
+
if key:
- cmds.append('{0}-server host {1} key {2} {3}'.format(server_type,
- address,
- enc_type, key))
+ if key != 'default':
+ cmds.append(cmd_str + ' key {0} {1}'.format(enc_type, key))
+ else:
+ cmds.append(cmd_no_str + ' key 7 {0}'.format(existing.get('key')))
+
+ locdict = {'auth_port': 'auth-port', 'acct_port': 'acct-port',
+ 'tacacs_port': 'port', 'host_timeout': 'timeout'}
+
+ # platform CLI needs the keywords in the following order
+ for key in ['auth_port', 'acct_port', 'tacacs_port', 'host_timeout']:
+ item = params.get(key)
+ if item:
+ if item != 'default':
+ cmd_str += ' {0} {1}'.format(locdict.get(key), item)
+ nondef = True
+ else:
+ cmd_no_str += ' {0} 1'.format(locdict.get(key))
+ defval = True
+ if defval:
+ cmds.append(cmd_no_str)
+ if nondef or not existing:
+ cmds.append(cmd_str)
- cmds.append(cmd_str)
return cmds
@@ -302,24 +303,19 @@ def main():
end_state = existing
commands = []
+ delta = {}
if state == 'present':
- host_timeout = proposed.get('host_timeout')
- if host_timeout:
- try:
- if int(host_timeout) < 1 or int(host_timeout) > 60:
- raise ValueError
- except ValueError:
- module.fail_json(
- msg='host_timeout must be an integer between 1 and 60')
-
- delta = dict(
- set(proposed.items()).difference(existing.items()))
- if delta:
- union = existing.copy()
- union.update(delta)
- command = config_aaa_host(server_type, address, union)
- if command:
- commands.append(command)
+ if not existing:
+ delta = proposed
+ else:
+ for key, value in proposed.items():
+ if value != existing.get(key):
+ if value != 'default' or existing.get(key):
+ delta[key] = value
+
+ command = config_aaa_host(server_type, address, delta, existing)
+ if command:
+ commands.append(command)
elif state == 'absent':
intersect = dict(
diff --git a/test/integration/targets/nxos_aaa_server_host/tests/common/radius.yaml b/test/integration/targets/nxos_aaa_server_host/tests/common/radius.yaml
index 572650e97e..cf9a65556b 100644
--- a/test/integration/targets/nxos_aaa_server_host/tests/common/radius.yaml
+++ b/test/integration/targets/nxos_aaa_server_host/tests/common/radius.yaml
@@ -43,7 +43,7 @@
register: result
- assert: *false
-
+
- name: "Configure radius server non defaults"
nxos_aaa_server_host: &configure_radius_non_default
server_type: radius
@@ -54,7 +54,7 @@
state: present
provider: "{{ connection }}"
register: result
-
+
- assert: *true
- name: "Check Idempotence"
@@ -63,25 +63,38 @@
- assert: *false
- - name: "Remove radius server configuration"
- nxos_aaa_server_host: *remove
+ - name: "Configure some defaults on radius server"
+ nxos_aaa_server_host: &configure_some_radius_default
+ server_type: radius
+ address: 8.8.8.8
+ host_timeout: default
+ auth_port: 1000
+ acct_port: default
+ state: present
+ provider: "{{ connection }}"
register: result
- assert: *true
+ - name: "Check Idempotence"
+ nxos_aaa_server_host: *configure_some_radius_default
+ register: result
+
+ - assert: *false
+
- name: "Configure radius server with clear text pwd"
nxos_aaa_server_host: &configure_radius_clear_text
server_type: radius
address: 8.8.8.8
host_timeout: 25
- auth_port: 2083
+ auth_port: default
acct_port: 2084
encrypt_type: 0
key: hello
state: present
provider: "{{ connection }}"
register: result
-
+
- assert: *true
- name: "Check NOT Idempotent"
@@ -115,8 +128,49 @@
nxos_aaa_server_host: *configure_radius_type7
register: result
+ - assert: *false
+
+ - name: "Configure radius server with default key"
+ nxos_aaa_server_host: &configure_radius_defkey
+ server_type: radius
+ address: 8.8.8.8
+ host_timeout: default
+ auth_port: 1000
+ acct_port: default
+ encrypt_type: 7
+ key: default
+ state: present
+ provider: "{{ connection }}"
+ register: result
+
+ - assert: *true
+
+ - name: "Check Idempotence"
+ nxos_aaa_server_host: *configure_radius_defkey
+ register: result
+
+ - assert: *false
+
+ - name: "Configure radius server with all def"
+ nxos_aaa_server_host: &configure_radius_alldef
+ server_type: radius
+ address: 8.8.8.8
+ host_timeout: default
+ auth_port: default
+ acct_port: default
+ key: default
+ state: present
+ provider: "{{ connection }}"
+ register: result
+
- assert: *true
+ - name: "Check Idempotence"
+ nxos_aaa_server_host: *configure_radius_alldef
+ register: result
+
+ - assert: *false
+
rescue:
- debug: msg="connection={{ ansible_connection }} nxos_aaa_server_host failure detected"
@@ -127,4 +181,4 @@
nxos_aaa_server_host: *remove
register: result
- - debug: msg="END connection={{ ansible_connection }} nxos_aaa_server_host radius.yaml sanity test"
+ - debug: msg="END connection={{ ansible_connection }} nxos_aaa_server_host radius.yaml sanity test"
diff --git a/test/integration/targets/nxos_aaa_server_host/tests/common/tacacs.yaml b/test/integration/targets/nxos_aaa_server_host/tests/common/tacacs.yaml
index 4229f9affb..6307316734 100644
--- a/test/integration/targets/nxos_aaa_server_host/tests/common/tacacs.yaml
+++ b/test/integration/targets/nxos_aaa_server_host/tests/common/tacacs.yaml
@@ -60,7 +60,7 @@
state: present
provider: "{{ connection }}"
register: result
-
+
- assert: *true
- name: "Check Idempotence"
@@ -69,18 +69,30 @@
- assert: *false
- - name: "Remove tacacs server configuration"
- nxos_aaa_server_host: *remove
+ - name: "Configure some defaults on tacacs server"
+ nxos_aaa_server_host: &configure_some_tacacs_default
+ server_type: tacacs
+ address: 8.8.8.8
+ host_timeout: default
+ tacacs_port: 100
+ state: present
+ provider: "{{ connection }}"
register: result
- assert: *true
+ - name: "Check Idempotence"
+ nxos_aaa_server_host: *configure_some_tacacs_default
+ register: result
+
+ - assert: *false
+
- name: "Configure tacacs server with clear text pwd"
nxos_aaa_server_host: &configure_tacacs_clear_text
server_type: tacacs
address: 8.8.8.8
host_timeout: 25
- tacacs_port: 89
+ tacacs_port: default
encrypt_type: 0
key: hello
state: present
@@ -119,8 +131,47 @@
nxos_aaa_server_host: *configure_tacacs_type7
register: result
+ - assert: *false
+
+ - name: "Configure tacacs server with default key"
+ nxos_aaa_server_host: &configure_tacacs_defkey
+ server_type: tacacs
+ address: 8.8.8.8
+ host_timeout: default
+ tacacs_port: 89
+ encrypt_type: 7
+ key: default
+ state: present
+ provider: "{{ connection }}"
+ register: result
+
+ - assert: *true
+
+ - name: "Check Idempotence"
+ nxos_aaa_server_host: *configure_tacacs_defkey
+ register: result
+
+ - assert: *false
+
+ - name: "Configure tacacs server with all def"
+ nxos_aaa_server_host: &configure_tacacs_alldef
+ server_type: tacacs
+ address: 8.8.8.8
+ host_timeout: default
+ tacacs_port: default
+ key: default
+ state: present
+ provider: "{{ connection }}"
+ register: result
+
- assert: *true
+ - name: "Check Idempotence"
+ nxos_aaa_server_host: *configure_tacacs_alldef
+ register: result
+
+ - assert: *false
+
rescue:
- debug: msg="connection={{ ansible_connection }} nxos_aaa_server_host failure detected"
@@ -131,7 +182,7 @@
nxos_aaa_server_host: *remove
register: result
- - name: "Enable feature tacacs+"
+ - name: "Disable feature tacacs+"
nxos_feature:
feature: tacacs+
state: disabled