fix(server): version check bugs (#632)

1. Align checked version with the format provided by the endpoint
2. Improve error reporting as well as install ca certificates in the docker file.

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2023-01-02 11:43:06 +02:00 committed by GitHub
parent a7186c5baa
commit f7e70bc45a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 37 deletions

View File

@ -14,6 +14,7 @@
#include <absl/strings/strip.h>
#include <liburing.h>
#include <mimalloc.h>
#include <openssl/err.h>
#include <signal.h>
#include <regex>
@ -134,40 +135,43 @@ std::optional<std::string> GetRemoteVersion(ProactorBase* proactor, SSL_CTX* ssl
http_client.set_connect_timeout_ms(2000);
auto ec = http_client.Connect(host, service, ssl_context);
if (!ec) {
ec = http_client.Send(req, &res);
if (!ec) {
VLOG(1) << "successfully got response from HTTP GET for host " << host << ":" << service
<< "/" << resource << " response code is " << res.result();
if (res.result() == bh::status::ok) {
return GetVersionString(res.body());
}
} else {
LOG_FIRST_N(WARNING, 1) << "Remote version - HTTP GET error [" << host << ":" << service
<< resource << "], error: " << ec.message();
}
} else {
if (ec) {
LOG_FIRST_N(WARNING, 1) << "Remote version - connection error [" << host << ":" << service
<< "] : " << ec.message();
return nullopt;
}
return std::nullopt;
;
ec = http_client.Send(req, &res);
if (!ec) {
VLOG(1) << "successfully got response from HTTP GET for host " << host << ":" << service << "/"
<< resource << " response code is " << res.result();
if (res.result() == bh::status::ok) {
return GetVersionString(res.body());
}
} else {
static bool is_logged{false};
if (!is_logged) {
is_logged = true;
// Unfortunately AsioStreamAdapter looses the original error category
// because std::error_code can not be converted into boost::system::error_code.
// It's fixed in later versions of Boost, but for now we assume it's from TLS.
LOG(WARNING) << "Remote version - HTTP GET error [" << host << ":" << service << resource
<< "], error: " << ec.value();
LOG(WARNING) << "ssl error: " << ERR_func_error_string(ec.value()) << "/"
<< ERR_reason_error_string(ec.value());
}
}
return nullopt;
}
struct VersionMonitor {
fibers_ext::Fiber version_fiber_;
fibers_ext::Done monitor_ver_done_;
void Run(ProactorPool* proactor_pool) {
const std::string dev_version_name = "dev";
// Don't run in dev environment - i.e. where we don't build with
// real version number
if (GetFlag(FLAGS_version_check) && kGitTag != dev_version_name) {
version_fiber_ = proactor_pool->GetNextProactor()->LaunchFiber([this] { RunTask(); });
}
}
void Run(ProactorPool* proactor_pool);
void Shutdown() {
monitor_ver_done_.Notify();
@ -177,37 +181,50 @@ struct VersionMonitor {
}
private:
void RunTask();
void RunTask(SSL_CTX* ssl_ctx);
};
void VersionMonitor::RunTask() {
void VersionMonitor::Run(ProactorPool* proactor_pool) {
// Don't run in dev environment - i.e. where we don't build with
// real version number
if (!GetFlag(FLAGS_version_check) || kGitTag[0] != 'v')
return;
SSL_CTX* ssl_ctx = TlsClient::CreateSslContext();
if (!ssl_ctx) {
VLOG(1) << "Remote version - failed to create SSL context - cannot run version monitoring";
return;
}
version_fiber_ =
proactor_pool->GetNextProactor()->LaunchFiber([ssl_ctx, this] { RunTask(ssl_ctx); });
}
void VersionMonitor::RunTask(SSL_CTX* ssl_ctx) {
const auto loop_sleep_time = std::chrono::hours(24); // every 24 hours
const std::string host_name = "version.dragonflydb.io";
const std::string_view port = "443";
const std::string resource = "/v1";
const std::string version_header = std::string("DragonflyDB/") + kGitTag;
string_view current_version(kGitTag);
SSL_CTX* context = TlsClient::CreateSslContext();
if (!context) {
VLOG(1) << "Remote version - failed to create SSL context - cannot run version monitoring";
return;
}
current_version.remove_prefix(1);
const std::string version_header = absl::StrCat("DragonflyDB/", current_version);
ProactorBase* my_pb = ProactorBase::me();
while (true) {
const std::optional<std::string> remote_version =
GetRemoteVersion(my_pb, context, host_name, port, resource, version_header);
GetRemoteVersion(my_pb, ssl_ctx, host_name, port, resource, version_header);
if (remote_version) {
const std::string rv = remote_version.value();
if (rv != kGitTag) {
LOG_FIRST_N(INFO, 1) << "Your current version '" << kGitTag
if (rv != current_version) {
LOG_FIRST_N(INFO, 1) << "Your current version '" << current_version
<< "' is not the latest version. A newer version '" << rv
<< "' is now available. Please consider an update.";
}
}
if (monitor_ver_done_.WaitFor(loop_sleep_time)) {
TlsClient::FreeContext(context);
TlsClient::FreeContext(ssl_ctx);
VLOG(1) << "finish running version monitor task";
return;
}

View File

@ -21,7 +21,7 @@ FROM ubuntu:20.04
ARG QEMU_CPU
ARG DEBIAN_FRONTEND=noninteractive
RUN apt clean && apt update && apt -y install netcat-openbsd
RUN apt clean && apt update && apt -y install netcat-openbsd ca-certificates
RUN groupadd -r -g 999 dfly && useradd -r -g dfly -u 999 dfly