Merge pull request #64253 from arm7star/rgw-openssl

rgw, common: OpenSSL provider support

Reviewed-by: Kefu Chai <tchaikov@gmail.com>
Reviewed-by: Casey Bodley <cbodley@redhat.com>
This commit is contained in:
Casey Bodley 2025-08-12 09:04:39 -04:00 committed by GitHub
commit 07ab7ecbfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 39 additions and 79 deletions

View File

@ -1,3 +1,10 @@
* RGW: OpenSSL engine support deprecated in favor of provider support.
- Removed `openssl_engine_opts` configuration option. OpenSSL engine configurations in string format are no longer supported.
- Added `openssl_conf` configuration option for loading specified providers as default providers.
Configuration file syntax follows the OpenSSL standard (see https://github.com/openssl/openssl/blob/master/doc/man5/config.pod).
If the default provider is still required when using custom providers,
it must be explicitly loaded in the configuration file or code (see https://github.com/openssl/openssl/blob/master/README-PROVIDERS.md).
>=20.0.0
* RADOS: lead Monitor and stretch mode status are now included in the `ceph status` output.

View File

@ -3,7 +3,7 @@
/*
* Ceph - scalable distributed file system
*
* Copyright (c) 2020 Huawei Technologies Co., Ltd.
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -16,12 +16,6 @@
#include <openssl/bio.h>
#include <openssl/conf.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
#include <mutex>
#include <vector>
#include <algorithm>
#include "common/debug.h"
#include "global/global_context.h"
@ -29,8 +23,8 @@
#include "include/scope_guard.h"
using std::string;
using std::string_view;
using std::ostream;
using std::vector;
// -----------------------------------------------------------------------------
#define dout_context g_ceph_context
@ -43,44 +37,14 @@ static ostream &_prefix(std::ostream *_dout)
return *_dout << "OpenSSLOptsHandler: ";
}
#ifndef OPENSSL_NO_ENGINE
// -----------------------------------------------------------------------------
string construct_engine_conf(const string &opts)
{
const string conf_header = "openssl_conf=openssl_def\n[openssl_def]\n";
const string engine_header = "engines=engine_section\n[engine_section]\n";
string engine_id, engine_statement, engine_detail;
const string id_prefix = "engine";
const string suffix = "_section";
const char delimiter = '\n';
int index = 1;
vector<string> confs = get_str_vec(opts, ":");
for (auto conf : confs) {
// Construct engine section statement like "engine1=engine1_section"
engine_id = id_prefix + std::to_string(index++);
engine_statement += engine_id + "=" + engine_id + suffix + delimiter;
// Adapt to OpenSSL parser
// Replace ',' with '\n' and add section in front
std::replace(conf.begin(), conf.end(), ',', delimiter);
engine_detail += "[" + engine_id + suffix + "]" + delimiter;
engine_detail += conf + delimiter;
}
return conf_header + engine_header + engine_statement + engine_detail;
}
string get_openssl_error()
static string get_openssl_error()
{
BIO *bio = BIO_new(BIO_s_mem());
if (bio == nullptr) {
return "failed to create BIO for more error printing";
}
ERR_print_errors(bio);
char* buf;
size_t len = BIO_get_mem_data(bio, &buf);
string ret(buf, len);
@ -88,44 +52,38 @@ string get_openssl_error()
return ret;
}
void log_error(const string &err)
static void log_error(const string_view &err)
{
derr << "Intended OpenSSL engine acceleration failed.\n"
<< "set by openssl_engine_opts = "
<< g_ceph_context->_conf->openssl_engine_opts
derr << "Intended OpenSSL acceleration failed.\n"
<< "set by openssl_conf = "
<< g_ceph_context->_conf.get_val<std::string>("openssl_conf")
<< "\ndetail error information:\n" << err << dendl;
}
void load_module(const string &engine_conf)
static void load_openssl_modules(const string &openssl_conf)
{
BIO *mem = BIO_new_mem_buf(engine_conf.c_str(), engine_conf.size());
if (mem == nullptr) {
log_error("failed to new BIO memory");
BIO *bio = BIO_new_file(openssl_conf.c_str(), "r");
if (bio == nullptr) {
log_error("failed to open openssl conf");
return;
}
auto sg_mem = make_scope_guard([&mem] { BIO_free(mem); });
auto sg_bio = make_scope_guard([bio] { BIO_free(bio); });
CONF *conf = NCONF_new(nullptr);
if (conf == nullptr) {
log_error("failed to new OpenSSL CONF");
return;
}
auto sg_conf = make_scope_guard([&conf] { NCONF_free(conf); });
if (NCONF_load_bio(conf, mem, nullptr) <= 0) {
auto sg_conf = make_scope_guard([conf] { NCONF_free(conf); });
if (NCONF_load_bio(conf, bio, nullptr) <= 0) {
log_error("failed to load CONF from BIO:\n" + get_openssl_error());
return;
}
OPENSSL_load_builtin_modules();
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
ENGINE_load_builtin_engines();
#pragma clang diagnostic pop
#pragma GCC diagnostic pop
if (CONF_modules_load(
conf, nullptr,
@ -133,24 +91,19 @@ void load_module(const string &engine_conf)
log_error("failed to load modules from CONF:\n" + get_openssl_error());
}
}
#endif // !OPENSSL_NO_ENGINE
void init_engine()
static void init_openssl()
{
string opts = g_ceph_context->_conf->openssl_engine_opts;
if (opts.empty()) {
string openssl_conf = g_ceph_context->_conf.get_val<std::string>("openssl_conf");
if (openssl_conf.empty()) {
return;
}
#ifdef OPENSSL_NO_ENGINE
derr << "OpenSSL is compiled with no engine, but openssl_engine_opts is set" << dendl;
#else
string engine_conf = construct_engine_conf(opts);
load_module(engine_conf);
#endif
load_openssl_modules(openssl_conf);
}
void ceph::crypto::init_openssl_engine_once()
void ceph::crypto::init_openssl_once()
{
static std::once_flag flag;
std::call_once(flag, init_engine);
std::call_once(flag, init_openssl);
}

View File

@ -3,7 +3,7 @@
/*
* Ceph - scalable distributed file system
*
* Copyright (c) 2020 Huawei Technologies Co., Ltd.
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -17,7 +17,7 @@
namespace ceph {
namespace crypto {
void init_openssl_engine_once();
void init_openssl_once();
}
}

View File

@ -822,14 +822,13 @@ options:
desc: Crypto accelerator library to use
default: crypto_isal
with_legacy: true
- name: openssl_engine_opts
- name: openssl_conf
type: str
level: advanced
desc: Use engine for specific openssl algorithm
long_desc: 'Pass opts in this way: engine_id=engine1,dynamic_path=/some/path/engine1.so,default_algorithms=DIGESTS:engine_id=engine2,dynamic_path=/some/path/engine2.so,default_algorithms=CIPHERS,other_ctrl=other_value'
desc: Use openssl_conf for specific openssl algorithm
long_desc: 'Pass opts in this way: openssl_conf=/path/to/openssl.conf'
flags:
- startup
with_legacy: true
- name: mempool_debug
type: bool
level: dev

View File

@ -20,7 +20,6 @@
#include "common/errno.h"
#include "common/Timer.h"
#include "common/TracepointProvider.h"
#include "common/openssl_opts_handler.h"
#include "common/numa.h"
#include "include/compat.h"
#include "include/str_list.h"
@ -168,8 +167,6 @@ void rgw::AppMain::init_frontends1(bool nfs)
if (!g_conf()->rgw_region.empty() && g_conf()->rgw_zonegroup.empty()) {
g_conf().set_val_or_die("rgw_zonegroup", g_conf()->rgw_region.c_str());
}
ceph::crypto::init_openssl_engine_once();
} /* init_frontends1 */
void rgw::AppMain::init_numa()

View File

@ -22,6 +22,7 @@
#include "global/global_init.h"
#include "common/ceph_crypto.h"
#include "common/openssl_opts_handler.h"
#include "common/armor.h"
#include "common/errno.h"
#include "common/Clock.h"
@ -3250,6 +3251,9 @@ rgw_global_init(const std::map<std::string,std::string> *defaults,
// Load the config from the files, but not the mon
global_pre_init(defaults, args, module_type, code_env, flags);
// Init and load specific openssl algorithm
ceph::crypto::init_openssl_once();
// Get the store backend
const auto& config_store = g_conf().get_val<std::string>("rgw_backend_store");