diff --git a/tests/gnmi/conftest.py b/tests/gnmi/conftest.py index f282cbe174..b5d77ffa09 100644 --- a/tests/gnmi/conftest.py +++ b/tests/gnmi/conftest.py @@ -4,8 +4,8 @@ from tests.common.helpers.assertions import pytest_require as pyrequire from tests.common.helpers.dut_utils import check_container_state -from tests.gnmi.helper import gnmi_container, apply_cert_config, recover_cert_config, create_ext_conf -from tests.gnmi.helper import GNMI_SERVER_START_WAIT_TIME +from tests.gnmi.helper import gnmi_container, apply_cert_config, recover_cert_config, GNMI_SERVER_START_WAIT_TIME, \ + prepare_root_cert, prepare_server_cert, prepare_client_cert, copy_certificate_to_dut, copy_certificate_to_ptf from tests.common.gu_utils import create_checkpoint, rollback logger = logging.getLogger(__name__) @@ -46,82 +46,12 @@ def setup_gnmi_server(duthosts, rand_one_dut_hostname, localhost, ptfhost): check_container_state(duthost, gnmi_container(duthost), should_be_running=True), "Test was not supported on devices which do not support GNMI!") - # Create Root key - local_command = "openssl genrsa -out gnmiCA.key 2048" - localhost.shell(local_command) - - # Create Root cert - local_command = "openssl req \ - -x509 \ - -new \ - -nodes \ - -key gnmiCA.key \ - -sha256 \ - -days 1825 \ - -subj '/CN=test.gnmi.sonic' \ - -out gnmiCA.pem" - localhost.shell(local_command) - - # Create server key - local_command = "openssl genrsa -out gnmiserver.key 2048" - localhost.shell(local_command) - - # Create server CSR - local_command = "openssl req \ - -new \ - -key gnmiserver.key \ - -subj '/CN=test.server.gnmi.sonic' \ - -out gnmiserver.csr" - localhost.shell(local_command) - - # Sign server certificate - create_ext_conf(duthost.mgmt_ip, "extfile.cnf") - local_command = "openssl x509 \ - -req \ - -in gnmiserver.csr \ - -CA gnmiCA.pem \ - -CAkey gnmiCA.key \ - -CAcreateserial \ - -out gnmiserver.crt \ - -days 825 \ - -sha256 \ - -extensions req_ext -extfile extfile.cnf" - localhost.shell(local_command) - - # Create client key - local_command = "openssl genrsa -out gnmiclient.key 2048" - localhost.shell(local_command) - - # Create client CSR - local_command = "openssl req \ - -new \ - -key gnmiclient.key \ - -subj '/CN=test.client.gnmi.sonic' \ - -out gnmiclient.csr" - localhost.shell(local_command) - - # Sign client certificate - local_command = "openssl x509 \ - -req \ - -in gnmiclient.csr \ - -CA gnmiCA.pem \ - -CAkey gnmiCA.key \ - -CAcreateserial \ - -out gnmiclient.crt \ - -days 825 \ - -sha256" - localhost.shell(local_command) + prepare_root_cert(localhost) + prepare_server_cert(duthost, localhost) + prepare_client_cert(localhost) - # Copy CA certificate, server certificate and client certificate over to the DUT - duthost.copy(src='gnmiCA.pem', dest='/etc/sonic/telemetry/') - duthost.copy(src='gnmiserver.crt', dest='/etc/sonic/telemetry/') - duthost.copy(src='gnmiserver.key', dest='/etc/sonic/telemetry/') - duthost.copy(src='gnmiclient.crt', dest='/etc/sonic/telemetry/') - duthost.copy(src='gnmiclient.key', dest='/etc/sonic/telemetry/') - # Copy CA certificate and client certificate over to the PTF - ptfhost.copy(src='gnmiCA.pem', dest='/root/') - ptfhost.copy(src='gnmiclient.crt', dest='/root/') - ptfhost.copy(src='gnmiclient.key', dest='/root/') + copy_certificate_to_dut(duthost) + copy_certificate_to_ptf(ptfhost) create_checkpoint(duthost, SETUP_ENV_CP) apply_cert_config(duthost) diff --git a/tests/gnmi/helper.py b/tests/gnmi/helper.py index 5c06ee8c3c..76af7d5ccb 100644 --- a/tests/gnmi/helper.py +++ b/tests/gnmi/helper.py @@ -1,6 +1,8 @@ import time import logging import pytest +import re +from datetime import datetime from tests.common.utilities import wait_until from tests.common.helpers.gnmi_utils import GNMIEnvironment @@ -406,3 +408,130 @@ def gnoi_request(duthost, localhost, rpc, request_json_data): return -1, output['stderr'] else: return 0, output['stdout'] + + +def cert_date_on_dut(duthost): + cmd = "openssl x509 -in /etc/sonic/telemetry/gnmiCA.pem -text" + output = duthost.shell(cmd, module_ignore_errors=True) + not_after_line = re.search(r"Not After\s*:\s*(.*)", output['stdout']) + if not_after_line: + not_after_date_str = not_after_line.group(1).strip() + # Convert the date string to a datetime object + expiry_date = datetime.strptime(not_after_date_str, "%b %d %H:%M:%S %Y GMT") + # comparison date is January 20, 2038, after the 2038 problem + after_2038_problem_date = datetime(2038, 1, 20) + + if expiry_date < after_2038_problem_date: + raise Exception("The expiry date {} is not after 2038 problem date".format(expiry_date)) + else: + logger.info("The expiry date {} is after January 20, 2038.".format(expiry_date)) + else: + raise Exception("The 'Not After' line with expiry date was not found") + + +def prepare_root_cert(localhost, days="1825"): + create_root_key(localhost) + create_root_cert(localhost, days) + + +def create_root_key(localhost): + local_command = "openssl genrsa -out gnmiCA.key 2048" + localhost.shell(local_command) + + +def create_root_cert(localhost, days): + local_command = "openssl req \ + -x509 \ + -new \ + -nodes \ + -key gnmiCA.key \ + -sha256 \ + -days {} \ + -subj '/CN=test.gnmi.sonic' \ + -out gnmiCA.pem".format(days) + localhost.shell(local_command) + + +def prepare_server_cert(duthost, localhost, days="825"): + create_server_key(localhost) + create_server_csr(localhost) + sign_server_certificate(duthost, localhost, days) + + +def create_server_key(localhost): + local_command = "openssl genrsa -out gnmiserver.key 2048" + localhost.shell(local_command) + + +def create_server_csr(localhost): + local_command = "openssl req \ + -new \ + -key gnmiserver.key \ + -subj '/CN=test.server.gnmi.sonic' \ + -out gnmiserver.csr" + localhost.shell(local_command) + + +def sign_server_certificate(duthost, localhost, days): + create_ext_conf(duthost.mgmt_ip, "extfile.cnf") + local_command = "openssl x509 \ + -req \ + -in gnmiserver.csr \ + -CA gnmiCA.pem \ + -CAkey gnmiCA.key \ + -CAcreateserial \ + -out gnmiserver.crt \ + -days {} \ + -sha256 \ + -extensions req_ext \ + -extfile extfile.cnf".format(days) + localhost.shell(local_command) + + +def prepare_client_cert(localhost, days="825"): + create_client_key(localhost) + create_client_csr(localhost) + sign_client_certificate(localhost, days) + + +def create_client_key(localhost): + local_command = "openssl genrsa -out gnmiclient.key 2048" + localhost.shell(local_command) + + +def create_client_csr(localhost): + local_command = "openssl req \ + -new \ + -key gnmiclient.key \ + -subj '/CN=test.client.gnmi.sonic' \ + -out gnmiclient.csr" + localhost.shell(local_command) + + +def sign_client_certificate(localhost, days): + local_command = "openssl x509 \ + -req \ + -in gnmiclient.csr \ + -CA gnmiCA.pem \ + -CAkey gnmiCA.key \ + -CAcreateserial \ + -out gnmiclient.crt \ + -days {} \ + -sha256".format(days) + localhost.shell(local_command) + + +def copy_certificate_to_dut(duthost): + # Copy CA certificate, server certificate and client certificate over to the DUT + duthost.copy(src='gnmiCA.pem', dest='/etc/sonic/telemetry/') + duthost.copy(src='gnmiserver.crt', dest='/etc/sonic/telemetry/') + duthost.copy(src='gnmiserver.key', dest='/etc/sonic/telemetry/') + duthost.copy(src='gnmiclient.crt', dest='/etc/sonic/telemetry/') + duthost.copy(src='gnmiclient.key', dest='/etc/sonic/telemetry/') + + +def copy_certificate_to_ptf(ptfhost): + # Copy CA certificate and client certificate over to the PTF + ptfhost.copy(src='gnmiCA.pem', dest='/root/') + ptfhost.copy(src='gnmiclient.crt', dest='/root/') + ptfhost.copy(src='gnmiclient.key', dest='/root/') diff --git a/tests/gnmi/test_gnmi_2038.py b/tests/gnmi/test_gnmi_2038.py new file mode 100644 index 0000000000..04047a2240 --- /dev/null +++ b/tests/gnmi/test_gnmi_2038.py @@ -0,0 +1,38 @@ +import pytest +import logging + +from .helper import gnmi_capabilities, prepare_root_cert, prepare_server_cert, prepare_client_cert, \ + copy_certificate_to_dut, copy_certificate_to_ptf, apply_cert_config, cert_date_on_dut + +logger = logging.getLogger(__name__) +SETUP_ENV_CP = "test_setup_checkpoint" + +pytestmark = [ + pytest.mark.topology('any'), + pytest.mark.disable_loganalyzer +] + + +def test_gnmi_capabilities(duthosts, rand_one_dut_hostname, localhost, ptfhost): + ''' + Verify certificate after 2038 year problem + ''' + duthost = duthosts[rand_one_dut_hostname] + + prepare_root_cert(localhost, days="4850") + prepare_server_cert(duthost, localhost, days="4810") + prepare_client_cert(localhost, days="4810") + + copy_certificate_to_dut(duthost) + copy_certificate_to_ptf(ptfhost) + + apply_cert_config(duthost) + + # Verify certificate date on DUT + cert_date_on_dut(duthost) + + # Verify GNMI capabilities to validate functionality + ret, msg = gnmi_capabilities(duthost, localhost) + assert ret == 0, msg + assert "sonic-db" in msg, msg + assert "JSON_IETF" in msg, msg