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:
12
README.md
12
README.md
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user