Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/admin-guide/files/records.yaml.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4407,6 +4407,7 @@ Client-Related Configuration

.. ts:cv:: CONFIG proxy.config.ssl.client.CA.cert.path STRING NULL
:reloadable:
:overridable:

Specifies the location of the certificate authority file against
which the origin server will be verified.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ TSOverridableConfigKey Value Config
:enumerator:`TS_CONFIG_SSL_CLIENT_CERT_FILENAME` :ts:cv:`proxy.config.ssl.client.cert.filename`
:enumerator:`TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME` :ts:cv:`proxy.config.ssl.client.private_key.filename`
:enumerator:`TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME` :ts:cv:`proxy.config.ssl.client.CA.cert.filename`
:enumerator:`TS_CONFIG_SSL_CLIENT_CA_CERT_PATH` :ts:cv:`proxy.config.ssl.client.CA.cert.path`
:enumerator:`TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE` :ts:cv:`proxy.config.hostdb.ip_resolve`
:enumerator:`TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_INDEX` :ts:cv:`proxy.config.plugin.vc.default_buffer_index`
:enumerator:`TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_WATER_MARK` :ts:cv:`proxy.config.plugin.vc.default_buffer_water_mark`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ Enumeration Members
.. enumerator:: TS_CONFIG_SSL_CLIENT_SNI_POLICY
.. enumerator:: TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME
.. enumerator:: TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME
.. enumerator:: TS_CONFIG_SSL_CLIENT_CA_CERT_PATH
.. enumerator:: TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE
.. enumerator:: TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_INDEX
.. enumerator:: TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_WATER_MARK
Expand Down
1 change: 1 addition & 0 deletions include/cripts/Configs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ class Proxy
{
public:
cripts::StringConfig filename{"proxy.config.ssl.client.CA.cert.filename"};
cripts::StringConfig path{"proxy.config.ssl.client.CA.cert.path"};
}; // End class Cert

public:
Expand Down
2 changes: 2 additions & 0 deletions include/proxy/http/HttpConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ struct OverridableHttpConfigParams {
char *ssl_client_cert_filename = nullptr;
char *ssl_client_private_key_filename = nullptr;
char *ssl_client_ca_cert_filename = nullptr;
char *ssl_client_ca_cert_path = nullptr;
char *ssl_client_alpn_protocols = nullptr;

// Host Resolution order
Expand Down Expand Up @@ -1031,6 +1032,7 @@ inline HttpConfigParams::~HttpConfigParams()
ats_free(oride.ssl_client_cert_filename);
ats_free(oride.ssl_client_private_key_filename);
ats_free(oride.ssl_client_ca_cert_filename);
ats_free(oride.ssl_client_ca_cert_path);
ats_free(connect_ports_string);
ats_free(reverse_proxy_no_host_redirect);
ats_free(redirect_actions_string);
Expand Down
3 changes: 2 additions & 1 deletion include/proxy/http/OverridableConfigDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
X(HTTP_CONNECT_ATTEMPTS_RETRY_BACKOFF_BASE, connect_attempts_retry_backoff_base, "proxy.config.http.connect_attempts_retry_backoff_base", INT, GENERIC) \
X(HTTP_NEGATIVE_REVALIDATING_LIST, negative_revalidating_list, "proxy.config.http.negative_revalidating_list", STRING, HttpStatusCodeList_Conv) \
X(HTTP_CACHE_POST_METHOD, cache_post_method, "proxy.config.http.cache.post_method", INT, GENERIC) \
X(HTTP_CACHE_TARGETED_CACHE_CONTROL_HEADERS, targeted_cache_control_headers, "proxy.config.http.cache.targeted_cache_control_headers", STRING, TargetedCacheControlHeaders_Conv)
X(HTTP_CACHE_TARGETED_CACHE_CONTROL_HEADERS, targeted_cache_control_headers, "proxy.config.http.cache.targeted_cache_control_headers", STRING, TargetedCacheControlHeaders_Conv) \
X(SSL_CLIENT_CA_CERT_PATH, ssl_client_ca_cert_path, "proxy.config.ssl.client.CA.cert.path", STRING, NONE)

// clang-format on
1 change: 1 addition & 0 deletions include/ts/apidefs.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,7 @@ enum TSOverridableConfigKey {
TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIST,
TS_CONFIG_HTTP_CACHE_POST_METHOD,
TS_CONFIG_HTTP_CACHE_TARGETED_CACHE_CONTROL_HEADERS,
TS_CONFIG_SSL_CLIENT_CA_CERT_PATH,
TS_CONFIG_LAST_ENTRY,
};

Expand Down
9 changes: 9 additions & 0 deletions src/api/InkAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7545,6 +7545,11 @@ TSHttpTxnConfigStringSet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char
s->t_state.my_txn_conf().ssl_client_ca_cert_filename = const_cast<char *>(value);
}
break;
case TS_CONFIG_SSL_CLIENT_CA_CERT_PATH:
if (value && length > 0) {
s->t_state.my_txn_conf().ssl_client_ca_cert_path = const_cast<char *>(value);
}
break;
case TS_CONFIG_SSL_CLIENT_ALPN_PROTOCOLS:
if (value && length > 0) {
s->t_state.my_txn_conf().ssl_client_alpn_protocols = const_cast<char *>(value);
Expand Down Expand Up @@ -7624,6 +7629,10 @@ TSHttpTxnConfigStringGet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char
*value = sm->t_state.txn_conf->server_session_sharing_match_str;
*length = *value ? strlen(*value) : 0;
break;
case TS_CONFIG_SSL_CLIENT_CA_CERT_PATH:
*value = sm->t_state.txn_conf->ssl_client_ca_cert_path;
*length = *value ? strlen(*value) : 0;
break;
default: {
MgmtConverter const *conv;
const void *src = _conf_to_memberp(conf, sm->t_state.txn_conf, conv);
Expand Down
30 changes: 23 additions & 7 deletions src/iocore/net/SSLNetVConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ DbgCtl dbg_ctl_ssl_alpn{"ssl_alpn"};
DbgCtl dbg_ctl_ssl_origin_session_cache{"ssl.origin_session_cache"};
DbgCtl dbg_ctl_proxyprotocol{"proxyprotocol"};

const char *
resolve_client_ca_cert_path(const SSLConfigParams *params, const char *path, std::string &storage)
{
if (path == nullptr) {
return params->clientCACertPath;
}

storage = Layout::get()->relative_to(Layout::get()->prefix, path);
return storage.c_str();
}

} // namespace

//
Expand Down Expand Up @@ -1129,6 +1140,8 @@ SSLNetVConnection::_sslStartHandShake(int event, int &err)
auto nps = sniParam->get_property_config(serverKey);
shared_SSL_CTX sharedCTX = nullptr;
SSL_CTX *clientCTX = nullptr;
std::string caCertPathStorage;
const char *caCertPath = resolve_client_ca_cert_path(params, options.ssl_client_ca_cert_path, caCertPathStorage);

// First Look to see if there are override parameters
Dbg(dbg_ctl_ssl, "Checking for outbound client cert override [%p]", options.ssl_client_cert_name.get());
Expand All @@ -1144,18 +1157,21 @@ SSLNetVConnection::_sslStartHandShake(int event, int &err)
keyFilePath = Layout::get()->relative_to(params->clientKeyPathOnly, options.ssl_client_private_key_name);
}
if (options.ssl_client_ca_cert_name) {
caCertFilePath = Layout::get()->relative_to(params->clientCACertPath, options.ssl_client_ca_cert_name);
caCertFilePath = Layout::get()->relative_to(caCertPath, options.ssl_client_ca_cert_name);
}
Dbg(dbg_ctl_ssl, "Using outbound client cert `%s'", options.ssl_client_cert_name.get());
} else {
Dbg(dbg_ctl_ssl, "Clearing outbound client cert");
}
sharedCTX =
params->getCTX(certFilePath, keyFilePath, caCertFilePath.empty() ? params->clientCACertFilename : caCertFilePath.c_str(),
params->clientCACertPath);
} else if (options.ssl_client_ca_cert_name) {
std::string caCertFilePath = Layout::get()->relative_to(params->clientCACertPath, options.ssl_client_ca_cert_name);
sharedCTX = params->getCTX(params->clientCertPath, params->clientKeyPath, caCertFilePath.c_str(), params->clientCACertPath);
sharedCTX = params->getCTX(certFilePath, keyFilePath,
caCertFilePath.empty() ? params->clientCACertFilename : caCertFilePath.c_str(), caCertPath);
} else if (options.ssl_client_ca_cert_name || options.ssl_client_ca_cert_path) {
std::string caCertFilePath;
if (options.ssl_client_ca_cert_name) {
caCertFilePath = Layout::get()->relative_to(caCertPath, options.ssl_client_ca_cert_name);
}
sharedCTX = params->getCTX(params->clientCertPath, params->clientKeyPath,
caCertFilePath.empty() ? params->clientCACertFilename : caCertFilePath.c_str(), caCertPath);
} else if (nps && !nps->client_cert_file.empty()) {
// If no overrides available, try the available nextHopProperty by reading from context mappings
sharedCTX =
Expand Down
1 change: 1 addition & 0 deletions src/proxy/http/HttpSM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5804,6 +5804,7 @@ HttpSM::do_http_server_open(bool raw, bool only_direct)
opt.set_ssl_client_cert_name(t_state.txn_conf->ssl_client_cert_filename);
opt.ssl_client_private_key_name = t_state.txn_conf->ssl_client_private_key_filename;
opt.ssl_client_ca_cert_name = t_state.txn_conf->ssl_client_ca_cert_filename;
opt.ssl_client_ca_cert_path = t_state.txn_conf->ssl_client_ca_cert_path;
if (is_private()) {
// If the connection to origin is private, don't try to negotiate the higher overhead H2
opt.alpn_protocols_array_size = -1;
Expand Down
1 change: 1 addition & 0 deletions src/proxy/http/PreWarmManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ PreWarmSM::_connect(const IpEndpoint &addr)
opt.ssl_client_cert_name = http_conf_params->oride.ssl_client_cert_filename;
opt.ssl_client_private_key_name = http_conf_params->oride.ssl_client_private_key_filename;
opt.ssl_client_ca_cert_name = http_conf_params->oride.ssl_client_ca_cert_filename;
opt.ssl_client_ca_cert_path = http_conf_params->oride.ssl_client_ca_cert_path;

SCOPED_MUTEX_LOCK(lock, mutex, this_ethread());
connect_action_handle = sslNetProcessor.connect_re(this, &addr.sa, opt);
Expand Down
25 changes: 16 additions & 9 deletions tests/gold_tests/tls/tls_verify_ca_override.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# limitations under the License.

Test.Summary = '''
Test tls server certificate verification options. Exercise conf_remap for ca bundle
Test tls server certificate verification options. Exercise conf_remap for ca bundle path and file.
'''

# Define default ATS
Expand Down Expand Up @@ -58,18 +58,25 @@
ts.addSSLfile("ssl/signer2.pem")
ts.addSSLfile("ssl/signer2.key")


def ca_cert_overrides(filename):
return (
f'@pparam=proxy.config.ssl.client.CA.cert.path={ts.Variables.SSLDir} '
f'@pparam=proxy.config.ssl.client.CA.cert.filename={filename}')


ts.Disk.remap_config.AddLine(
'map /case1 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.CA.cert.filename={1}/{2}'.format(
server1.Variables.SSL_Port, ts.Variables.SSLDir, "signer.pem"))
f'map /case1 https://127.0.0.1:{server1.Variables.SSL_Port}/ '
f'@plugin=conf_remap.so {ca_cert_overrides("signer.pem")}')
ts.Disk.remap_config.AddLine(
'map /badcase1 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.CA.cert.filename={1}/{2}'.format(
server1.Variables.SSL_Port, ts.Variables.SSLDir, "signer2.pem"))
f'map /badcase1 https://127.0.0.1:{server1.Variables.SSL_Port}/ '
f'@plugin=conf_remap.so {ca_cert_overrides("signer2.pem")}')
ts.Disk.remap_config.AddLine(
'map /case2 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.CA.cert.filename={1}/{2}'.format(
server2.Variables.SSL_Port, ts.Variables.SSLDir, "signer2.pem"))
f'map /case2 https://127.0.0.1:{server2.Variables.SSL_Port}/ '
f'@plugin=conf_remap.so {ca_cert_overrides("signer2.pem")}')
ts.Disk.remap_config.AddLine(
'map /badcase2 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.CA.cert.filename={1}/{2}'.format(
server2.Variables.SSL_Port, ts.Variables.SSLDir, "signer.pem"))
f'map /badcase2 https://127.0.0.1:{server2.Variables.SSL_Port}/ '
f'@plugin=conf_remap.so {ca_cert_overrides("signer.pem")}')

ts.Disk.ssl_multicert_yaml.AddLines(
"""
Expand Down