From 6563e397c55396d8dbeb48c6cf09a564e948af79 Mon Sep 17 00:00:00 2001 From: Kenneth Giusti Date: Mon, 30 Sep 2024 09:23:13 -0400 Subject: [PATCH] fixup: workaround bad password openssl issue --- tests/system_tests_ssl.py | 106 ++++++++++++++++++-- tests/system_tests_tcp_adaptor_tls.py | 134 +++++++------------------- 2 files changed, 129 insertions(+), 111 deletions(-) diff --git a/tests/system_tests_ssl.py b/tests/system_tests_ssl.py index 76f6040c7..605ce8d1a 100644 --- a/tests/system_tests_ssl.py +++ b/tests/system_tests_ssl.py @@ -1030,6 +1030,25 @@ def setUpClass(cls): cls.listener1_port = cls.tester.get_port() cls.listener2_port = cls.tester.get_port() + # default TLS configurations + cls.profile_L1_cfg = { + 'caCertFile': CA_CERT, + 'certFile': SERVER_CERTIFICATE, + 'privateKeyFile': SERVER_PRIVATE_KEY, + 'password': SERVER_PRIVATE_KEY_PASSWORD + } + cls.profile_L2_cfg = { + 'caCertFile': CA2_CERT, + 'certFile': SERVER2_CERTIFICATE, + 'privateKeyFile': SERVER2_PRIVATE_KEY, + 'password': SERVER2_PRIVATE_KEY_PASSWORD + } + + ssl_profile_L1 = {'name': 'ssl-profile-L1'} + ssl_profile_L1.update(cls.profile_L1_cfg) + ssl_profile_L2 = {'name': 'ssl-profile-L2'} + ssl_profile_L2.update(cls.profile_L2_cfg) + router_cfg = Qdrouterd.Config([ ('router', {'id': 'Router1', 'mode': 'interior'}), @@ -1038,11 +1057,7 @@ def setUpClass(cls): 'port': cls.tester.get_port()}), # Listener1 - ('sslProfile', {'name': 'ssl-profile-L1', - 'caCertFile': CA_CERT, - 'certFile': SERVER_CERTIFICATE, - 'privateKeyFile': SERVER_PRIVATE_KEY, - 'password': SERVER_PRIVATE_KEY_PASSWORD}), + ('sslProfile', ssl_profile_L1), ('listener', {'name': 'Listener1', 'host': 'localhost', 'role': 'normal', @@ -1054,11 +1069,7 @@ def setUpClass(cls): 'sslProfile': 'ssl-profile-L1'}), # Listener2 - ('sslProfile', {'name': 'ssl-profile-L2', - 'caCertFile': CA2_CERT, - 'certFile': SERVER2_CERTIFICATE, - 'privateKeyFile': SERVER2_PRIVATE_KEY, - 'password': SERVER2_PRIVATE_KEY_PASSWORD}), + ('sslProfile', ssl_profile_L2), ('listener', {'name': 'Listener2', 'host': 'localhost', 'role': 'normal', @@ -1195,6 +1206,81 @@ def test_ssl_client_profile_update(self): msg = test_rx.queue.get() self.assertIn("TLS Message!", msg.body, "missing payload") + # restore original sslProfile configurations + self.router1.sk_manager.update(SSL_PROFILE_TYPE, self.profile_L1_cfg, name='ssl-profile-L1') + self.router1.sk_manager.update(SSL_PROFILE_TYPE, self.profile_L2_cfg, name='ssl-profile-L2') + + def test_ssl_client_profile_update_load(self): + """ + Test sslProfile updates while under client load + """ + + payload = "?" * 1024 * 65 + payload += "TLS Message!" + message = Message(body=payload) + + ssl_domain = SSLDomain(SSLDomain.MODE_CLIENT) + ssl_domain.set_trusted_ca_db(CA_CERT) + ssl_domain.set_peer_authentication(SSLDomain.VERIFY_PEER_NAME, CA_CERT) + ssl_domain.set_credentials(CLIENT_CERTIFICATE, CLIENT_PRIVATE_KEY, CLIENT_PRIVATE_KEY_PASSWORD) + conn_args = {'sasl_enabled': True, + 'allowed_mechs': "EXTERNAL", + 'ssl_domain': ssl_domain} + test_rx = AsyncTestReceiver(f"amqps://localhost:{self.listener1_port}", + source="test/addr", + container_id="FooRx", + conn_args=conn_args) + + ssl_domain = SSLDomain(SSLDomain.MODE_CLIENT) + ssl_domain.set_trusted_ca_db(CA2_CERT) + ssl_domain.set_peer_authentication(SSLDomain.VERIFY_PEER_NAME, CA2_CERT) + ssl_domain.set_credentials(CLIENT2_CERTIFICATE, CLIENT2_PRIVATE_KEY, CLIENT2_PRIVATE_KEY_PASSWORD) + conn_args = {'sasl_enabled': True, + 'allowed_mechs': "EXTERNAL", + 'ssl_domain': ssl_domain} + + clients = [] + for test in range(10): + + # Expect failure + bad_ssl_domain = SSLDomain(SSLDomain.MODE_CLIENT) + bad_ssl_domain.set_trusted_ca_db(CA_CERT) + bad_ssl_domain.set_peer_authentication(SSLDomain.VERIFY_PEER_NAME, CA_CERT) + bad_ssl_domain.set_credentials(CLIENT_CERTIFICATE, CLIENT_PRIVATE_KEY, CLIENT_PRIVATE_KEY_PASSWORD) + bad_conn_args = {'sasl_enabled': True, + 'allowed_mechs': "EXTERNAL", + 'ssl_domain': bad_ssl_domain} + + with self.assertRaises(Exception) as exc: + test_tx = AsyncTestSender(f"amqps://localhost:{self.listener2_port}", + target="test/addr", + message=message, + container_id=f"BADTX{test}", + conn_args=bad_conn_args, + get_link_info=False) + test_tx.wait() + + for c_index in range(4): + c_id = f"FooTx-{c_index}" + test_tx = AsyncTestSender(f"amqps://localhost:{self.listener2_port}", + target="test/addr", + message=message, + container_id=c_id, + conn_args=conn_args, + get_link_info=False) + clients.append(test_tx) + + self.router1.sk_manager.update(SSL_PROFILE_TYPE, self.profile_L2_cfg, name='ssl-profile-L2') + + for client in clients: + client.wait() + + test_rx.stop() + self.assertEqual(40, test_rx.num_queue_puts, "expected 40 messages") + for count in range(40): + msg = test_rx.queue.get() + self.assertIn("TLS Message!", msg.body, "missing payload") + class RouterTestSslProfileDeleteClients(RouterTestSslBase): """ diff --git a/tests/system_tests_tcp_adaptor_tls.py b/tests/system_tests_tcp_adaptor_tls.py index 03250f564..0a136450e 100644 --- a/tests/system_tests_tcp_adaptor_tls.py +++ b/tests/system_tests_tcp_adaptor_tls.py @@ -864,25 +864,25 @@ def test_ssl_profile_update(self): openssl_server.wait_out_message("Sanity Check the Configuration!") # - # Attempt to update the listener-side sslProfile with the wrong - # password. This should cause new client connections to fail due to + # Attempt to update the listener-side sslProfile with a bad + # CA cert file. Verify that the management operation fails # the configuration error. # skmgr_a = self.router_qdra.sk_manager with self.assertRaises(Exception) as emgr: - skmgr_a.update(SSL_PROFILE_TYPE, {'password': 'badpassword'}, + skmgr_a.update(SSL_PROFILE_TYPE, + {'caCertFile': '/this/file/does/not/exist.pem'}, name='listener-ssl-profile') - self.assertIn('Failed to set TLS certFile', str(emgr.exception)) + self.assertIn('Failed to configure TLS caCertFile', str(emgr.exception)) # # Restore the proper password and verify clients can connect # - skmgr_a.update(SSL_PROFILE_TYPE, {'password': - SERVER_PRIVATE_KEY_PASSWORD}, + skmgr_a.update(SSL_PROFILE_TYPE, {'caCertFile': CA_CERT}, name='listener-ssl-profile') out = skmgr_a.read(name='listener-ssl-profile') @@ -986,99 +986,6 @@ def test_ssl_profile_update(self): skmgr_a.update(SSL_PROFILE_TYPE, self.listener_profile_cfg, name='listener-ssl-profile') skmgr_b.update(SSL_PROFILE_TYPE, self.connector_profile_cfg, name='connector-ssl-profile') - def test_ssl_profile_update_dummy(self): - """ - Test only - remove - """ - payload = b'?' * 1024 * 65 - server_ssl_info_1 = dict() - server_ssl_info_1['CA_CERT'] = CA_CERT - server_ssl_info_1['SERVER_CERTIFICATE'] = SERVER_CERTIFICATE - server_ssl_info_1['SERVER_PRIVATE_KEY'] = SERVER_PRIVATE_KEY - server_ssl_info_1['SERVER_PRIVATE_KEY_PASSWORD'] = SERVER_PRIVATE_KEY_PASSWORD - - server_ssl_info_2 = dict() - server_ssl_info_2['CA_CERT'] = CA2_CERT - server_ssl_info_2['SERVER_CERTIFICATE'] = SERVER2_CERTIFICATE - server_ssl_info_2['SERVER_PRIVATE_KEY'] = SERVER2_PRIVATE_KEY - server_ssl_info_2['SERVER_PRIVATE_KEY_PASSWORD'] = SERVER2_PRIVATE_KEY_PASSWORD - - client_ssl_info_1 = dict() - client_ssl_info_1['CA_CERT'] = CA_CERT - client_ssl_info_1['CLIENT_CERTIFICATE'] = CLIENT_CERTIFICATE - client_ssl_info_1['CLIENT_PRIVATE_KEY'] = CLIENT_PRIVATE_KEY - client_ssl_info_1['CLIENT_PRIVATE_KEY_PASSWORD'] = CLIENT_PRIVATE_KEY_PASSWORD - - client_ssl_info_2 = dict() - client_ssl_info_2['CA_CERT'] = CA2_CERT - client_ssl_info_2['CLIENT_CERTIFICATE'] = CLIENT2_CERTIFICATE - client_ssl_info_2['CLIENT_PRIVATE_KEY'] = CLIENT2_PRIVATE_KEY - client_ssl_info_2['CLIENT_PRIVATE_KEY_PASSWORD'] = CLIENT2_PRIVATE_KEY_PASSWORD - - server_port = self.tester.get_port() - server_create = self.tester.openssl_server - - # verify SSL1 to SSL1 - openssl_server = server_create(listening_port=server_port, - ssl_info=server_ssl_info_1, - name="OpenSSLServerAuthPeerDummy", - cl_args=self.s_server_args) - - out, error = self.opensslclient(port=server_port, - ssl_info=client_ssl_info_1, - data=b"Sanity Check the Configuration!" + payload, - cl_args=self.s_client_args) - self.assertIn(b"Verification: OK", out, f"{error}") - self.assertIn(b"Verify return code: 0 (ok)", out, f"{error}") - openssl_server.wait_out_message("Sanity Check the Configuration!") - - # SSL2 to SSL1 fails - - out, error = self.opensslclient(port=server_port, - ssl_info=client_ssl_info_2, - data=b"This should not succeed!" + payload, - expect=Process.EXIT_FAIL, - cl_args=self.s_client_args) - openssl_server.wait_out_message("ERROR") - - # Retest SSL1 to SSL1 ok - - out, error = self.opensslclient(port=server_port, - ssl_info=client_ssl_info_1, - data=b"This SSL1 to SSL1 should work!" + payload, - cl_args=self.s_client_args) - self.assertIn(b"Verification: OK", out, f"{error}") - self.assertIn(b"Verify return code: 0 (ok)", out, f"{error}") - openssl_server.wait_out_message("This SSL1 to SSL1 should work!") - - openssl_server.teardown() - - openssl_server = server_create(listening_port=server_port, - ssl_info=server_ssl_info_2, - name="OpenSSLServerAuthPeerDummy", - cl_args=self.s_server_args) - - # SSL1 to SSL2 fails - - out, error = self.opensslclient(port=server_port, - ssl_info=client_ssl_info_1, - data=b"This should not succeed!" + payload, - expect=Process.EXIT_FAIL, - cl_args=self.s_client_args) - openssl_server.wait_out_message("ERROR") - - # SSL2 to SSL2 ok - - out, error = self.opensslclient(port=server_port, - ssl_info=client_ssl_info_2, - data=b"This SSL2 to SSL2 should work!" + payload, - cl_args=self.s_client_args) - self.assertIn(b"Verification: OK", out, f"{error}") - self.assertIn(b"Verify return code: 0 (ok)", out, f"{error}") - openssl_server.wait_out_message("This SSL2 to SSL2 should work!") - - openssl_server.teardown() - def test_ssl_profile_update_load(self): """ Test sslProfile updates while under client load @@ -1111,11 +1018,35 @@ def test_ssl_profile_update_load(self): echo_server.logger.dump() self.assertTrue(echo_server.is_running, "Echo Server failed to start") + # Negative test - expect failure + + bad_ssl_info = {'CLIENT_CERTIFICATE': CLIENT2_CERTIFICATE, + 'CLIENT_PRIVATE_KEY': CLIENT2_PRIVATE_KEY, + 'CLIENT_PRIVATE_KEY_PASSWORD': CLIENT2_PRIVATE_KEY_PASSWORD, + 'CA_CERT': CA2_CERT} + + client_name = "SslProfileEchoClientBAD" + client_logger = Logger(title=client_name, + print_to_console=False, + ofilename=os.path.join(os.path.dirname(os.getcwd()), + f"{client_name}.log")) + with self.assertRaises(Exception) as exc: + bad_client = TcpEchoClient(prefix=client_name, + host='localhost', + port=self.router_listener_port, + size=5000, + count=10, + logger=client_logger, + ssl_info=bad_ssl_info) + bad_client.wait() + + # now test multiple simultaineous clients while updating the sslProfile + clients = [] for test in range(10): - for c_index in range(2): - client_name = f"SslProfileEchoClient-{test}-{c_index}" + for c_index in range(4): + client_name = f"SslProfileEchoClient-{test}-{c_index}-A" client_logger = Logger(title=client_name, print_to_console=False, ofilename=os.path.join(os.path.dirname(os.getcwd()), @@ -1128,6 +1059,7 @@ def test_ssl_profile_update_load(self): logger=client_logger, ssl_info=client_ssl_info) clients.append(echo_client) + skmgr_a.update(SSL_PROFILE_TYPE, self.listener_profile_cfg, name='listener-ssl-profile') skmgr_b.update(SSL_PROFILE_TYPE, self.connector_profile_cfg, name='connector-ssl-profile')