You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sh...@apache.org on 2018/10/30 20:56:27 UTC

[trafficserver] branch master updated: Enable reloadable records.config client cert settings

This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new d483f49  Enable reloadable records.config client cert settings
d483f49 is described below

commit d483f4958fb642365b7d57d96906051dd1ae53f1
Author: Susan Hinrichs <sh...@oath.com>
AuthorDate: Tue Oct 23 13:47:43 2018 +0000

    Enable reloadable records.config client cert settings
---
 doc/admin-guide/files/records.config.en.rst  |   4 +
 iocore/net/SSLConfig.cc                      |  13 ++-
 mgmt/RecordsConfig.cc                        |   8 +-
 tests/gold_tests/tls/tls_client_cert.test.py | 154 +++++++++++++++++++--------
 4 files changed, 125 insertions(+), 54 deletions(-)

diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 152bf73..cc0c46b 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -3497,21 +3497,25 @@ Client-Related Configuration
    :2: The provided certificate will be verified and the connection will be established 
 
 .. ts:cv:: CONFIG proxy.config.ssl.client.cert.filename STRING NULL
+   :reloadable:
 
    The filename of SSL client certificate installed on |TS|.
 
 .. ts:cv:: CONFIG proxy.config.ssl.client.cert.path STRING /config
+   :reloadable:
 
    The location of the SSL client certificate installed on Traffic
    Server.
 
 .. ts:cv:: CONFIG proxy.config.ssl.client.private_key.filename STRING NULL
+   :reloadable:
 
    The filename of the |TS| private key. Change this variable
    only if the private key is not located in the |TS| SSL
    client certificate file.
 
 .. ts:cv:: CONFIG proxy.config.ssl.client.private_key.path STRING NULL
+   :reloadable:
 
    The location of the |TS| private key. Change this variable
    only if the private key is not located in the SSL client certificate
diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc
index f2290c9..018cfcf 100644
--- a/iocore/net/SSLConfig.cc
+++ b/iocore/net/SSLConfig.cc
@@ -68,7 +68,9 @@ char *SSLConfigParams::ssl_wire_trace_server_name = nullptr;
 int SSLConfigParams::async_handshake_enabled      = 0;
 char *SSLConfigParams::engine_conf_file           = nullptr;
 
-static ConfigUpdateHandler<SSLCertificateConfig> *sslCertUpdate;
+static std::unique_ptr<ConfigUpdateHandler<SSLCertificateConfig>> sslCertUpdate;
+static std::unique_ptr<ConfigUpdateHandler<SSLConfig>> sslConfigUpdate;
+static std::unique_ptr<ConfigUpdateHandler<SSLTicketKeyConfig>> sslTicketKey;
 
 // Check if the ticket_key callback #define is available, and if so, enable session tickets.
 #ifdef SSL_CTX_set_tlsext_ticket_key_cb
@@ -496,6 +498,11 @@ SSLConfigParams::getClientSSL_CTX() const
 void
 SSLConfig::startup()
 {
+  sslConfigUpdate.reset(new ConfigUpdateHandler<SSLConfig>());
+  sslConfigUpdate->attach("proxy.config.ssl.client.cert.path");
+  sslConfigUpdate->attach("proxy.config.ssl.client.cert.filename");
+  sslConfigUpdate->attach("proxy.config.ssl.client.private_key.path");
+  sslConfigUpdate->attach("proxy.config.ssl.client.private_key.filename");
   reconfigure();
 }
 
@@ -523,7 +530,7 @@ SSLConfig::release(SSLConfigParams *params)
 bool
 SSLCertificateConfig::startup()
 {
-  sslCertUpdate = new ConfigUpdateHandler<SSLCertificateConfig>();
+  sslCertUpdate.reset(new ConfigUpdateHandler<SSLCertificateConfig>());
   sslCertUpdate->attach("proxy.config.ssl.server.multicert.filename");
   sslCertUpdate->attach("proxy.config.ssl.server.cert.path");
   sslCertUpdate->attach("proxy.config.ssl.server.private_key.path");
@@ -654,7 +661,7 @@ SSLTicketParams::LoadTicketData(char *ticket_data, int ticket_data_len)
 void
 SSLTicketKeyConfig::startup()
 {
-  auto sslTicketKey = new ConfigUpdateHandler<SSLTicketKeyConfig>();
+  sslTicketKey.reset(new ConfigUpdateHandler<SSLTicketKeyConfig>());
 
   sslTicketKey->attach("proxy.config.ssl.server.ticket_key.filename");
   SSLConfig::scoped_config params;
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index c1dedd6..a03324f 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1134,13 +1134,13 @@ static const RecordElement RecordsConfig[] =
   ,
   {RECT_CONFIG, "proxy.config.ssl.client.verify.server.properties", RECD_STRING, "ALL", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
-  {RECT_CONFIG, "proxy.config.ssl.client.cert.filename", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_STR, "^[^[:space:]]*$", RECA_NULL}
+  {RECT_CONFIG, "proxy.config.ssl.client.cert.filename", RECD_STRING, nullptr, RECU_DYNAMIC, RR_NULL, RECC_STR, "^[^[:space:]]*$", RECA_NULL}
   ,
-  {RECT_CONFIG, "proxy.config.ssl.client.cert.path", RECD_STRING, TS_BUILD_SYSCONFDIR, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  {RECT_CONFIG, "proxy.config.ssl.client.cert.path", RECD_STRING, TS_BUILD_SYSCONFDIR, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
-  {RECT_CONFIG, "proxy.config.ssl.client.private_key.filename", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_STR, "^[^[:space:]]*$", RECA_NULL}
+  {RECT_CONFIG, "proxy.config.ssl.client.private_key.filename", RECD_STRING, nullptr, RECU_DYNAMIC, RR_NULL, RECC_STR, "^[^[:space:]]*$", RECA_NULL}
   ,
-  {RECT_CONFIG, "proxy.config.ssl.client.private_key.path", RECD_STRING, TS_BUILD_SYSCONFDIR, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  {RECT_CONFIG, "proxy.config.ssl.client.private_key.path", RECD_STRING, TS_BUILD_SYSCONFDIR, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.ssl.client.CA.cert.filename", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_STR, "^[^[:space:]]*$", RECA_NULL}
   ,
diff --git a/tests/gold_tests/tls/tls_client_cert.test.py b/tests/gold_tests/tls/tls_client_cert.test.py
index 4ebec4a..1973031 100644
--- a/tests/gold_tests/tls/tls_client_cert.test.py
+++ b/tests/gold_tests/tls/tls_client_cert.test.py
@@ -144,9 +144,10 @@ trbarfail.Processes.Default.TimeOut = 5
 trbarfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
 trbarfail.TimeOut = 5
 
-tr2 = Test.AddTestRun("Update client cert file and reload")
+tr2 = Test.AddTestRun("Update config files")
 # Update the SNI config
 snipath = ts.Disk.ssl_server_name_yaml.AbsPath
+recordspath = ts.Disk.records_config.AbsPath
 tr2.Disk.File(snipath, id = "ssl_server_name_yaml", typename="ats:config"),
 tr2.Disk.ssl_server_name_yaml.AddLine(
     '- fqdn: bar.com')
@@ -154,24 +155,52 @@ tr2.Disk.ssl_server_name_yaml.AddLine(
     '  client_cert: {0}/signed-bar.pem'.format(ts.Variables.SSLDir))
 tr2.Disk.ssl_server_name_yaml.AddLine(
     '  client_key: {0}/signed-bar.key'.format(ts.Variables.SSLDir))
+# recreate the records.config with the cert filename changed
+tr2.Disk.File(recordspath, id = "records_config", typename="ats:config:records"),
+tr2.Disk.records_config.update({
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'ssl|http',
+    'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.http.server_ports': '{0}'.format(ts.Variables.port),
+    'proxy.config.ssl.client.verify.server':  0,
+    'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2',
+    'proxy.config.ssl.client.cert.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.ssl.client.cert.filename': 'signed2-foo.pem',
+    'proxy.config.ssl.client.private_key.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.ssl.client.private_key.filename': 'signed-foo.key',
+    'proxy.config.url_remap.pristine_host_hdr' : 1,
+})
 tr2.StillRunningAfter = ts
 tr2.StillRunningAfter = server
 tr2.StillRunningAfter = server2
-tr2.Processes.Default.Command = 'traffic_ctl config set proxy.config.ssl.client.cert.filename signed2-foo.pem; traffic_ctl config reload'
+tr2.Processes.Default.Command = 'echo Updated configs'
 # Need to copy over the environment so traffic_ctl knows where to find the unix domain socket
 tr2.Processes.Default.Env = ts.Env
 tr2.Processes.Default.ReturnCode = 0
 tr2.Processes.Default.TimeOut = 5
 tr2.TimeOut = 5
 
+tr2reload = Test.AddTestRun("Reload config")
+tr2reload.StillRunningAfter = ts
+tr2reload.StillRunningAfter = server
+tr2reload.StillRunningAfter = server2
+tr2reload.Processes.Default.Command = 'traffic_ctl config reload'
+# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket
+tr2reload.Processes.Default.Env = ts.Env
+tr2reload.Processes.Default.ReturnCode = 0
+tr2reload.Processes.Default.TimeOut = 5
+tr2reload.TimeOut = 5
+
+
 #Should succeed
 tr3bar = Test.AddTestRun("Make request with other bar cert to first server")
 # Wait for the reload to complete
-tr3bar.DelayStart = 2
+tr3bar.DelayStart = 10
 tr3bar.StillRunningAfter = ts
 tr3bar.StillRunningAfter = server
 tr3bar.StillRunningAfter = server2
-tr3bar.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
+tr3bar.Processes.Default.Command = 'curl  -H host:bar.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
 tr3bar.Processes.Default.ReturnCode = 0
 tr3bar.Processes.Default.TimeOut = 5
 tr3bar.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Check response")
@@ -182,73 +211,104 @@ tr3barfail = Test.AddTestRun("Make request with other bar cert to second server"
 tr3barfail.StillRunningAfter = ts
 tr3barfail.StillRunningAfter = server
 tr3barfail.StillRunningAfter = server2
-tr3barfail.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
+tr3barfail.Processes.Default.Command = 'curl  -H host:bar.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
 tr3barfail.Processes.Default.ReturnCode = 0
 tr3barfail.Processes.Default.TimeOut = 5
 tr3barfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
 tr3barfail.TimeOut = 5
 
-# Skipping the last two cases until we get the certificate settings reloadable from records.config
-
 #Should succeed
-#tr3 = Test.AddTestRun("Make request with other cert to second server")
+tr3 = Test.AddTestRun("Make request with other cert to second server")
 # Wait for the reload to complete
-#tr3.StillRunningAfter = ts
-#tr3.StillRunningAfter = server
-#tr3.StillRunningAfter = server2
-#tr3.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
-#tr3.Processes.Default.ReturnCode = 0
-#tr3.Processes.Default.TimeOut = 5
-#tr3.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Check response")
-#tr3.TimeOut = 5
-#
+tr3.StillRunningAfter = ts
+tr3.StillRunningAfter = server
+tr3.StillRunningAfter = server2
+tr3.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
+tr3.Processes.Default.ReturnCode = 0
+tr3.Processes.Default.TimeOut = 5
+tr3.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Check response")
+tr3.TimeOut = 5
+
 #Should fail
-#tr3fail = Test.AddTestRun("Make request with other cert to first server")
-#tr3fail.StillRunningAfter = ts
-#tr3fail.StillRunningAfter = server
-#tr3fail.StillRunningAfter = server2
-#tr3fail.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
-#tr3fail.Processes.Default.ReturnCode = 0
-#tr3fail.Processes.Default.TimeOut = 5
-#tr3fail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
-#tr3fail.TimeOut = 5
+tr3fail = Test.AddTestRun("Make request with other cert to first server")
+tr3fail.StillRunningAfter = ts
+tr3fail.StillRunningAfter = server
+tr3fail.StillRunningAfter = server2
+tr3fail.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
+tr3fail.Processes.Default.ReturnCode = 0
+tr3fail.Processes.Default.TimeOut = 5
+tr3fail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
+tr3fail.TimeOut = 5
+
 
 # Test the case of updating certificate contents without changing file name.
 trupdate = Test.AddTestRun("Update client cert file in place")
 trupdate.StillRunningAfter = ts
 trupdate.StillRunningAfter = server
 trupdate.StillRunningAfter = server2
-trupdate.Setup.CopyAs("ssl/signed2-bar.pem", ".", "signed-bar.pem")
+# Make a meaningless config change on the path so the records.config reload logic will trigger
+trupdate.Setup.CopyAs("ssl/signed2-bar.pem", ".", "{0}/signed-bar.pem".format(ts.Variables.SSLDir))
+# in the config/ssl directory for records.config
 trupdate.Setup.CopyAs("ssl/signed-foo.pem", ".", "{0}/signed2-foo.pem".format(ts.Variables.SSLDir))
-trupdate.Processes.Default.Command = 'traffic_ctl config reload'
+trupdate.Processes.Default.Command = 'traffic_ctl config set proxy.config.ssl.client.cert.path {0}/; touch {1}'.format(ts.Variables.SSLDir,snipath)
 # Need to copy over the environment so traffic_ctl knows where to find the unix domain socket
 trupdate.Processes.Default.Env = ts.Env
 trupdate.Processes.Default.ReturnCode = 0
 trupdate.Processes.Default.TimeOut = 5
-trupdate.TimeOut = 5
+
+trreload = Test.AddTestRun("Reload config after renaming certs")
+trreload.StillRunningAfter = ts
+trreload.StillRunningAfter = server
+trreload.StillRunningAfter = server2
+trreload.Processes.Default.Command = 'traffic_ctl config reload'
+trreload.Processes.Default.Env = ts.Env
+trreload.Processes.Default.ReturnCode = 0
+trreload.Processes.Default.TimeOut = 5
 
 #Should succeed
-tr3bar = Test.AddTestRun("Make request with renamed bar cert to first server")
+tr4bar = Test.AddTestRun("Make request with renamed bar cert to second server")
 # Wait for the reload to complete
-tr3bar.DelayStart = 2
-tr3bar.StillRunningAfter = ts
-tr3bar.StillRunningAfter = server
-tr3bar.StillRunningAfter = server2
-tr3bar.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
-tr3bar.Processes.Default.ReturnCode = 0
-tr3bar.Processes.Default.TimeOut = 5
-tr3bar.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Check response")
-tr3bar.TimeOut = 5
+tr4bar.DelayStart = 10
+tr4bar.StillRunningAfter = ts
+tr4bar.StillRunningAfter = server
+tr4bar.StillRunningAfter = server2
+tr4bar.Processes.Default.Command = 'curl  -H host:bar.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
+tr4bar.Processes.Default.ReturnCode = 0
+tr4bar.Processes.Default.TimeOut = 5
+tr4bar.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Check response")
+tr4bar.TimeOut = 5
 
 #Should fail
-tr3barfail = Test.AddTestRun("Make request with renamed bar cert to second server")
-tr3barfail.StillRunningAfter = ts
-tr3barfail.StillRunningAfter = server
-tr3barfail.StillRunningAfter = server2
-tr3barfail.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
-tr3barfail.Processes.Default.ReturnCode = 0
-tr3barfail.Processes.Default.TimeOut = 5
-tr3barfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
+tr4barfail = Test.AddTestRun("Make request with renamed bar cert to first server")
+tr4barfail.StillRunningAfter = ts
+tr4barfail.StillRunningAfter = server
+tr4barfail.StillRunningAfter = server2
+tr4barfail.Processes.Default.Command = 'curl  -H host:bar.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
+tr4barfail.Processes.Default.ReturnCode = 0
+tr4barfail.Processes.Default.TimeOut = 5
+tr4barfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
+
+#Should succeed
+tr4 = Test.AddTestRun("Make request with renamed foo cert to first server")
+tr4.StillRunningAfter = ts
+tr4.StillRunningAfter = server
+tr4.StillRunningAfter = server2
+tr4.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
+tr4.Processes.Default.ReturnCode = 0
+tr4.Processes.Default.TimeOut = 5
+tr4.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Check response")
+tr4.TimeOut = 5
+
+#Should fail
+tr4fail = Test.AddTestRun("Make request with renamed foo cert to second server")
+tr4fail.StillRunningAfter = ts
+tr4fail.StillRunningAfter = server
+tr4fail.StillRunningAfter = server2
+tr4fail.Processes.Default.Command = 'curl  -H host:example.com http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
+tr4fail.Processes.Default.ReturnCode = 0
+tr4fail.Processes.Default.TimeOut = 5
+tr4fail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Check response")
+tr4fail.TimeOut = 5
 
 # Allow for error messages in diags
 ts.Disk.diags_log.Content = Testers.ContainsExpression("ERROR", "Some connections should fail")