Skip to content

Commit 63a5257

Browse files
authored
[TACACS+] Add config command for AAA authorization and accounting. (#1889)
This pull request add config command for AAA authorization & accounting. #### Why I did it Support TACACS per-command authorization & accounting. #### How I did it Change AAA config command to support authorization & accounting. Change show AAA command to support authorization & accounting. Add UT to cover changed code. #### How to verify it 1. Build following project and pass all UTs: make target/python-wheels/sonic_utilities-1.2-py3-none-any.whl 2. Test new command manually. #### Which release branch to backport (provide reason below if selected) N/A #### Description for the changelog Add config command for AAA authorization & accounting. #### A picture of a cute animal (not mandatory but encouraged)
1 parent 8a8577b commit 63a5257

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

config/aaa.py

+38
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,44 @@ def login(auth_protocol):
137137
add_table_kv('AAA', 'authentication', 'login', val)
138138
authentication.add_command(login)
139139

140+
# cmd: aaa authorization
141+
@click.command()
142+
@click.argument('protocol', nargs=-1, type=click.Choice([ "tacacs+", "local", "tacacs+ local"]))
143+
def authorization(protocol):
144+
"""Switch AAA authorization [tacacs+ | local | '\"tacacs+ local\"']"""
145+
if len(protocol) == 0:
146+
click.echo('Argument "protocol" is required')
147+
return
148+
149+
if len(protocol) == 1 and (protocol[0] == 'tacacs+' or protocol[0] == 'local'):
150+
add_table_kv('AAA', 'authorization', 'login', protocol[0])
151+
elif len(protocol) == 1 and protocol[0] == 'tacacs+ local':
152+
add_table_kv('AAA', 'authorization', 'login', 'tacacs+,local')
153+
else:
154+
click.echo('Not a valid command')
155+
aaa.add_command(authorization)
156+
157+
# cmd: aaa accounting
158+
@click.command()
159+
@click.argument('protocol', nargs=-1, type=click.Choice(["disable", "tacacs+", "local", "tacacs+ local"]))
160+
def accounting(protocol):
161+
"""Switch AAA accounting [disable | tacacs+ | local | '\"tacacs+ local\"']"""
162+
if len(protocol) == 0:
163+
click.echo('Argument "protocol" is required')
164+
return
165+
166+
if len(protocol) == 1:
167+
if protocol[0] == 'tacacs+' or protocol[0] == 'local':
168+
add_table_kv('AAA', 'accounting', 'login', protocol[0])
169+
elif protocol[0] == 'tacacs+ local':
170+
add_table_kv('AAA', 'accounting', 'login', 'tacacs+,local')
171+
elif protocol[0] == 'disable':
172+
del_table_key('AAA', 'accounting', 'login')
173+
else:
174+
click.echo('Not a valid command')
175+
else:
176+
click.echo('Not a valid command')
177+
aaa.add_command(accounting)
140178

141179
@click.group()
142180
def tacacs():

show/main.py

+10
Original file line numberDiff line numberDiff line change
@@ -1478,10 +1478,20 @@ def aaa(db):
14781478
'authentication': {
14791479
'login': 'local (default)',
14801480
'failthrough': 'False (default)'
1481+
},
1482+
'authorization': {
1483+
'login': 'local (default)'
1484+
},
1485+
'accounting': {
1486+
'login': 'disable (default)'
14811487
}
14821488
}
14831489
if 'authentication' in data:
14841490
aaa['authentication'].update(data['authentication'])
1491+
if 'authorization' in data:
1492+
aaa['authorization'].update(data['authorization'])
1493+
if 'accounting' in data:
1494+
aaa['accounting'].update(data['accounting'])
14851495
for row in aaa:
14861496
entry = aaa[row]
14871497
for key in entry:

tests/aaa_test.py

+144
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,24 @@
1818
show_aaa_default_output="""\
1919
AAA authentication login local (default)
2020
AAA authentication failthrough False (default)
21+
AAA authorization login local (default)
22+
AAA accounting login disable (default)
2123
2224
"""
2325

2426
show_aaa_radius_output="""\
2527
AAA authentication login radius
2628
AAA authentication failthrough False (default)
29+
AAA authorization login local (default)
30+
AAA accounting login disable (default)
2731
2832
"""
2933

3034
show_aaa_radius_local_output="""\
3135
AAA authentication login radius,local
3236
AAA authentication failthrough False (default)
37+
AAA authorization login local (default)
38+
AAA accounting login disable (default)
3339
3440
"""
3541

@@ -40,6 +46,54 @@
4046
Not a valid command
4147
"""
4248

49+
show_aaa_tacacs_authentication_output="""\
50+
AAA authentication login tacacs+
51+
AAA authentication failthrough False (default)
52+
AAA authorization login local (default)
53+
AAA accounting login disable (default)
54+
55+
"""
56+
57+
show_aaa_tacacs_authorization_output="""\
58+
AAA authentication login tacacs+
59+
AAA authentication failthrough False (default)
60+
AAA authorization login tacacs+
61+
AAA accounting login disable (default)
62+
63+
"""
64+
65+
show_aaa_tacacs_local_authorization_output="""\
66+
AAA authentication login tacacs+
67+
AAA authentication failthrough False (default)
68+
AAA authorization login tacacs+,local
69+
AAA accounting login disable (default)
70+
71+
"""
72+
73+
show_aaa_tacacs_accounting_output="""\
74+
AAA authentication login tacacs+
75+
AAA authentication failthrough False (default)
76+
AAA authorization login tacacs+,local
77+
AAA accounting login tacacs+
78+
79+
"""
80+
81+
show_aaa_tacacs_local_accounting_output="""\
82+
AAA authentication login tacacs+
83+
AAA authentication failthrough False (default)
84+
AAA authorization login tacacs+,local
85+
AAA accounting login tacacs+,local
86+
87+
"""
88+
89+
show_aaa_disable_accounting_output="""\
90+
AAA authentication login tacacs+
91+
AAA authentication failthrough False (default)
92+
AAA authorization login tacacs+,local
93+
AAA accounting login disable
94+
95+
"""
96+
4397
class TestAaa(object):
4498
@classmethod
4599
def setup_class(cls):
@@ -136,3 +190,93 @@ def test_config_aaa_radius_invalid(self):
136190
assert result.exit_code == 0
137191
assert result.output == config_aaa_not_a_valid_command_output
138192

193+
def test_config_aaa_tacacs(self, get_cmd_module):
194+
(config, show) = get_cmd_module
195+
runner = CliRunner()
196+
db = Db()
197+
db.cfgdb.delete_table("AAA")
198+
199+
# test tacacs authentication
200+
result = runner.invoke(config.config.commands["aaa"],\
201+
["authentication", "login", "tacacs+"], obj=db)
202+
print(result.exit_code)
203+
print(result.output)
204+
assert result.exit_code == 0
205+
assert result.output == config_aaa_empty_output
206+
207+
db.cfgdb.mod_entry("AAA", "authentication", {'login' : 'tacacs+'})
208+
209+
result = runner.invoke(show.cli.commands["aaa"], [], obj=db)
210+
assert result.exit_code == 0
211+
assert result.output == show_aaa_tacacs_authentication_output
212+
213+
# test tacacs authorization
214+
result = runner.invoke(config.config.commands["aaa"],\
215+
["authorization", "tacacs+"], obj=db)
216+
print(result.exit_code)
217+
print(result.output)
218+
assert result.exit_code == 0
219+
assert result.output == config_aaa_empty_output
220+
221+
db.cfgdb.mod_entry("AAA", "authorization", {'login' : 'tacacs+'})
222+
223+
result = runner.invoke(show.cli.commands["aaa"], [], obj=db)
224+
assert result.exit_code == 0
225+
assert result.output == show_aaa_tacacs_authorization_output
226+
227+
# test tacacs + local authorization
228+
result = runner.invoke(config.config.commands["aaa"],\
229+
["authorization", "tacacs+ local"], obj=db)
230+
print(result.exit_code)
231+
print(result.output)
232+
assert result.exit_code == 0
233+
assert result.output == config_aaa_empty_output
234+
235+
db.cfgdb.mod_entry("AAA", "authorization", {'login' : 'tacacs+,local'})
236+
237+
result = runner.invoke(show.cli.commands["aaa"], [], obj=db)
238+
assert result.exit_code == 0
239+
assert result.output == show_aaa_tacacs_local_authorization_output
240+
241+
# test tacacs accounting
242+
result = runner.invoke(config.config.commands["aaa"],\
243+
["accounting", "tacacs+"], obj=db)
244+
print(result.exit_code)
245+
print(result.output)
246+
assert result.exit_code == 0
247+
assert result.output == config_aaa_empty_output
248+
249+
db.cfgdb.mod_entry("AAA", "accounting", {'login' : 'tacacs+'})
250+
251+
result = runner.invoke(show.cli.commands["aaa"], [], obj=db)
252+
assert result.exit_code == 0
253+
assert result.output == show_aaa_tacacs_accounting_output
254+
255+
# test tacacs + local accounting
256+
result = runner.invoke(config.config.commands["aaa"],\
257+
["accounting", "tacacs+ local"], obj=db)
258+
print(result.exit_code)
259+
print(result.output)
260+
assert result.exit_code == 0
261+
assert result.output == config_aaa_empty_output
262+
263+
db.cfgdb.mod_entry("AAA", "accounting", {'login' : 'tacacs+,local'})
264+
265+
result = runner.invoke(show.cli.commands["aaa"], [], obj=db)
266+
assert result.exit_code == 0
267+
assert result.output == show_aaa_tacacs_local_accounting_output
268+
269+
# test disable accounting
270+
result = runner.invoke(config.config.commands["aaa"],\
271+
["accounting", "disable"], obj=db)
272+
print(result.exit_code)
273+
print(result.output)
274+
assert result.exit_code == 0
275+
assert result.output == config_aaa_empty_output
276+
277+
db.cfgdb.mod_entry("AAA", "accounting", {'login' : 'disable'})
278+
279+
result = runner.invoke(show.cli.commands["aaa"], [], obj=db)
280+
assert result.exit_code == 0
281+
assert result.output == show_aaa_disable_accounting_output
282+

0 commit comments

Comments
 (0)