diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform.json b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform.json index 4d34218672e9..a3770132c05f 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform.json +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform.json @@ -1,4 +1,5 @@ { + "fips_module": "Nokia-SONiC-MACsec-Version 1.0", "chassis": { "name": "Nokia-IXR7250E-36x400G", "components": [ diff --git a/dockers/docker-macsec/cli-plugin-tests/platform.json b/dockers/docker-macsec/cli-plugin-tests/platform.json new file mode 100644 index 000000000000..09e746dbe15c --- /dev/null +++ b/dockers/docker-macsec/cli-plugin-tests/platform.json @@ -0,0 +1,4 @@ +{ + "fips_module": "SONiC-MACsec-Version 1.0", + "chassis": { } +} diff --git a/dockers/docker-macsec/cli-plugin-tests/test_show_macsec.py b/dockers/docker-macsec/cli-plugin-tests/test_show_macsec.py index bc9a3792a2af..63290a8ef05d 100644 --- a/dockers/docker-macsec/cli-plugin-tests/test_show_macsec.py +++ b/dockers/docker-macsec/cli-plugin-tests/test_show_macsec.py @@ -1,4 +1,5 @@ import sys +import subprocess from unittest.mock import MagicMock, patch from click.testing import CliRunner @@ -7,6 +8,7 @@ import show_macsec + class TestShowMACsec(object): def test_plugin_registration(self): cli = MagicMock() @@ -274,3 +276,41 @@ def mock_get_all(db_name, key): assert "Module : sai" in result.output assert "Status : pass" in result.output assert "Namespace (asic1)" in result.output + + @patch('sonic_py_common.device_info.get_path_to_platform_dir', MagicMock(return_value='.')) + def test_show_fips_module(self): + runner = CliRunner() + result = runner.invoke(show_macsec.macsec,["--fips-module"]) + assert result.exit_code == 0, "exit code: {}, Exception: {}, Traceback: {}".format(result.exit_code, result.exception, result.exc_info) + assert "SONiC-MACsec-Version 1.0" in result.output + + # remove fips-module from platform.json. Re-test. This is to test scenario that some vendors + # do not have fips_module defined in platform file yet. + cmd = ['sed', '-i.bak', '/fips_module/d', './platform.json'] + subprocess.run(cmd, capture_output=True) + result = runner.invoke(show_macsec.macsec,["--fips-module"]) + assert result.exit_code == 0, "exit code: {}, Exception: {}, Traceback: {}".format(result.exit_code, result.exception, result.exc_info) + assert result.output == "" + # put original platform.json back + cmd = ['mv', './platform.json.bak', './platform.json'] + subprocess.run(cmd, stdout=subprocess.DEVNULL) + + def test_fips_module_mutual_exclusivity(self): + """Test that --fips-module and other option/argument are mutually exclusive""" + runner = CliRunner() + + result = runner.invoke(show_macsec.macsec, ["--fips-module", "--post-status"]) + assert result.exit_code == 0 + assert "POST status is not valid with other options/arguments" in result.output + + result = runner.invoke(show_macsec.macsec, ["--fips-module", "--profile"]) + assert result.exit_code == 0 + assert "fips-module is not valid with other options/arguments" in result.output + + result = runner.invoke(show_macsec.macsec, ["--fips-module", "Ethernet1"]) + assert result.exit_code == 0 + assert "fips-module is not valid with other options/arguments" in result.output + + result = runner.invoke(show_macsec.macsec, ["--fips-module", "--dump-file"]) + assert result.exit_code == 0 + assert "fips-module is not valid with other options/arguments" in result.output \ No newline at end of file diff --git a/dockers/docker-macsec/cli/show/plugins/show_macsec.py b/dockers/docker-macsec/cli/show/plugins/show_macsec.py index 8c3fd56982c3..7ce1bee0ffc5 100644 --- a/dockers/docker-macsec/cli/show/plugins/show_macsec.py +++ b/dockers/docker-macsec/cli/show/plugins/show_macsec.py @@ -4,13 +4,14 @@ import pickle import os import copy - +import json import click from tabulate import tabulate import utilities_common.multi_asic as multi_asic_util from swsscommon.swsscommon import CounterTable, MacsecCounter, SonicV2Connector from utilities_common.cli import UserCache +from sonic_py_common import device_info CACHE_MANAGER = UserCache(app_name="macsec") CACHE_FILE = os.path.join(CACHE_MANAGER.get_directory(), "macsecstats{}") @@ -267,15 +268,21 @@ def cache_find(cache: dict, target: MACsecAppMeta) -> MACsecAppMeta: @click.option('--profile', is_flag=True, required=False, default=False, help="show all macsec profiles") @click.option('--dump-file', is_flag=True, required=False, default=False, help="store show output to a file") @click.option('--post-status', is_flag=True, required=False, default=False, help="show macsec FIPS POST(Pre-Operational Self-Test) status") +@click.option('--fips-module', is_flag=True, required=False, default=False, help="show macsec FIPS module") @multi_asic_util.multi_asic_click_options -def macsec(interface_name, dump_file, namespace, display, profile, post_status): +def macsec(interface_name, dump_file, namespace, display, profile, post_status, fips_module): if post_status: - if interface_name is not None or profile or dump_file: + if interface_name is not None or profile or dump_file or fips_module: click.echo('POST status is not valid with other options/arguments') return MacsecContext(namespace, display).show_post_status() return - + if fips_module: + if interface_name is not None or profile or dump_file or post_status: + click.echo('fips-module is not valid with other options/arguments') + return + MacsecContext(namespace, display).show_fips_module() + return if interface_name is not None and profile: click.echo('Interface name is not valid with profile option') return @@ -399,6 +406,18 @@ def format_module_status(module, namespace): if display_output: click.echo("\n".join(display_output)) + def show_fips_module(self): + json_file = device_info.get_path_to_platform_dir() + '/' + device_info.PLATFORM_JSON_FILE + if not os.path.exists(json_file): + return + try: + with open(json_file, 'r') as file: + platform_data = json.load(file) + except (json.JSONDecodeError, IOError, TypeError, ValueError): + return + if 'fips_module' in platform_data: + click.echo(platform_data['fips_module']) + def register(cli): cli.add_command(macsec)