Skip to content

Commit 7446787

Browse files
authored
CXXCBC-739: Support mTLS Cert Refresh (without restart) (#857)
* CXXCBC-739: Support mTLS Cert Refresh (without restart) * Add locking to credentials * Update credentials for app telemetry * fix build * Optimise lock acquistion on constructors/assignment operators
1 parent 4952733 commit 7446787

14 files changed

+246
-48
lines changed

core/app_telemetry_reporter.cxx

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -671,30 +671,29 @@ class app_telemetry_reporter_impl
671671
{
672672
public:
673673
app_telemetry_reporter_impl(std::shared_ptr<app_telemetry_meter> meter,
674-
cluster_options options,
675-
cluster_credentials credentials,
674+
origin& origin,
676675
asio::io_context& ctx,
677676
asio::ssl::context& tls)
678677
: meter_{ std::move(meter) }
679-
, options_{ std::move(options) }
680-
, credentials_{ std::move(credentials) }
678+
, origin_{ origin }
681679
, ctx_{ ctx }
682680
, tls_{ tls }
683681
, backoff_{ ctx }
684682
, exponential_backoff_calculator_{
685683
std::chrono::milliseconds{ 100 },
686-
options_.app_telemetry_backoff_interval,
684+
origin_.options().app_telemetry_backoff_interval,
687685
2 /* backoff factor */,
688686
0.5 /* jitter factor */,
689687
}
690688
{
691-
if (options_.enable_app_telemetry) {
692-
if (!options_.app_telemetry_endpoint.empty()) {
693-
auto url = couchbase::core::utils::string_codec::url_parse(options_.app_telemetry_endpoint);
689+
if (origin_.options().enable_app_telemetry) {
690+
if (!origin_.options().app_telemetry_endpoint.empty()) {
691+
auto url =
692+
couchbase::core::utils::string_codec::url_parse(origin_.options().app_telemetry_endpoint);
694693
if (url.host.empty() || url.scheme != "ws") {
695694
CB_LOG_WARNING(
696695
"unable to use \"{}\" as a app telemetry endpoint (expected ws:// and hostname)",
697-
options_.app_telemetry_endpoint);
696+
origin_.options().app_telemetry_endpoint);
698697
return;
699698
}
700699
addresses_.push_back({
@@ -750,12 +749,12 @@ class app_telemetry_reporter_impl
750749
}));
751750
websocket_session_ = websocket_session::start(ctx_,
752751
address,
753-
credentials_,
752+
origin_.credentials(),
754753
std::move(stream),
755754
meter_,
756755
shared_from_this(),
757-
options_.app_telemetry_ping_interval,
758-
options_.app_telemetry_ping_timeout);
756+
origin_.options().app_telemetry_ping_interval,
757+
origin_.options().app_telemetry_ping_timeout);
759758
retry_backoff_calculator_ = &no_backoff_calculator_;
760759
++next_address_index_;
761760
}
@@ -813,25 +812,27 @@ class app_telemetry_reporter_impl
813812
return;
814813
}
815814
if (self->websocket_state_ == connection_state::disconnected) {
816-
self->dialer_ =
817-
telemetry_dialer::dial(next_address, self->options_, self->ctx_, self->tls_, self);
815+
self->dialer_ = telemetry_dialer::dial(
816+
next_address, self->origin_.options(), self->ctx_, self->tls_, self);
818817
}
819818
});
820819
return;
821820
}
822-
dialer_ = telemetry_dialer::dial(next_address, options_, ctx_, tls_, shared_from_this());
821+
dialer_ =
822+
telemetry_dialer::dial(next_address, origin_.options(), ctx_, tls_, shared_from_this());
823823
}
824824

825825
void update_config(topology::configuration&& config)
826826
{
827-
if (!options_.enable_app_telemetry) {
827+
if (!origin_.options().enable_app_telemetry) {
828828
meter_->disable();
829829
return;
830830
}
831831
meter_->update_config(config);
832832

833-
if (options_.app_telemetry_endpoint.empty()) {
834-
addresses_ = get_app_telemetry_addresses(config, options_.enable_tls, options_.network);
833+
if (origin_.options().app_telemetry_endpoint.empty()) {
834+
addresses_ = get_app_telemetry_addresses(
835+
config, origin_.options().enable_tls, origin_.options().network);
835836
next_address_index_ = 0;
836837
}
837838

@@ -841,15 +842,14 @@ class app_telemetry_reporter_impl
841842
meter_->enable();
842843
if (websocket_state_ == connection_state::disconnected) {
843844
dialer_ = telemetry_dialer::dial(
844-
addresses_[next_address_index_], options_, ctx_, tls_, shared_from_this());
845+
addresses_[next_address_index_], origin_.options(), ctx_, tls_, shared_from_this());
845846
}
846847
}
847848
}
848849

849850
private:
850851
std::shared_ptr<app_telemetry_meter> meter_;
851-
cluster_options options_;
852-
cluster_credentials credentials_;
852+
origin& origin_;
853853
asio::io_context& ctx_;
854854
asio::ssl::context& tls_;
855855
asio::steady_timer backoff_;
@@ -868,13 +868,10 @@ class app_telemetry_reporter_impl
868868
};
869869

870870
app_telemetry_reporter::app_telemetry_reporter(std::shared_ptr<app_telemetry_meter> meter,
871-
const cluster_options& options,
872-
const cluster_credentials& credentials,
871+
origin& origin,
873872
asio::io_context& ctx,
874873
asio::ssl::context& tls)
875-
: impl_{
876-
std::make_shared<app_telemetry_reporter_impl>(std::move(meter), options, credentials, ctx, tls)
877-
}
874+
: impl_{ std::make_shared<app_telemetry_reporter_impl>(std::move(meter), origin, ctx, tls) }
878875
{
879876
}
880877

core/app_telemetry_reporter.hxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#pragma once
1717

18+
#include "cluster.hxx"
1819
#include "config_listener.hxx"
1920

2021
#include <memory>
@@ -45,8 +46,7 @@ public:
4546
auto operator=(const app_telemetry_reporter&) -> app_telemetry_reporter& = delete;
4647

4748
app_telemetry_reporter(std::shared_ptr<app_telemetry_meter> meter,
48-
const cluster_options& options,
49-
const cluster_credentials& credentials,
49+
origin& origin,
5050
asio::io_context& ctx,
5151
asio::ssl::context& tls);
5252
~app_telemetry_reporter() override;

core/cluster.cxx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "core/app_telemetry_meter.hxx"
2525
#include "core/app_telemetry_reporter.hxx"
2626
#include "core/diagnostics.hxx"
27+
#include "core/error.hxx"
2728
#include "core/impl/get_replica.hxx"
2829
#include "core/impl/lookup_in_replica.hxx"
2930
#include "core/impl/observe_seqno.hxx"
@@ -521,6 +522,21 @@ class cluster_impl : public std::enable_shared_from_this<cluster_impl>
521522
return handler({});
522523
}
523524

525+
auto update_credentials(cluster_credentials auth) -> core::error
526+
{
527+
if (stopped_) {
528+
return { errc::network::cluster_closed, {} };
529+
}
530+
531+
if (auth.requires_tls() && !origin_.options().enable_tls) {
532+
return { errc::common::invalid_argument,
533+
"TLS not enabled but the provided authenticator requires TLS" };
534+
}
535+
536+
origin_.update_credentials(std::move(auth));
537+
return {};
538+
}
539+
524540
auto origin() const -> std::pair<std::error_code, couchbase::core::origin>
525541
{
526542
if (stopped_) {
@@ -1281,8 +1297,8 @@ class cluster_impl : public std::enable_shared_from_this<cluster_impl>
12811297

12821298
app_telemetry_meter_->update_agent(origin_.options().user_agent_extra);
12831299
session_manager_->set_app_telemetry_meter(app_telemetry_meter_);
1284-
app_telemetry_reporter_ = std::make_shared<app_telemetry_reporter>(
1285-
app_telemetry_meter_, origin_.options(), origin_.credentials(), ctx_, tls_);
1300+
app_telemetry_reporter_ =
1301+
std::make_shared<app_telemetry_reporter>(app_telemetry_meter_, origin_, ctx_, tls_);
12861302

12871303
if (origin_.options().enable_orphan_reporting) {
12881304
orphan_reporter_ = std::make_shared<orphan_reporter>(ctx_, origin_.options().orphan_options);
@@ -1437,6 +1453,15 @@ cluster::origin() const -> std::pair<std::error_code, couchbase::core::origin>
14371453
return { errc::network::cluster_closed, {} };
14381454
}
14391455

1456+
auto
1457+
cluster::update_credentials(core::cluster_credentials auth) -> core::error
1458+
{
1459+
if (impl_) {
1460+
return impl_->update_credentials(std::move(auth));
1461+
}
1462+
return { errc::network::cluster_closed, {} };
1463+
}
1464+
14401465
auto
14411466
cluster::io_context() const -> asio::io_context&
14421467
{

core/cluster.hxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#pragma once
1919

2020
#include "diagnostics.hxx"
21+
#include "error.hxx"
2122
#include "operations_fwd.hxx"
2223
#include "origin.hxx"
2324
#include "topology/configuration.hxx"
@@ -85,6 +86,8 @@ public:
8586
utils::movable_function<void(std::error_code, std::shared_ptr<topology::configuration>)>&&
8687
handler) const;
8788

89+
[[nodiscard]] auto update_credentials(core::cluster_credentials auth) -> core::error;
90+
8891
void execute(o::analytics_request request, mf<void(o::analytics_response)>&& handler) const;
8992
void execute(o::append_request request, mf<void(o::append_response)>&& handler) const;
9093
void execute(o::decrement_request request, mf<void(o::decrement_response)>&& handler) const;

core/cluster_credentials.cxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,11 @@ cluster_credentials::uses_certificate() const -> bool
2424
{
2525
return !certificate_path.empty();
2626
}
27+
28+
auto
29+
cluster_credentials::requires_tls() const -> bool
30+
{
31+
return !certificate_path.empty() && !key_path.empty();
32+
}
33+
2734
} // namespace couchbase::core

core/cluster_credentials.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct cluster_credentials {
3131
std::optional<std::vector<std::string>> allowed_sasl_mechanisms{};
3232

3333
[[nodiscard]] auto uses_certificate() const -> bool;
34+
[[nodiscard]] auto requires_tls() const -> bool;
3435
};
3536

3637
} // namespace couchbase::core

core/impl/public_cluster.cxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,15 @@ class cluster_impl : public std::enable_shared_from_this<cluster_impl>
416416
});
417417
}
418418

419+
auto set_authenticator(core::cluster_credentials auth) -> error
420+
{
421+
auto e = core_.update_credentials(std::move(auth));
422+
if (e.ec) {
423+
return core::impl::make_error(e);
424+
}
425+
return {};
426+
}
427+
419428
void notify_fork(fork_event event)
420429
{
421430
if (event == fork_event::prepare) {
@@ -700,6 +709,29 @@ cluster::close() -> std::future<void>
700709
return future;
701710
}
702711

712+
auto
713+
cluster::set_authenticator(const password_authenticator& authenticator) -> couchbase::error
714+
{
715+
core::cluster_credentials auth;
716+
auth.username = authenticator.username_;
717+
auth.password = authenticator.password_;
718+
if (authenticator.ldap_compatible_) {
719+
auth.allowed_sasl_mechanisms = { { "PLAIN" } };
720+
}
721+
722+
return impl_->set_authenticator(std::move(auth));
723+
}
724+
725+
auto
726+
cluster::set_authenticator(const certificate_authenticator& authenticator) -> couchbase::error
727+
{
728+
core::cluster_credentials auth;
729+
auth.certificate_path = authenticator.certificate_path_;
730+
auth.key_path = authenticator.key_path_;
731+
732+
return impl_->set_authenticator(std::move(auth));
733+
}
734+
703735
auto
704736
cluster::query_indexes() const -> query_index_manager
705737
{

0 commit comments

Comments
 (0)