2
0
mirror of https://github.com/boostorg/redis.git synced 2026-01-19 04:42:09 +00:00

Merge pull request #174 from boostorg/168-no-way-to-specify-caclient-certificate-for-ssl-connections

Provides a way of passing a custom ssl context to the connection.
This commit is contained in:
Marcelo
2024-01-03 17:20:00 +01:00
committed by GitHub
6 changed files with 62 additions and 40 deletions

View File

@@ -686,12 +686,12 @@ https://lists.boost.org/Archives/boost/2023/01/253944.php.
not.
* ([Issue 168](https://github.com/boostorg/redis/issues/168)).
Provides SSL context getters. The user wants to be able to pass the
`ssl::context` in the connection constructor as is done in Boost.Beast
and Boost.MySql. However, doing so would penalize users on plain
connections, which would have to start passing a dummy context on
every instantiation. If there is more convincing argument I will
change this in the future.
Provides a way of passing a custom SSL context to the connection.
The design here differs from that of Boost.Beast and Boost.MySql
since in Boost.Redis the connection owns the context instead of only
storing a reference to a user provided one. This is ok so because
apps need only one connection for their entire application, which
makes the overhead of one ssl-context per connection negligible.
### Boost 1.84 (First release in Boost)

View File

@@ -10,8 +10,8 @@ macro(make_example EXAMPLE_NAME STANDARD)
if (${STANDARD} STREQUAL "20")
target_link_libraries(${EXAMPLE_NAME} PRIVATE examples_main)
endif()
if (${STANDARD} STREQUAL "20")
target_link_libraries(${EXAMPLE_NAME} PRIVATE Boost::json)
if (${EXAMPLE_NAME} STREQUAL "cpp20_json")
target_link_libraries(${EXAMPLE_NAME} PRIVATE Boost::json Boost::container_hash)
endif()
endmacro()

View File

@@ -86,13 +86,19 @@ public:
using other = basic_connection<Executor1>;
};
/// Contructs from an executor.
/** @brief Constructor
*
* @param ex Executor on which connection operation will run.
* @param ctx SSL context.
* @param max_read_size Maximum read size that is passed to
* the internal `asio::dynamic_buffer` constructor.
*/
explicit
basic_connection(
executor_type ex,
asio::ssl::context::method method = asio::ssl::context::tls_client,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)())
: impl_{ex, method, max_read_size}
: impl_{ex, std::move(ctx), max_read_size}
, timer_{ex}
{ }
@@ -100,9 +106,9 @@ public:
explicit
basic_connection(
asio::io_context& ioc,
asio::ssl::context::method method = asio::ssl::context::tls_client,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)())
: basic_connection(ioc.get_executor(), method, max_read_size)
: basic_connection(ioc.get_executor(), std::move(ctx), max_read_size)
{ }
/** @brief Starts underlying connection operations.
@@ -286,10 +292,6 @@ public:
auto const& get_ssl_context() const noexcept
{ return impl_.get_ssl_context();}
/// Returns the ssl context.
auto& get_ssl_context() noexcept
{ return impl_.get_ssl_context();}
/// Resets the underlying stream.
void reset_stream()
{ impl_.reset_stream(); }
@@ -343,14 +345,14 @@ public:
explicit
connection(
executor_type ex,
asio::ssl::context::method method = asio::ssl::context::tls_client,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)());
/// Contructs from a context.
explicit
connection(
asio::io_context& ioc,
asio::ssl::context::method method = asio::ssl::context::tls_client,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)());
/// Returns the underlying executor.
@@ -427,10 +429,6 @@ public:
auto const& get_ssl_context() const noexcept
{ return impl_.get_ssl_context();}
/// Returns the ssl context.
auto& get_ssl_context() noexcept
{ return impl_.get_ssl_context();}
private:
void
async_run_impl(

View File

@@ -394,9 +394,9 @@ public:
/// Constructs from an executor.
connection_base(
executor_type ex,
asio::ssl::context::method method,
asio::ssl::context ctx,
std::size_t max_read_size)
: ctx_{method}
: ctx_{std::move(ctx)}
, stream_{std::make_unique<next_layer_type>(ex, ctx_)}
, writer_timer_{ex}
, receive_channel_{ex, 256}
@@ -411,10 +411,6 @@ public:
auto const& get_ssl_context() const noexcept
{ return ctx_;}
/// Returns the ssl context.
auto& get_ssl_context() noexcept
{ return ctx_;}
/// Resets the underlying stream.
void reset_stream()
{

View File

@@ -10,16 +10,16 @@ namespace boost::redis {
connection::connection(
executor_type ex,
asio::ssl::context::method method,
asio::ssl::context ctx,
std::size_t max_read_size)
: impl_{ex, method, max_read_size}
: impl_{ex, std::move(ctx), max_read_size}
{ }
connection::connection(
asio::io_context& ioc,
asio::ssl::context::method method,
asio::ssl::context ctx,
std::size_t max_read_size)
: impl_{ioc.get_executor(), method, max_read_size}
: impl_{ioc.get_executor(), std::move(ctx), max_read_size}
{ }
void

View File

@@ -25,7 +25,7 @@ bool verify_certificate(bool, net::ssl::verify_context&)
return true;
}
BOOST_AUTO_TEST_CASE(ping)
config make_tls_config()
{
config cfg;
cfg.use_ssl = true;
@@ -34,7 +34,12 @@ BOOST_AUTO_TEST_CASE(ping)
cfg.addr.host = "db.occase.de";
cfg.addr.port = "6380";
//cfg.health_check_interval = std::chrono::seconds{0};
return cfg;
}
BOOST_AUTO_TEST_CASE(ping_internal_ssl_context)
{
auto const cfg = make_tls_config();
std::string const in = "Kabuf";
request req;
@@ -59,14 +64,37 @@ BOOST_AUTO_TEST_CASE(ping)
BOOST_CHECK_EQUAL(in, std::get<0>(resp).value());
}
BOOST_AUTO_TEST_CASE(ping_custom_ssl_context)
{
auto const cfg = make_tls_config();
std::string const in = "Kabuf";
request req;
req.push("PING", in);
response<std::string> resp;
net::io_context ioc;
net::ssl::context ctx{boost::asio::ssl::context::tls_client};
connection conn{ioc, std::move(ctx)};
conn.next_layer().set_verify_mode(net::ssl::verify_peer);
conn.next_layer().set_verify_callback(verify_certificate);
conn.async_exec(req, resp, [&](auto ec, auto) {
BOOST_TEST(!ec);
conn.cancel();
});
conn.async_run(cfg, {}, [](auto) { });
ioc.run();
BOOST_CHECK_EQUAL(in, std::get<0>(resp).value());
}
BOOST_AUTO_TEST_CASE(acl_does_not_allow_select)
{
config cfg;
cfg.use_ssl = true;
cfg.username = "aedis";
cfg.password = "aedis";
cfg.addr.host = "db.occase.de";
cfg.addr.port = "6380";
auto cfg = make_tls_config();
cfg.database_index = 22;
cfg.reconnect_wait_interval = std::chrono::seconds::zero();