Skip to content

Commit 1f5a49f

Browse files
authored
Setup TACACS server on ptf for daily work and none TACACS test case (sonic-net#13400)
Setup TACACS server on ptf for daily work and none TACACS test case. Why I did it Improve TACACS feature coverage. How I did it Setup TACACS server on PTF device and bind to port 49. Because one test bed may run test case in parallel with multiple DUT: For none TACACS test case, run test case with new TACACS server on port 49. For TACACS test case, run test case with old TACACS server on port 59. Force user login with TACACS account, account name is 'admin' password is the value in 'ansible_altpasswords' variable or 'ansible_altpassword' variable. How to verify it Pass all test case.
1 parent 3954dfc commit 1f5a49f

16 files changed

+485
-21
lines changed

ansible/config_sonic_basedon_testbed.yml

+33
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,27 @@
413413
become: true
414414
when: proxy_env is defined and deploy is defined and deploy|bool == true
415415

416+
- name: Enable PTF tacacs server by default
417+
set_fact:
418+
use_ptf_tacacs_server: true
419+
tacacs_enabled_by_default: true
420+
when: use_ptf_tacacs_server is not defined
421+
422+
- debug: msg="use_ptf_tacacs_server {{ use_ptf_tacacs_server }}"
423+
416424
- block:
417425
- name: saved original minigraph file in SONiC DUT(ignore errors when file does not exist)
418426
shell: mv /etc/sonic/minigraph.xml /etc/sonic/minigraph.xml.orig
419427
become: true
420428
ignore_errors: true
421429

430+
- name: Update TACACS server address to PTF IP
431+
set_fact:
432+
tacacs_servers: ["{{ testbed_facts['ptf_ip'] }}"]
433+
when: use_ptf_tacacs_server is defined and use_ptf_tacacs_server|bool == true
434+
435+
- debug: msg="tacacs_servers {{ tacacs_servers }}"
436+
422437
- name: create new minigraph file for SONiC device
423438
template: src=templates/minigraph_template.j2
424439
dest=/etc/sonic/minigraph.xml
@@ -606,6 +621,24 @@
606621
ignore_errors: true
607622
when: tacacs_enabled_by_default is defined and tacacs_enabled_by_default|bool == true
608623

624+
- block:
625+
- name: Configure TACACS with PTF TACACS server
626+
become: true
627+
shell: "{{ tacacs_config_cmd }}"
628+
loop:
629+
- config tacacs authtype login
630+
- config aaa authorization tacacs+
631+
- config aaa accounting "tacacs+ local"
632+
loop_control:
633+
loop_var: tacacs_config_cmd
634+
ignore_errors: true
635+
636+
- name: Configure TACACS with PTF TACACS server for MX
637+
become: true
638+
shell: config aaa authorization "tacacs+ local"
639+
when: topo == "mx"
640+
when: use_ptf_tacacs_server is defined and use_ptf_tacacs_server|bool == true
641+
609642
- name: execute configlet application script, which applies configlets in strict order.
610643
become: true
611644
shell: bash "/etc/sonic/apply_clet.sh"

ansible/roles/vm_set/tasks/add_topo.yml

+3
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@
265265
nic_simulator_action: start
266266
when: topology.host_interfaces_active_active is defined and topology.host_interfaces_active_active|length > 0
267267

268+
- name: Start tacacs+ daily daemon
269+
include_tasks: start_tacacs_daily_daemon.yml
270+
268271
when: container_type == "PTF"
269272

270273
- name: Save PTF image
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
- name: Include tacacs_passkey
3+
block:
4+
- name: Get inventory folder name
5+
set_fact: inv_file="{{ playbook_dir }}/group_vars/{{ inventory_file.split("/")[-1] }}/{{ inventory_file.split("/")[-1] }}.yml"
6+
7+
- debug: msg="inv_file {{ inv_file }}"
8+
9+
- name: Check inventory file exist
10+
stat:
11+
path: "{{ inv_file }}"
12+
register: inventory_file
13+
14+
- name: Include tacacs_passkey from inventory file
15+
include_vars: "{{ inv_file }}"
16+
when: inventory_file.stat.exists
17+
18+
- name: Include default tacacs_passkey
19+
include_vars: "{{ playbook_dir }}/group_vars/lab/lab.yml"
20+
when: tacacs_passkey is not defined
21+
22+
when: tacacs_passkey is not defined
23+
24+
- debug: msg="tacacs_passkey {{ tacacs_passkey }}"
25+
26+
- name: Set ptf host
27+
set_fact:
28+
ptf_host: "ptf_{{ vm_set_name }}"
29+
30+
- debug: msg="ptf_host {{ ptf_host }}"
31+
32+
- name: Include duthost user name
33+
block:
34+
- name: Set duthost user name
35+
set_fact:
36+
dut_host_user: "{{ secret_group_vars['str']['ansible_ssh_user'] }}"
37+
38+
when:
39+
- secret_group_vars is defined
40+
- secret_group_vars['str'] is defined
41+
- secret_group_vars['str']['ansible_ssh_user'] is defined
42+
43+
- name: Set default duthost user name from group_vars/lab/secrets.yml
44+
block:
45+
- name: Include sonicadmin_user from group_vars/lab/secrets.yml
46+
include_vars: "{{ playbook_dir }}/group_vars/lab/secrets.yml"
47+
48+
- name: Set dut user name
49+
set_fact:
50+
dut_host_user: "{{ sonicadmin_user }}"
51+
52+
when:
53+
- dut_host_user is not defined
54+
55+
- debug: msg="dut_host_user {{ dut_host_user }}"
56+
57+
- name: Include duthost password
58+
block:
59+
- name: Encrypt encrypted_sonic_password from secret_group_vars
60+
block:
61+
62+
- name: Encrypt TACACS password from secret_group_vars
63+
shell: python3 -c "import crypt; print(crypt.crypt('{{secret_group_vars['str']['altpasswords'][0]}}', 'abc'))"
64+
register: encrypted_sonic_password
65+
delegate_to: "{{ ptf_host }}"
66+
67+
when:
68+
- secret_group_vars is defined
69+
- secret_group_vars['str'] is defined
70+
- secret_group_vars['str']['altpasswords'] is defined
71+
72+
- name: Encrypt default encrypted_sonic_password from group_vars/lab/secrets.yml
73+
block:
74+
- name: Include sonicadmin_password from group_vars/lab/secrets.yml
75+
include_vars: "{{ playbook_dir }}/group_vars/lab/secrets.yml"
76+
77+
- name: Encrypt TACACS password from sonicadmin_password
78+
shell: python3 -c "import crypt; print(crypt.crypt('{{sonicadmin_password}}', 'abc'))"
79+
register: encrypted_sonic_password
80+
delegate_to: "{{ ptf_host }}"
81+
82+
when:
83+
- tacacs_user_passwd is not defined
84+
85+
- name: Set TACACS password from encrypted_sonic_password
86+
set_fact:
87+
tacacs_user_passwd: '{{ encrypted_sonic_password.stdout }}'
88+
89+
- debug: msg="tacacs_user_passwd {{ tacacs_user_passwd }}"
90+
91+
- block:
92+
- name: Generate tacacs daily daemon config file
93+
template:
94+
src: tac_plus_daily.conf.j2
95+
dest: /etc/tac_plus_daily.conf
96+
delegate_to: "{{ ptf_host }}"
97+
98+
- name: Upload tacacs daily daemon file
99+
copy:
100+
src: 'scripts/tacacs_daily_daemon'
101+
dest: /root/tacacs_daily_daemon
102+
mode: "0755"
103+
delegate_to: "{{ ptf_host }}"
104+
105+
- name: Upload tacacs daily start script
106+
copy:
107+
src: 'scripts/start_tacacs.sh'
108+
dest: /root/start_tacacs.sh
109+
mode: "0755"
110+
delegate_to: "{{ ptf_host }}"
111+
112+
- name: Start tacacs daily daemon
113+
shell: /root/start_tacacs.sh
114+
delegate_to: "{{ptf_host}}"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Created by Henry-Nicolas Tourneur(henry.nicolas@tourneur.be)
2+
# See man(5) tac_plus.conf for more details
3+
4+
# Define where to log accounting data, this is the default.
5+
6+
accounting file = /var/log/tac_plus_daily.acct
7+
8+
# This is the key that clients have to use to access Tacacs+
9+
10+
key = {{ tacacs_passkey }}
11+
12+
group = netadmin {
13+
default service = permit
14+
service = exec {
15+
priv-lvl = 15
16+
}
17+
}
18+
19+
user = {{ dut_host_user }} {
20+
login = des {{ tacacs_user_passwd }}
21+
member = netadmin
22+
}

ansible/scripts/start_tacacs.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
/root/tacacs_daily_daemon &

ansible/scripts/tacacs_daily_daemon

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/sh
2+
3+
# This TACACS server need bind to port 49, because SONiC load_minigraph only support port 49
4+
TACPLUS_PORT=49
5+
6+
# Always kill running tac_plus process on port $TACPLUS_PORT to reload config
7+
# It will be start later by tacacs_daily_daemon
8+
TACPLUS_PID=$(ps -ef | grep "tac_plus .* -p $TACPLUS_PORT" | grep -v "grep" | awk '{print $2}')
9+
if [ $TACPLUS_PID ]; then
10+
echo "tac_plus already running on port $TACPLUS_PORT, stop it to reload config"
11+
kill -9 $TACPLUS_PID
12+
fi
13+
14+
# Exit if tacacs_daily_daemon already running
15+
PROCESS_NUM=$(pgrep -l tacacs_daily_daemon | wc -l)
16+
if [ $PROCESS_NUM -ge 1 ]; then
17+
echo "tacacs_daily_daemon already running"
18+
exit 0
19+
fi
20+
21+
# Exit if tacacs_daily_daemon already running in background
22+
# need check -ge3, because every grep command will create a process with same name
23+
PROCESS_NUM=$(ps -ef | grep "/bin/sh .*tacacs_daily_daemon" | grep -v "grep" | wc -l)
24+
if [ $PROCESS_NUM -ge 3 ]; then
25+
echo "tacacs_daily_daemon already running in background" $PROCESS_NUM
26+
exit 0
27+
fi
28+
29+
echo "starting tac_plus for daily work"
30+
while true;
31+
do
32+
# start tac_plus will kill existed tac_plus instance bind to same port
33+
# Enable Authentication/Authorization/Accounting debug by: -d 88
34+
/usr/sbin/tac_plus -d 88 -l /var/log/tac_plus_daily.log -C /etc/tac_plus_daily.conf -p $TACPLUS_PORT -G
35+
echo "tac_plus existed, restarting"
36+
done

docs/testbed/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
- [Internal](README.testbed.Internal.md)
1919
- [Kubernetes Setup](README.testbed.k8s.Setup.md)
2020
- [SAI Test Setup](./sai_quality/README.md)
21+
- [TACACS](README.testbed.TACACS.md)

docs/testbed/README.testbed.Example.Config.md

+16
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ grep 'vlab-01' -A 2 ./veos_vtb
6262
```
6363
this is the IP for the DUT.
6464

65+
#### DUT user name and password
66+
The DUT may enable TACACS AAA, if you can't login DUT with local user, please find TACACS user name and password by following steps:
67+
68+
##### User name:
69+
```
70+
1. If secret_group_vars['str']['ansible_ssh_user'] defined, the DUT user name is the value of secret_group_vars['str']['ansible_ssh_user']
71+
2. If secret_group_vars['str']['ansible_ssh_user'] not defined, the DUT user name is the value of sonicadmin_user variable defined in group_vars/lab/secrets.yml
72+
```
73+
74+
##### Password:
75+
```
76+
1. If secret_group_vars['str']['altpasswords'] defined, the DUT user name is the value of secret_group_vars['str']['altpasswords'][0]
77+
2. If secret_group_vars['str']['altpasswords'] not defined, the DUT user name is the value of sonicadmin_password variable defined in group_vars/lab/secrets.yml
78+
```
79+
6580

6681
Then, you can use this IP `10.250.0.101` to access that DUT.
6782

@@ -153,3 +168,4 @@ For this article, some of the reference docs as:
153168
- [```Testbed Configuration```](/docs/testbed/README.testbed.Config.md): Introduction about Testbed configuration, mainly about the testbed.csv (Will be replaced by testbed.yaml).
154169
- [```New Testbed Configuration```](/docs/testbed/README.new.testbed.Configuration.md): Introduction about Testbed configuration, mainly about the Testbed.yaml.
155170
- [```KVM Testbed Setup```](/docs/testbed/README.testbed.VsSetup.md)
171+
- [```Testbed TACACS server```](/docs/testbed/README.testbed.TACACS.md)

0 commit comments

Comments
 (0)