Skip to content

Commit 8703773

Browse files
authored
YANG Validation for ConfigDB Updates: RADIUS_SERVER (#2604)
#### What I did Add YANG validation using GCU for writes to RADIUS_SERVER table in ConfigDB #### How I did it Using same method as https://github.com/sonic-net/sonic-utilities/pull/2190/files, extend to RADIUS table #### How to verify it verified testing on virtual switch CLI, unit tests
1 parent c2d746d commit 8703773

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

config/aaa.py

+33-19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from swsscommon.swsscommon import ConfigDBConnector
55
from .validated_config_db_connector import ValidatedConfigDBConnector
66
from jsonpatch import JsonPatchConflict
7+
from jsonpointer import JsonPointerException
78
import utilities_common.cli as clicommon
89

910
ADHOC_VALIDATION = True
@@ -498,15 +499,16 @@ def statistics(option):
498499
def add(address, retransmit, timeout, key, auth_type, auth_port, pri, use_mgmt_vrf, source_interface):
499500
"""Specify a RADIUS server"""
500501

501-
if key:
502-
if len(key) > RADIUS_PASSKEY_MAX_LEN:
503-
click.echo('--key: Maximum of %d chars can be configured' % RADIUS_PASSKEY_MAX_LEN)
504-
return
505-
elif not is_secret(key):
506-
click.echo('--key: ' + VALID_CHARS_MSG)
507-
return
502+
if ADHOC_VALIDATION:
503+
if key:
504+
if len(key) > RADIUS_PASSKEY_MAX_LEN:
505+
click.echo('--key: Maximum of %d chars can be configured' % RADIUS_PASSKEY_MAX_LEN)
506+
return
507+
elif not is_secret(key):
508+
click.echo('--key: ' + VALID_CHARS_MSG)
509+
return
508510

509-
config_db = ConfigDBConnector()
511+
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
510512
config_db.connect()
511513
old_data = config_db.get_table('RADIUS_SERVER')
512514
if address in old_data :
@@ -529,16 +531,24 @@ def add(address, retransmit, timeout, key, auth_type, auth_port, pri, use_mgmt_v
529531
data['passkey'] = key
530532
if use_mgmt_vrf :
531533
data['vrf'] = "mgmt"
532-
if source_interface :
533-
if (source_interface.startswith("Ethernet") or \
534-
source_interface.startswith("PortChannel") or \
535-
source_interface.startswith("Vlan") or \
536-
source_interface.startswith("Loopback") or \
537-
source_interface == "eth0"):
534+
if ADHOC_VALIDATION:
535+
if source_interface :
536+
if (source_interface.startswith("Ethernet") or \
537+
source_interface.startswith("PortChannel") or \
538+
source_interface.startswith("Vlan") or \
539+
source_interface.startswith("Loopback") or \
540+
source_interface == "eth0"):
541+
data['src_intf'] = source_interface
542+
else:
543+
click.echo('Not supported interface name (valid interface name: Etherent<id>/PortChannel<id>/Vlan<id>/Loopback<id>/eth0)')
544+
else:
545+
if source_interface:
538546
data['src_intf'] = source_interface
539-
else:
540-
click.echo('Not supported interface name (valid interface name: Etherent<id>/PortChannel<id>/Vlan<id>/Loopback<id>/eth0)')
541-
config_db.set_entry('RADIUS_SERVER', address, data)
547+
try:
548+
config_db.set_entry('RADIUS_SERVER', address, data)
549+
except ValueError as e:
550+
ctx = click.get_current_context()
551+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
542552
radius.add_command(add)
543553

544554

@@ -549,7 +559,11 @@ def add(address, retransmit, timeout, key, auth_type, auth_port, pri, use_mgmt_v
549559
def delete(address):
550560
"""Delete a RADIUS server"""
551561

552-
config_db = ConfigDBConnector()
562+
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
553563
config_db.connect()
554-
config_db.set_entry('RADIUS_SERVER', address, None)
564+
try:
565+
config_db.set_entry('RADIUS_SERVER', address, None)
566+
except (JsonPointerException, JsonPatchConflict) as e:
567+
ctx = click.get_current_context()
568+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
555569
radius.add_command(delete)

tests/radius_test.py

+25
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import imp
22
import os
33
import sys
4+
import mock
5+
import jsonpatch
46

57
from click.testing import CliRunner
68
from utilities_common.db import Db
9+
from mock import patch
10+
from jsonpointer import JsonPointerException
711

812
import config.main as config
13+
import config.aaa as aaa
914
import show.main as show
1015

1116
test_path = os.path.dirname(os.path.abspath(__file__))
@@ -192,3 +197,23 @@ def test_config_radius_authtype(self, get_cmd_module):
192197
assert result.exit_code == 0
193198
assert result.output == show_radius_default_output
194199

200+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
201+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=ValueError))
202+
def test_config_radius_server_invalidkey_yang_validation(self):
203+
aaa.ADHOC_VALIDATION = False
204+
runner = CliRunner()
205+
result = runner.invoke(config.config.commands["radius"],\
206+
["add", "10.10.10.10", "-r", "1", "-t", "3",\
207+
"-k", "comma,invalid", "-s", "eth0"])
208+
print(result.output)
209+
assert "Invalid ConfigDB. Error" in result.output
210+
211+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
212+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=JsonPointerException))
213+
def test_config_radius_server_invalid_delete_yang_validation(self):
214+
aaa.ADHOC_VALIDATION = False
215+
runner = CliRunner()
216+
result = runner.invoke(config.config.commands["radius"],\
217+
["delete", "10.10.10.x"])
218+
print(result.output)
219+
assert "Invalid ConfigDB. Error" in result.output

0 commit comments

Comments
 (0)