Compare commits

..
Author SHA1 Message Date
Vitaliy Filippov 6b28e10660 HTTP "hello, world!" 2026-04-09 12:14:56 +03:00
Vitaliy Filippov f5d19b657a WIP TLS 2026-04-09 11:42:18 +03:00
Vitaliy Filippov 82f9515bf1 Auto-select the only RDMA device/port if there is only one 2026-04-05 16:16:54 +03:00
Vitaliy Filippov dc13f2dd45 Allow to skip checksums for headers 2026-04-05 11:40:00 +03:00
Vitaliy Filippov d54f73195b Implement protocol-level checksums (xxhash3) 2026-04-04 19:03:27 +03:00
Vitaliy Filippov 6c584df3ca Include xxhash3 x86dispatch 2026-04-04 19:03:01 +03:00
Vitaliy Filippov b2effacbc1 Do not use scrap_buffer in the client (it would block protocol checksum support) 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 440a722827 Support TLS CN authentication and per-image permissions in vitastor-cli serve 2026-04-04 19:01:50 +03:00
Vitaliy Filippov e478139e4d Add VitastorAuthFilter 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 7d68443235 Implement vitastor-cli ls-user, modify-user, remove-user commands 2026-04-04 19:01:50 +03:00
Vitaliy Filippov ff6519a005 Add image owner/owner_group/reader_group support (for antietcd VitastorAuthFilter) 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 34a98e4dcc Add security parameter documentation 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 1ebac51110 Support inline (string PEM) certificates and pkeys 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 2e261ac2cf Show encryption keys (only IDs) in the listing 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 405a8c3f53 Support storing image encryption keys in Vault 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 8d4d49dad3 Prefer local etcd addresses and correctly cycle over them even when they need resolving
Seems slightly overcomplicated...
2026-04-04 19:01:50 +03:00
Vitaliy Filippov 6a646be234 Support DNS resolving via libc-ares 2026-04-04 19:01:50 +03:00
Vitaliy Filippov bc0aa48bc7 Batch handle_immediate_ops more 2026-04-04 19:01:50 +03:00
Vitaliy Filippov df08f4e4d2 Add vitastor-cli create & modify --enc-key parameter 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 2669ba96ad Support reading from snapshots encrypted with different keys 2026-04-04 19:01:50 +03:00
Vitaliy Filippov b5b3c95bfd Support decryption with multiple keys 2026-04-04 19:01:50 +03:00
Vitaliy Filippov 0d5530f89a Allow to return chain_info in response to reads 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 0b32d76f75 Add basic AES-XTS client-side encryption support 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 67132a29ae Rework msgr send/receive to allow encryption support 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 6d22ab77ec Move fromhexstr() to str_util 2026-04-04 19:01:49 +03:00
Vitaliy Filippov b2bcf2734c Add openapi description 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 04e4fcd14d Slightly fix API return and input types 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 2dbfc8548a Implement vitastor-cli serve command to serve simple HTTP API 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 74a826d0be Implement HTTP server support O_o 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 4aa9c8bf2b Rename http_response_t to http_message_t 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 5a51415d2c Extract common HTTP context 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 2be8dfbb48 Support xxhash 32-bit checksums (data_csum_type=xxh3_32) 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 49db218f73 Detect block checksums using csum_block_size, not data_csum_type 2026-04-04 19:01:49 +03:00
Vitaliy Filippov b04a2d62b2 Add client certificate support 2026-04-04 19:01:49 +03:00
Vitaliy Filippov dcd545a1a5 Do not re-initialize TLS context every connection 2026-04-04 19:01:49 +03:00
Vitaliy Filippov 553e153c16 Add https support to antietcd 2026-04-04 19:01:49 +03:00
Vitaliy Filippov cc420ca32d Implement etcd SSL support via OpenSSL
Maybe I should remove all of this and use libwebsockets :)
2026-04-04 19:01:49 +03:00
34 changed files with 1057 additions and 1855 deletions
+8 -6
View File
@@ -12,18 +12,20 @@ ARG REL=
WORKDIR /root
RUN set -e -x; \
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
apt-get update; \
apt-get -y install wget; \
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
if [ "$REL" = "buster" ]; then \
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
apt-get update; \
apt-get -y install wget; \
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
fi; \
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/*.sources || true; \
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
RUN apt-get update && \
apt-get -y install fio libgoogle-perftools-dev devscripts libjerasure-dev cmake libc-ares-dev libisal-crypto-dev \
apt-get -y install fio libgoogle-perftools-dev devscripts libjerasure-dev cmake libc-ares-dev \
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
apt-get -y build-dep fio && \
apt-get --download-only source fio
+4 -4
View File
@@ -25,7 +25,7 @@ Most of them can be set in /etc/vitastor/vitastor.conf and in etcd, but don't su
- [vault_timeout_ms](#vault_timeout_ms)
- [vault_error_timeout_sec](#vault_error_timeout_sec)
- [vault_refresh_leeway_sec](#vault_refresh_leeway_sec)
- [max_cipher_pool_size](#max_cipher_pool_size)
- [max_aes_xts_pool_size](#max_aes_xts_pool_size)
## etcd_client_cert
@@ -141,10 +141,10 @@ Time (in seconds) to wait before retrying after receiving an error from Vault.
Extra time (in seconds) before real Vault token lease_timeout to refresh it, just
in case of system clock drift.
## max_cipher_pool_size
## max_aes_xts_pool_size
- Type: integer
- Default: 256
Maximum number of OpenSSL cipher contexts cached in OSD memory, counted separately
for each cipher and for encryption/decryption. Probably doesn't require modification.
Maximum number of OpenSSL encryption contexts cached in OSD memory. Probably
doesn't require modification.
+4 -4
View File
@@ -27,7 +27,7 @@ OSD, мониторами и клиентами.
- [vault_timeout_ms](#vault_timeout_ms)
- [vault_error_timeout_sec](#vault_error_timeout_sec)
- [vault_refresh_leeway_sec](#vault_refresh_leeway_sec)
- [max_cipher_pool_size](#max_cipher_pool_size)
- [max_aes_xts_pool_size](#max_aes_xts_pool_size)
## etcd_client_cert
@@ -145,10 +145,10 @@ OSD, клиенты и мониторы должны иметь разные п
Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального
lease_timeout, на случай "ухода" системных часов.
## max_cipher_pool_size
## max_aes_xts_pool_size
- Тип: целое число
- Значение по умолчанию: 256
Максимальное количество кэшируемых в памяти OSD контекстов шифра OpenSSL, учитываемое
отдельно для каждого шифра и для шифрования и расшифровки. Вряд ли требует изменения.
Максимальное количество кэшируемых в памяти OSD контекстов шифрования OpenSSL.
Вряд ли требует изменения.
+5 -5
View File
@@ -120,12 +120,12 @@
info_ru: |
Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального
lease_timeout, на случай "ухода" системных часов.
- name: max_cipher_pool_size
- name: max_aes_xts_pool_size
type: int
default: 256
info: |
Maximum number of OpenSSL cipher contexts cached in OSD memory, counted separately
for each cipher and for encryption/decryption. Probably doesn't require modification.
Maximum number of OpenSSL encryption contexts cached in OSD memory. Probably
doesn't require modification.
info_ru: |
Максимальное количество кэшируемых в памяти OSD контекстов шифра OpenSSL, учитываемое
отдельно для каждого шифра и для шифрования и расшифровки. Вряд ли требует изменения.
Максимальное количество кэшируемых в памяти OSD контекстов шифрования OpenSSL.
Вряд ли требует изменения.
-1
View File
@@ -37,7 +37,6 @@ function derive_osd_stats(st, prev, prev_diff)
const n = c.count - BigInt(pr && pr.count||0);
diff.recovery_stats[op] = { ...c, bps: n > 0 ? b*1000n/timediff : 0n, iops: n > 0 ? n*1000n/timediff : 0n };
}
diff.inode_stats = {};
for (const pool_id in st.inode_stats||{})
{
diff.inode_stats[pool_id] = {};
+3 -5
View File
@@ -69,17 +69,15 @@ pkg_check_modules(ISAL libisal)
if (ISAL_LIBRARIES)
add_definitions(-DWITH_ISAL)
endif (ISAL_LIBRARIES)
pkg_check_modules(ISAL_CRYPTO libisal_crypto)
if (ISAL_CRYPTO_LIBRARIES)
add_definitions(-DWITH_ISAL_CRYPTO)
endif (ISAL_CRYPTO_LIBRARIES)
pkg_check_modules(RDMACM librdmacm)
if (RDMACM_LIBRARIES)
add_definitions(-DWITH_RDMACM)
endif (RDMACM_LIBRARIES)
find_package(OpenSSL REQUIRED)
add_definitions(-DWITH_OPENSSL)
if (OPENSSL_FOUND)
add_definitions(-DWITH_OPENSSL)
endif (OPENSSL_FOUND)
pkg_check_modules(CARES REQUIRED libcares)
include_directories(${CARES_INCLUDE_DIRS})
+13 -6
View File
@@ -344,12 +344,19 @@ corrupted_block:
block_num, block_offset, wr->size, sizeof(heap_entry_t));
goto corrupted_block;
}
// Garbage collection is only performed when writing new entries into the block
// because it needs a fake LSN and modified blocks require consecutive modified LSNs
// At the same time, further modifications _after_ putting new entries into the block,
// but _before_ writing it, may mark some entries in it as garbage. That's why garbage
// entries may still be present on disk.
wr->entry_type &= ~BS_HEAP_GARBAGE;
if (wr->is_garbage())
{
// Garbage collection is only performed when writing new entries into the block
// because it needs a fake LSN and modified blocks require consecutive modified LSNs
// That's why garbage entries may persist on disk
if (log_level > 5)
{
fprintf(stderr, "Notice: skipping garbage entry %jx:%jx v%ju l%ju in metadata block %u at %u\n",
wr->inode, wr->stripe, wr->version, wr->lsn, block_num, block_offset);
}
block_offset += wr->size;
continue;
}
if ((wr->entry_type & BS_HEAP_TYPE) < BS_HEAP_BIG_WRITE ||
(wr->entry_type & BS_HEAP_TYPE) > BS_HEAP_ROLLBACK ||
(wr->entry_type & ~(BS_HEAP_TYPE|BS_HEAP_STABLE)) ||
+1 -1
View File
@@ -311,7 +311,7 @@ resume_8:
uint32_t block_num = recheck_mod[i];
uint64_t block_offset = bs->dsk.meta_offset + (uint64_t)(block_num+1) * bs->dsk.meta_block_size;
data = ((ring_data_t*)sqe->user_data);
uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, bs->dsk.meta_block_size);
uint8_t *buf = (uint8_t*)malloc_or_die(bs->dsk.meta_block_size);
bs->heap->get_meta_block(block_num, buf);
data->iov = { buf, bs->dsk.meta_block_size };
data->callback = [this, buf, block_offset](ring_data_t *data)
+2 -3
View File
@@ -16,7 +16,7 @@ add_library(vitastor_common STATIC
msgr_encrypt.cpp msgr_stop.cpp msgr_op.cpp msgr_send.cpp msgr_receive.cpp ../util/ringloop.cpp ../../json11/json11.cpp
http_client.cpp osd_ops.cpp pg_states.cpp ../util/timerfd_manager.cpp ../util/str_util.cpp ../util/json_util.cpp ${MSGR_RDMA} ${MSGR_RDMACM}
)
target_link_libraries(vitastor_common pthread ${OPENSSL_LIBRARIES} ${CARES_LIBRARIES} ${ISAL_CRYPTO_LIBRARIES})
target_link_libraries(vitastor_common pthread ${OPENSSL_LIBRARIES} ${CARES_LIBRARIES})
target_compile_options(vitastor_common PUBLIC -fPIC)
# libvitastor_client.so
@@ -35,7 +35,6 @@ target_link_libraries(vitastor_client
${IBVERBS_LIBRARIES}
${RDMACM_LIBRARIES}
${OPENSSL_LIBRARIES}
${ISAL_CRYPTO_LIBRARIES}
)
set_target_properties(vitastor_client PROPERTIES VERSION ${VITASTOR_VERSION} SOVERSION 0)
configure_file(vitastor.pc.in vitastor.pc @ONLY)
@@ -104,7 +103,7 @@ add_executable(test_cluster_client
pg_states.cpp osd_ops.cpp cluster_client.cpp cluster_client_list.cpp cluster_client_wb.cpp cluster_client_icache.cpp msgr_op.cpp ../test/mock/messenger.cpp msgr_stop.cpp msgr_encrypt.cpp
etcd_state_client.cpp ../util/timerfd_manager.cpp ../util/addr_util.cpp ../util/str_util.cpp ../util/json_util.cpp ../util/xxh_x86dispatch.c ../../json11/json11.cpp
)
target_link_libraries(test_cluster_client ${OPENSSL_LIBRARIES} ${ISAL_CRYPTO_LIBRARIES})
target_link_libraries(test_cluster_client ${OPENSSL_LIBRARIES})
target_compile_definitions(test_cluster_client PUBLIC -D__MOCK__)
target_include_directories(test_cluster_client BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/src/test/mock)
add_dependencies(build_tests test_cluster_client)
+4 -7
View File
@@ -590,7 +590,7 @@ void cluster_client_t::on_change_pool_config_hook()
{
if (log_level > 2 && pg_counts[pool_item.first])
{
fprintf(stderr, "Pool %u (%s) PG count changed from %lu to %lu\n", pool_item.first, pool_item.second.name.c_str(),
printf("Pool %u (%s) PG count changed from %lu to %lu\n", pool_item.first, pool_item.second.name.c_str(),
pg_counts[pool_item.first], pool_item.second.real_pg_count);
}
// At this point, all pool operations should have been suspended
@@ -1294,8 +1294,8 @@ void cluster_client_t::slice_rw(cluster_op_t *op)
unsigned bitmap_mem = object_bitmap_size +
op->parts.size() * pg_data_size *
(pool_cfg.data_block_size / pool_cfg.bitmap_granularity / 8
// read chain_info - max 4 bytes per block
+ (op->enc ? osd_op_rw_t::chain_info_bytes(op->enc->chain_size)*op->len/pool_cfg.bitmap_granularity : 0));
// read chain info - 1 byte per block
+ (op->enc ? op->len/pool_cfg.bitmap_granularity : 0));
if (!op->bitmap_buf || op->bitmap_buf_size < bitmap_mem)
{
op->bitmap_buf = realloc_or_die(op->bitmap_buf, bitmap_mem);
@@ -1452,10 +1452,7 @@ int cluster_client_t::try_send(cluster_op_t *op, int i, std::function<void(osd_o
op->inflight_count++;
uint32_t pg_data_size = (pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 1 : pool_cfg.pg_size-pool_cfg.parity_chunks);
uint64_t pg_bitmap_size = pg_data_size * (pool_cfg.data_block_size / pool_cfg.bitmap_granularity / 8
// read chain_info - max 4 bytes per block
+ (op->opcode == OSD_OP_READ && op->enc
? osd_op_rw_t::chain_info_bytes(op->enc->chain_size)*pool_cfg.data_block_size/pool_cfg.bitmap_granularity
: 0));
+ (op->opcode == OSD_OP_READ && op->enc ? pool_cfg.data_block_size/pool_cfg.bitmap_granularity : 0));
uint64_t meta_rev = 0;
if (op->opcode != OSD_OP_READ_BITMAP && op->opcode != OSD_OP_DELETE && !op->deoptimise_snapshot)
{
+1 -1
View File
@@ -84,7 +84,7 @@ class writeback_cache_t;
struct inode_cache_t
{
std::vector<inode_t> chain; // only parents from the same pool
std::vector<inode_t> chain;
uint8_t *key_data = NULL;
osd_op_enc_t *op_enc = NULL;
bool readonly = false;
+1 -2
View File
@@ -166,11 +166,10 @@ void http_ares_cb(void *data, ares_socket_t socket_fd, int readable, int writabl
#ifdef WITH_OPENSSL
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
std::string pem;
BIO *bio = NULL;
if (file_or_pem.substr(0, 5) != "-----")
{
pem = read_file(file_or_pem);
std::string pem = read_file(file_or_pem);
bio = BIO_new_mem_buf(pem.data(), pem.size());
}
else
+36 -66
View File
@@ -10,16 +10,17 @@
#include <stdexcept>
#include "addr_util.h"
#include "str_util.h"
#include "messenger.h"
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
#include "http_client.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
#include <sys/poll.h>
@@ -126,6 +127,11 @@ void osd_messenger_t::init()
if (!tls_cert.empty() || !tls_key.empty() || !osd_tls_ca.empty() || !client_tls_ca.empty())
{
// Initialize TLS context
// FIXME: require OpenSSL
#ifndef WITH_OPENSSL
fprintf(stderr, "Vitastor is built without OpenSSL support\n");
exit(1);
#else
if (tls_cert.empty() || tls_key.empty() || osd_tls_ca.empty() || osd_num && client_tls_ca.empty())
{
if (osd_num)
@@ -137,12 +143,6 @@ void osd_messenger_t::init()
else
{
ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx)
{
init_err:
fprintf(stderr, "OpenSSL initialization failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
bool ok = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
ok = ok && openssl_ctx_add_ca(ssl_ctx, osd_tls_ca);
@@ -157,9 +157,9 @@ init_err:
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
goto init_err;
}
}
#endif
}
#ifdef WITH_RDMACM
if (use_rdmacm)
@@ -339,38 +339,21 @@ osd_messenger_t::~osd_messenger_t()
rdmacm_evch = NULL;
}
#endif
for (auto encrypt_ctx: encrypt_xts_pool)
for (auto encrypt_ctx: encrypt_ctx_pool)
{
destroy_aes_xts_encrypt(encrypt_ctx);
}
for (auto decrypt_ctx: decrypt_xts_pool)
for (auto decrypt_ctx: decrypt_ctx_pool)
{
destroy_aes_xts_decrypt(decrypt_ctx);
}
#ifdef WITH_ISAL_CRYPTO
for (isal_gcm_context_data *ctx: encrypt_gcm_pool)
{
free(ctx);
}
for (isal_gcm_context_data *ctx: decrypt_gcm_pool)
{
free(ctx);
}
#else
for (EVP_CIPHER_CTX *ctx: encrypt_gcm_pool)
{
EVP_CIPHER_CTX_free(ctx);
}
for (EVP_CIPHER_CTX *ctx: decrypt_gcm_pool)
{
EVP_CIPHER_CTX_free(ctx);
}
#endif
#ifdef WITH_OPENSSL
if (ssl_ctx)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
}
#endif
}
void osd_messenger_t::parse_config(const json11::Json & config)
@@ -405,9 +388,9 @@ void osd_messenger_t::parse_config(const json11::Json & config)
if (!this->rdma_max_msg || this->rdma_max_msg > 128*1024*1024)
this->rdma_max_msg = 129*1024;
#endif
this->max_cipher_pool_size = config["max_cipher_pool_size"].uint64_value();
if (!this->max_cipher_pool_size)
this->max_cipher_pool_size = 256;
this->max_aes_xts_pool_size = config["max_aes_xts_pool_size"].uint64_value();
if (!this->max_aes_xts_pool_size)
this->max_aes_xts_pool_size = 256;
if (config["proto_checksums"].is_null())
this->use_proto_checksums = MSGR_CSUM_PAYLOAD;
else if (config["proto_checksums"].is_bool())
@@ -429,15 +412,6 @@ void osd_messenger_t::parse_config(const json11::Json & config)
osd_tls_ca = config["osd_tls_ca"].string_value();
client_tls_ca = config["client_tls_ca"].string_value();
}
test_osd_aes_key.resize(32);
if (fromhexstr(config["test_osd_aes_key"].string_value(), 32, (uint8_t*)test_osd_aes_key.data()) != 32)
test_osd_aes_key.clear();
else
{
#ifdef WITH_ISAL_CRYPTO
isal_aes_gcm_pre_256(test_osd_aes_key.data(), &test_osd_aes_key_isal);
#endif
}
if (!osd_num)
this->iothread_count = (uint32_t)config["client_iothread_count"].uint64_value();
else
@@ -446,7 +420,7 @@ void osd_messenger_t::parse_config(const json11::Json & config)
if (!this->receive_buffer_size || this->receive_buffer_size > 1024*1024*1024)
this->receive_buffer_size = 65536;
this->use_sync_send_recv = config["use_sync_send_recv"].bool_value() ||
config["use_sync_send_recv"].uint64_value() || !ringloop;
config["use_sync_send_recv"].uint64_value();
this->min_zerocopy_send_size = config["min_zerocopy_send_size"].is_null()
? DEFAULT_MIN_ZEROCOPY_SEND_SIZE
: (int)config["min_zerocopy_send_size"].int64_value();
@@ -668,7 +642,10 @@ void osd_messenger_t::handle_connect_epoll(int peer_fd)
handle_peer_epoll(peer_fd, epoll_events);
});
// Check OSD number
ssl_init(cl, false);
if (!tls_cert.empty())
{
ssl_init(cl, false);
}
check_peer_config(cl);
}
@@ -910,7 +887,10 @@ void osd_messenger_t::accept_connections(int listen_fd)
cl->peer_fd = peer_fd;
cl->peer_state = PEER_CONNECTED;
cl->in_buf = (uint8_t*)malloc_or_die(receive_buffer_size);
ssl_init(cl, true);
if (!tls_cert.empty())
{
ssl_init(cl, true);
}
// Add FD to epoll
tfd->set_fd_handler(peer_fd, false, [this](int peer_fd, int epoll_events)
{
@@ -927,32 +907,22 @@ void osd_messenger_t::accept_connections(int listen_fd)
void osd_messenger_t::ssl_init(osd_client_t *cl, bool server_mode)
{
if (!tls_cert.empty())
#ifdef WITH_OPENSSL
cl->write_to_ssl = BIO_new(BIO_s_mem());
cl->read_from_ssl = BIO_new(BIO_s_mem());
cl->ssl_cli = SSL_new(ssl_ctx);
if (server_mode)
{
cl->write_to_ssl = BIO_new(BIO_s_mem());
cl->read_from_ssl = BIO_new(BIO_s_mem());
cl->ssl_cli = SSL_new(ssl_ctx);
if (!cl->ssl_cli)
{
fprintf(stderr, "OpenSSL initialization failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
if (server_mode)
{
SSL_set_accept_state(cl->ssl_cli);
}
else
{
SSL_set_connect_state(cl->ssl_cli);
}
SSL_set_bio(cl->ssl_cli, cl->write_to_ssl, cl->read_from_ssl);
bool ok = ssl_do_handshake(cl);
assert(ok);
SSL_set_accept_state(cl->ssl_cli);
}
else if (!test_osd_aes_key.empty())
else
{
cl->gcm_enabled = true;
SSL_set_connect_state(cl->ssl_cli);
}
SSL_set_bio(cl->ssl_cli, cl->write_to_ssl, cl->read_from_ssl);
bool ok = ssl_do_handshake(cl);
assert(ok);
#endif
}
#ifdef WITH_RDMA
+26 -61
View File
@@ -12,10 +12,8 @@
#include <deque>
#include <vector>
#ifdef WITH_OPENSSL
#include <openssl/types.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/aes_gcm.h>
#endif
#include "../util/xxh_x86dispatch.h"
@@ -62,12 +60,10 @@ struct op_aes_xts_decrypt_t;
void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx);
void destroy_aes_xts_decrypt(op_aes_xts_decrypt_t *decrypt_ctx);
// Standard TLS record header. We are only interested in the record size
struct __attribute__((__packed__)) msgr_tls_record_hdr_t
{
uint8_t content_type;
uint16_t version;
uint16_t size;
uint8_t encrypted;
uint32_t size;
};
struct osd_client_t
@@ -92,6 +88,7 @@ struct osd_client_t
msgr_rdma_connection_t *rdma_conn = NULL;
#endif
#ifdef WITH_OPENSSL
SSL *ssl_cli = NULL;
BIO *write_to_ssl = NULL;
// FIXME: use custom bio to avoid 1 more memory copy?
@@ -99,25 +96,10 @@ struct osd_client_t
uint8_t *ssl_out_buf = NULL;
size_t ssl_out_buf_size = 0, ssl_out_buf_cap = 0;
bool ssl_handshake_done = false;
msgr_tls_record_hdr_t ssl_read_record;
size_t ssl_read_header_size = 0;
bool ssl_more_to_buffer = false;
bool gcm_enabled = false;
#ifdef WITH_ISAL_CRYPTO
isal_gcm_context_data *enc_ctx = NULL;
isal_gcm_context_data *dec_ctx = NULL;
#else
EVP_CIPHER_CTX *enc_ctx = NULL;
EVP_CIPHER_CTX *dec_ctx = NULL;
bool ssl_want_write = false;
#endif
uint8_t enc_tag[16];
size_t enc_tag_size = 0;
uint8_t dec_tag[16];
size_t dec_tag_size = 0;
// Read state
bool io_error = false;
int read_ready = 0;
osd_op_t *read_op = NULL;
size_t read_op_size = 0;
@@ -125,11 +107,11 @@ struct osd_client_t
iovec read_iov = { 0 };
msghdr read_msg = { 0 };
std::vector<iovec> recv_list;
std::vector<int> recv_flags;
size_t recv_list_size = 0;
uint64_t read_op_id = 1;
bool check_sequencing = false;
bool enable_pg_locks = false;
op_aes_xts_decrypt_t *xts_dec_ctx = NULL;
op_aes_xts_decrypt_t *decrypt_ctx = NULL;
size_t read_op_inline_decrypt_pos = 0;
size_t read_op_inline_decrypt_in = 0;
int proto_csum_status = 0;
@@ -155,7 +137,7 @@ struct osd_client_t
size_t send_list_size = 0;
std::deque<osd_op_t*> send_free_ops;
std::vector<osd_op_t*> zc_free_list;
op_aes_xts_encrypt_t *xts_enc_ctx = NULL;
op_aes_xts_encrypt_t *encrypt_ctx = NULL;
XXH3_state_t* write_csum_state = NULL;
~osd_client_t();
@@ -234,21 +216,9 @@ struct osd_messenger_t;
struct rdmacm_connecting_t;
#endif
class msgr_op_reader_t;
class msgr_op_writer_t;
struct __attribute__((visibility("default"))) osd_messenger_t
{
protected:
friend class copy_op_reader_t;
friend class ssl_op_reader_t;
friend class gcm_op_reader_t;
friend class get_op_reader_t;
friend class copy_op_writer_t;
friend class ssl_op_writer_t;
friend class gcm_op_writer_t;
friend class get_op_writer_t;
int keepalive_timer_id = -1;
uint32_t receive_buffer_size = 0;
@@ -260,16 +230,12 @@ protected:
bool use_sync_send_recv = false;
int min_zerocopy_send_size = DEFAULT_MIN_ZEROCOPY_SEND_SIZE;
int iothread_count = 0;
int max_cipher_pool_size = 256;
int max_aes_xts_pool_size = 256;
std::string tls_cert;
std::string tls_key;
std::string osd_tls_ca;
std::string client_tls_ca;
std::string test_osd_aes_key; // FIXME Insecure, only for PoC tests
#ifdef WITH_ISAL_CRYPTO
isal_gcm_key_data test_osd_aes_key_isal;
#endif
#ifdef WITH_RDMA
bool use_rdma = true;
@@ -287,11 +253,18 @@ protected:
robin_hood::unordered_flat_map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting;
#endif
#ifdef WITH_OPENSSL
SSL_CTX *ssl_ctx = NULL;
std::string tls_cn;
void ssl_init(osd_client_t *cl, bool server_mode);
bool ssl_do_handshake(osd_client_t *cl);
bool ssl_do_encrypt(osd_client_t *cl);
size_t ssl_do_encrypt_to(osd_client_t *cl, uint8_t *buf, size_t size);
bool ssl_op_write_buf(osd_client_t *cl, uint8_t *src, size_t src_len, bool skip_csum, size_t & from, size_t & done);
size_t ssl_op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len);
void ssl_op_get_write_buffers(osd_client_t *cl, std::vector<iovec> & lst);
#endif
std::vector<msgr_iothread_t*> iothreads;
std::vector<uint64_t> read_ready_clients;
@@ -299,16 +272,8 @@ protected:
// We don't use ringloop->set_immediate here because we may have no ringloop in client :)
std::deque<osd_op_t*> set_immediate_ops;
std::vector<op_aes_xts_encrypt_t*> encrypt_xts_pool;
std::vector<op_aes_xts_decrypt_t*> decrypt_xts_pool;
#ifdef WITH_ISAL_CRYPTO
std::vector<isal_gcm_context_data*> encrypt_gcm_pool;
std::vector<isal_gcm_context_data*> decrypt_gcm_pool;
#else
std::vector<EVP_CIPHER_CTX*> encrypt_gcm_pool;
std::vector<EVP_CIPHER_CTX*> decrypt_gcm_pool;
#endif
std::vector<op_aes_xts_encrypt_t*> encrypt_ctx_pool;
std::vector<op_aes_xts_decrypt_t*> decrypt_ctx_pool;
public:
timerfd_manager_t *tfd = NULL;
@@ -377,32 +342,32 @@ protected:
bool try_send(osd_client_t *cl);
void handle_send(int result, bool prev, bool more, osd_client_t *cl);
bool op_write_to(osd_client_t *cl, msgr_op_writer_t & wr);
size_t op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len);
void op_get_write_buffers(osd_client_t *cl, std::vector<iovec> & lst);
void next_write_op(osd_client_t *cl);
bool op_write_buf(osd_client_t *cl, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, bool skip_csum, size_t & from, size_t & done);
bool op_copy_data_to(osd_client_t *cl, uint8_t *dst, size_t dst_len, size_t & from, size_t & done);
size_t copy_ops_to(osd_client_t *cl, uint8_t *dst, size_t dst_len);
template<typename T> size_t copy_ops_to_with(osd_client_t *cl, uint8_t *dst, size_t dst_len);
void handle_read(int result, osd_client_t *cl);
bool handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size_t bufsize);
template<typename T> bool handle_buffer_with(osd_client_t *cl, uint8_t *curbuf, size_t bufsize);
bool handle_hdr(osd_client_t *cl);
bool allocate_op_buffers(osd_client_t *cl);
bool allocate_reply_buffers(osd_client_t *cl, osd_op_t *op);
bool op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr);
bool op_copy_from(osd_client_t *cl, uint8_t *src, size_t src_len, size_t & done);
void op_get_read_buffers(osd_client_t *cl, std::vector<iovec> & lst);
void op_alloc_temp_buffers(osd_op_t *op, int i);
bool handle_finished_op(osd_client_t *cl);
void handle_immediate_ops();
void op_encrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc);
void op_encrypt_free(osd_client_t* cl);
void op_decrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc);
bool op_encrypted_copy_data_to(osd_client_t* cl, uint8_t *buf, size_t len, size_t from, size_t & done);
bool op_decrypted_copy_data_from(osd_client_t* cl, uint8_t *buf, size_t len, size_t from, size_t & done);
void op_decrypt_start(osd_client_t* cl);
void op_decrypt_inline(osd_client_t* cl);
void op_decrypt_free(osd_client_t* cl);
#ifdef WITH_RDMA
void try_send_rdma(osd_client_t *cl);
int try_send_rdma_copy(osd_client_t *cl, uint8_t *dst, int dst_len);
bool init_recv_rdma(osd_client_t *cl);
void handle_rdma_events(msgr_rdma_context_t *rdma_context);
msgr_rdma_context_t* choose_rdma_context(osd_client_t *cl);
+110 -107
View File
@@ -3,17 +3,13 @@
#include <assert.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/isal_crypto_api.h>
#endif
#include "etcd_state_client.h"
#include "messenger.h"
#include "msgr_encrypt.h"
op_aes_xts_encrypt_t::op_aes_xts_encrypt_t()
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (!(ctx = EVP_CIPHER_CTX_new()))
{
ERR_print_errors_fp(stderr);
@@ -25,13 +21,16 @@ op_aes_xts_encrypt_t::op_aes_xts_encrypt_t()
ERR_print_errors_fp(stderr);
abort();
}
#else
fprintf(stderr, "Error: Vitastor is built without encryption support\n");
abort();
#endif
}
op_aes_xts_encrypt_t::~op_aes_xts_encrypt_t()
{
assert(!encrypted);
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX_free(ctx);
#endif
if (tmp)
@@ -53,7 +52,7 @@ void op_aes_xts_encrypt_t::start(uint8_t *key, uint64_t start_offset, size_t blo
tmp = NULL;
tmp_size = 0;
}
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL) != 1)
{
ERR_print_errors_fp(stderr);
@@ -64,12 +63,9 @@ void op_aes_xts_encrypt_t::start(uint8_t *key, uint64_t start_offset, size_t blo
void op_aes_xts_encrypt_t::encrypt_block(uint8_t *in, uint8_t *out)
{
#ifdef WITH_OPENSSL
uint8_t iv[16] = { 0 };
*((uint64_t*)iv) = start_offset + offset - offset%block_size;
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_xts_enc_256(key+32, key, iv, block_size, in, out);
assert(r == 0 || r == ISAL_CRYPTO_ERR_XTS_SAME_KEYS);
#else
if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) != 1)
{
ERR_print_errors_fp(stderr);
@@ -102,10 +98,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
done_out += max_out;
tmp_pos += max_out;
if (tmp_pos >= block_size)
{
encrypted = false;
done_in += 1;
}
}
else if (max_in < block_size - offset%block_size)
{
@@ -133,7 +126,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
encrypted = true;
memcpy(out, tmp, max_out);
tmp_pos = max_out;
done_in += max_in-1;
done_in += max_in;
offset += max_in;
done_out += max_out;
}
@@ -165,7 +158,7 @@ void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx)
op_aes_xts_decrypt_t::op_aes_xts_decrypt_t()
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (!(ctx = EVP_CIPHER_CTX_new()))
{
ERR_print_errors_fp(stderr);
@@ -177,27 +170,29 @@ op_aes_xts_decrypt_t::op_aes_xts_decrypt_t()
ERR_print_errors_fp(stderr);
abort();
}
#else
fprintf(stderr, "Error: Vitastor is built without encryption support\n");
abort();
#endif
}
op_aes_xts_decrypt_t::~op_aes_xts_decrypt_t()
{
assert(!decrypted);
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX_free(ctx);
#endif
if (tmp)
free(tmp);
}
void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size)
void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, uint8_t *key_indexes, uint64_t start_offset, size_t block_size)
{
assert(!decrypted);
this->start_offset = start_offset;
this->key_chain = key_chain;
this->chain_size = chain_size;
this->key_indexes = key_indexes;
this->key_index_bytes = osd_op_rw_t::chain_info_bytes(chain_size);
this->key_chain = chain_size > 1 ? key_chain : 0;
this->chain_size = chain_size > 1 ? chain_size : 0;
this->key_indexes = chain_size > 1 ? key_indexes : NULL;
assert(chain_size <= 1 || key_indexes != NULL);
this->block_size = block_size;
this->offset = 0;
@@ -208,7 +203,7 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
tmp = NULL;
tmp_size = 0;
}
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (chain_size == 1 && key_chain[0] && EVP_DecryptInit_ex(ctx, NULL, NULL, key_chain[0], NULL) != 1)
{
ERR_print_errors_fp(stderr);
@@ -220,35 +215,21 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out)
{
uint8_t *key = NULL;
if (chain_size > 1)
if (chain_size)
{
uint32_t key_index = key_index_bytes == 1
? ((uint8_t*)key_indexes)[offset/block_size]
: (key_index_bytes == 2
? ((uint16_t*)key_indexes)[offset/block_size]
: (key_index_bytes == 4
? ((uint32_t*)key_indexes)[offset/block_size]
: UINT32_MAX));
assert(key_index < chain_size);
key = key_chain[key_index];
}
else
{
key = key_chain[0];
}
if (!key)
{
if (in != out)
memcpy(out, in, block_size);
return;
assert(key_indexes[offset/block_size] < chain_size);
key = key_chain[key_indexes[offset/block_size]];
if (!key)
{
if (in != out)
memcpy(out, in, block_size);
return;
}
}
#ifdef WITH_OPENSSL
uint8_t iv[16] = { 0 };
*((uint64_t*)iv) = start_offset + offset - offset%block_size;
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_xts_dec_256(key+32, key, iv, block_size, in, out);
assert(r == 0 || r == ISAL_CRYPTO_ERR_XTS_SAME_KEYS);
#else
if (EVP_DecryptInit_ex(ctx, NULL, NULL, chain_size == 1 ? NULL : key, iv) != 1)
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1)
{
ERR_print_errors_fp(stderr);
abort();
@@ -283,10 +264,7 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
done_out += max_out;
tmp_pos += max_out;
if (tmp_pos >= block_size)
{
decrypted = false;
done_in += 1;
}
}
else if (max_in < block_size - offset%block_size)
{
@@ -315,7 +293,7 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
if (out)
memcpy(out, tmp, max_out);
tmp_pos = max_out;
done_in += max_in-1;
done_in += max_in;
offset += max_in;
done_out += max_out;
}
@@ -347,65 +325,101 @@ void destroy_aes_xts_decrypt(op_aes_xts_decrypt_t *decrypt_ctx)
delete decrypt_ctx;
}
void osd_messenger_t::op_encrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc)
bool osd_messenger_t::op_encrypted_copy_data_to(osd_client_t* cl, uint8_t *enc_buf, size_t enc_len, size_t from, size_t & done)
{
if (!cl->xts_enc_ctx)
auto op = cl->write_op;
auto & op_pos = cl->write_op_pos;
assert(op->req.hdr.opcode == OSD_OP_WRITE);
if (!from)
{
if (encrypt_xts_pool.size())
if (!cl->encrypt_ctx)
{
cl->xts_enc_ctx = encrypt_xts_pool.back();
encrypt_xts_pool.pop_back();
if (encrypt_ctx_pool.size())
{
cl->encrypt_ctx = encrypt_ctx_pool.back();
encrypt_ctx_pool.pop_back();
}
else
cl->encrypt_ctx = new op_aes_xts_encrypt_t();
}
else
cl->xts_enc_ctx = new op_aes_xts_encrypt_t();
assert(cl->write_op->enc->key_chain[0]);
cl->xts_enc_ctx->start(cl->write_op->enc->key_chain[0], cl->write_op->req.rw.offset, cl->write_op->enc->bitmap_granularity);
assert(op->enc->key_chain[0]);
cl->encrypt_ctx->start(op->enc->key_chain[0], op->req.rw.offset, op->enc->bitmap_granularity);
}
while (done_plain < plain_len && done_enc < enc_len)
for (int i = 0; i < op->iov.count; i++)
{
size_t done_in = 0;
size_t done_out = 0;
cl->xts_enc_ctx->update(plain+done_plain, plain_len-done_plain, enc_buf+done_enc, enc_len-done_enc, done_in, done_out);
if (cl->write_csum_state && done_out > 0)
XXH3_64bits_update(cl->write_csum_state, enc_buf+done_enc, done_out);
done_enc += done_out;
cl->write_op_pos += done_in;
done_plain += done_in;
uint8_t *plain = (uint8_t*)op->iov.buf[i].iov_base;
size_t plain_len = op->iov.buf[i].iov_len;
while (from < plain_len || cl->encrypt_ctx->has_buffered())
{
if (done >= enc_len)
return false;
size_t done_in = 0;
size_t done_out = 0;
cl->encrypt_ctx->update(plain+from, plain_len-from, enc_buf+done, enc_len-done, done_in, done_out);
if (cl->write_csum_state && done_out > 0)
XXH3_64bits_update(cl->write_csum_state, enc_buf+done, done_out);
done += done_out;
op_pos += done_in;
from += done_in;
}
from -= plain_len;
}
if (cl->encrypt_ctx)
{
if (encrypt_ctx_pool.size() > max_aes_xts_pool_size)
delete cl->encrypt_ctx;
else
encrypt_ctx_pool.push_back(cl->encrypt_ctx);
cl->encrypt_ctx = NULL;
}
return true;
}
void osd_messenger_t::op_decrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc)
bool osd_messenger_t::op_decrypted_copy_data_from(osd_client_t* cl, uint8_t *enc_buf, size_t enc_len, size_t from, size_t & done)
{
op_decrypt_start(cl);
while (done_plain < plain_len && done_enc < enc_len)
auto op = cl->read_op;
assert(op->req.hdr.opcode == OSD_OP_READ);
for (int i = 0; i < op->iov.count; i++)
{
size_t done_in = 0;
size_t done_out = 0;
// plain == NULL means skip output
cl->xts_dec_ctx->update(enc_buf+done_enc, enc_len-done_enc, plain ? plain+done_plain : NULL, plain_len-done_plain, done_in, done_out);
if (cl->read_csum_state && done_in > 0)
XXH3_64bits_update(cl->read_csum_state, enc_buf+done_enc, done_in);
done_enc += done_in;
cl->read_op_pos += done_out;
cl->read_op_inline_decrypt_in += done_in;
done_plain += done_out;
uint8_t *plain = (uint8_t*)op->iov.buf[i].iov_base;
size_t plain_len = op->iov.buf[i].iov_len;
while (from < plain_len)
{
if (done >= enc_len)
return false;
size_t done_in = 0;
size_t done_out = 0;
// plain == NULL means skip output
cl->decrypt_ctx->update(enc_buf+done, enc_len-done, plain ? plain+from : NULL, plain_len-from, done_in, done_out);
if (cl->read_csum_state && done_in > 0)
XXH3_64bits_update(cl->read_csum_state, enc_buf+done, done_in);
done += done_in;
cl->read_op_pos += done_out;
cl->read_op_inline_decrypt_in += done_in;
from += done_out;
if (!done_out)
return false;
}
from -= plain_len;
}
op_decrypt_free(cl);
return true;
}
void osd_messenger_t::op_decrypt_start(osd_client_t* cl)
{
if (!cl->xts_dec_ctx)
if (!cl->decrypt_ctx)
{
if (decrypt_xts_pool.size())
if (decrypt_ctx_pool.size())
{
cl->xts_dec_ctx = decrypt_xts_pool.back();
decrypt_xts_pool.pop_back();
cl->decrypt_ctx = decrypt_ctx_pool.back();
decrypt_ctx_pool.pop_back();
}
else
cl->xts_dec_ctx = new op_aes_xts_decrypt_t();
cl->decrypt_ctx = new op_aes_xts_decrypt_t();
auto & enc = cl->read_op->enc;
assert(cl->read_op->req.hdr.opcode == OSD_OP_READ);
cl->xts_dec_ctx->start(enc->key_chain, enc->chain_size,
cl->decrypt_ctx->start(enc->key_chain, enc->chain_size,
(cl->read_op->req.rw.flags & OSD_OP_RETURN_CHAIN) ? (uint8_t*)cl->read_op->bitmap + enc->read_chain_bitmap_pos : 0,
cl->read_op->req.rw.offset, enc->bitmap_granularity);
}
@@ -437,7 +451,7 @@ void osd_messenger_t::op_decrypt_inline(osd_client_t* cl)
size_t out_len = op->iov.buf[j].iov_len - from_out;
size_t done_in = 0;
size_t done_out = 0;
cl->xts_dec_ctx->update(in, in_len, out, out_len, done_in, done_out);
cl->decrypt_ctx->update(in, in_len, out, out_len, done_in, done_out);
if (done_in >= in_len)
{
i++;
@@ -454,28 +468,17 @@ void osd_messenger_t::op_decrypt_inline(osd_client_t* cl)
from_out += done_out;
}
assert(j >= op->iov.count);
op_decrypt_free(cl);
}
void osd_messenger_t::op_decrypt_free(osd_client_t* cl)
{
if (cl->xts_dec_ctx)
if (cl->decrypt_ctx)
{
if (decrypt_xts_pool.size() > max_cipher_pool_size)
delete cl->xts_dec_ctx;
if (decrypt_ctx_pool.size() > max_aes_xts_pool_size)
delete cl->decrypt_ctx;
else
decrypt_xts_pool.push_back(cl->xts_dec_ctx);
cl->xts_dec_ctx = NULL;
}
}
void osd_messenger_t::op_encrypt_free(osd_client_t* cl)
{
if (cl->xts_enc_ctx)
{
if (encrypt_xts_pool.size() > max_cipher_pool_size)
delete cl->xts_enc_ctx;
else
encrypt_xts_pool.push_back(cl->xts_enc_ctx);
cl->xts_enc_ctx = NULL;
decrypt_ctx_pool.push_back(cl->decrypt_ctx);
cl->decrypt_ctx = NULL;
}
}
+9 -9
View File
@@ -3,18 +3,17 @@
#include <stdint.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/aes_xts.h>
#endif
#include "../util/xxh_x86dispatch.h"
// WITH_OPENSSL is left to possibly support other crypto libraries
#ifdef WITH_OPENSSL
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
class op_aes_xts_encrypt_t
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX *ctx = NULL;
#endif
uint64_t start_offset = 0;
@@ -32,6 +31,7 @@ public:
op_aes_xts_encrypt_t();
~op_aes_xts_encrypt_t();
inline bool has_buffered() { return encrypted; };
void start(uint8_t *key, uint64_t start_offset, size_t block_size);
void update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out);
};
@@ -40,14 +40,13 @@ void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx);
class op_aes_xts_decrypt_t
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX *ctx = NULL;
#endif
uint64_t start_offset = 0;
uint8_t **key_chain = NULL;
size_t chain_size = 0;
void *key_indexes = NULL;
int key_index_bytes = 0;
uint8_t *key_indexes = NULL;
size_t offset = 0;
size_t block_size = 0;
uint8_t *tmp = NULL;
@@ -61,7 +60,8 @@ public:
op_aes_xts_decrypt_t();
~op_aes_xts_decrypt_t();
void start(uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size);
inline bool has_buffered() { return decrypted; };
void start(uint8_t **key_chain, size_t chain_size, uint8_t *key_indexes, uint64_t start_offset, size_t block_size);
void update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out);
};
+1 -1
View File
@@ -182,7 +182,7 @@ struct __attribute__((visibility("default"))) osd_op_t
void *bitmap = NULL;
unsigned bitmap_len = 0;
unsigned bmp_data = 0;
uint8_t *bitmap_buf = NULL;
void *bitmap_buf = NULL;
void *rmw_buf = NULL;
std::shared_ptr<osd_op_enc_t> enc;
uint8_t *enc_buf = NULL;
+25 -36
View File
@@ -568,6 +568,29 @@ static void try_send_rdma_wr(osd_client_t *cl, ibv_sge *sge, int op_sge)
cl->rdma_conn->cur_send++;
}
int osd_messenger_t::try_send_rdma_copy(osd_client_t *cl, uint8_t *dst, int dst_len)
{
int total_dst_len = dst_len;
while (dst_len > 0 && (cl->write_op || cl->write_ops.size()))
{
next_write_op(cl);
osd_op_t *op = cl->write_op;
size_t copied = op_copy_to(cl, dst, dst_len);
if (!copied)
{
break;
}
dst += copied;
dst_len -= copied;
if (!cl->write_op && op->op_type == OSD_OP_IN)
{
// this is a reply, free the op after sending it
cl->send_free_ops.push_back(op);
}
}
return total_dst_len-dst_len;
}
void osd_messenger_t::try_send_rdma(osd_client_t *cl)
{
auto rc = cl->rdma_conn;
@@ -590,44 +613,10 @@ void osd_messenger_t::try_send_rdma(osd_client_t *cl)
while (!rc->send_out_full && copied > 0 && rc->cur_send < rc->max_send)
{
dst = (uint8_t*)rc->send_out.buf + rc->send_out_pos;
if (rc->send_out_pos >= rc->send_done_pos)
{
dst_len = rc->send_out_size-rc->send_out_pos;
if (dst_len < 4096)
{
// free end of the buffer is too small, skip
rc->send_out_pos = 0;
if (rc->send_out_pos >= rc->send_done_pos)
rc->send_out_full = true;
if (!rc->send_sizes.size())
{
rc->send_done_pos += dst_len;
rc->send_out_full = false;
if (rc->send_done_pos == rc->send_out_size)
rc->send_done_pos = 0;
}
else
rc->send_sizes.back() += dst_len;
continue;
}
}
else
{
dst_len = rc->send_done_pos-rc->send_out_pos;
if (dst_len < 4096)
{
// too small buffer, stop
break;
}
}
dst_len = (rc->send_out_pos < rc->send_out_size ? rc->send_out_size-rc->send_out_pos : rc->send_done_pos-rc->send_out_pos);
if (dst_len > rc->max_msg)
dst_len = rc->max_msg;
copied = copy_ops_to(cl, dst, dst_len);
if (cl->io_error)
{
stop_client(cl->client_id);
return;
}
copied = try_send_rdma_copy(cl, dst, dst_len);
if (copied > 0)
{
rc->send_out_pos += copied;
+1 -1
View File
@@ -79,7 +79,7 @@ struct msgr_rdma_connection_t
msgr_rdma_buf_t recv_buf;
std::deque<uint64_t> send_sizes;
msgr_rdma_buf_t send_out;
size_t send_out_pos = 0, send_done_pos = 0, send_out_size = 0;
int send_out_pos = 0, send_done_pos = 0, send_out_size = 0;
bool send_out_full = false;
~msgr_rdma_connection_t();
File diff suppressed because it is too large Load Diff
+447 -778
View File
File diff suppressed because it is too large Load Diff
+15 -32
View File
@@ -9,10 +9,12 @@
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
void osd_client_t::cancel_ops()
{
@@ -84,21 +86,21 @@ void osd_messenger_t::stop_client(uint64_t client_id, bool force_delete)
fprintf(stderr, "[OSD %ju] Stopping client %ju (regular client)\n", osd_num, client_id);
}
}
if (cl->xts_enc_ctx)
if (cl->encrypt_ctx)
{
if (encrypt_xts_pool.size() > max_cipher_pool_size)
destroy_aes_xts_encrypt(cl->xts_enc_ctx);
if (encrypt_ctx_pool.size() > max_aes_xts_pool_size)
destroy_aes_xts_encrypt(cl->encrypt_ctx);
else
encrypt_xts_pool.push_back(cl->xts_enc_ctx);
cl->xts_enc_ctx = NULL;
encrypt_ctx_pool.push_back(cl->encrypt_ctx);
cl->encrypt_ctx = NULL;
}
if (cl->xts_dec_ctx)
if (cl->decrypt_ctx)
{
if (decrypt_xts_pool.size() > max_cipher_pool_size)
destroy_aes_xts_decrypt(cl->xts_dec_ctx);
if (decrypt_ctx_pool.size() > max_aes_xts_pool_size)
destroy_aes_xts_decrypt(cl->decrypt_ctx);
else
decrypt_xts_pool.push_back(cl->xts_dec_ctx);
cl->xts_dec_ctx = NULL;
decrypt_ctx_pool.push_back(cl->decrypt_ctx);
cl->decrypt_ctx = NULL;
}
// First set state to STOPPED so another stop_client() call doesn't try to free it again
cl->refs++;
@@ -221,10 +223,7 @@ osd_client_t::~osd_client_t()
{
if (op)
{
if (!((size_t)op & 7))
delete op;
else
free((void*)((size_t)op & ~(size_t)7));
delete op;
}
}
#ifndef __MOCK__
@@ -246,24 +245,7 @@ osd_client_t::~osd_client_t()
XXH3_freeState(write_csum_state);
write_csum_state = NULL;
}
if (enc_ctx)
{
#ifdef WITH_ISAL_CRYPTO
free(enc_ctx);
#else
EVP_CIPHER_CTX_free(enc_ctx);
#endif
enc_ctx = NULL;
}
if (dec_ctx)
{
#ifdef WITH_ISAL_CRYPTO
free(dec_ctx);
#else
EVP_CIPHER_CTX_free(dec_ctx);
#endif
dec_ctx = NULL;
}
#ifdef WITH_OPENSSL
if (ssl_cli)
{
SSL_free(ssl_cli);
@@ -276,4 +258,5 @@ osd_client_t::~osd_client_t()
free(ssl_out_buf);
ssl_out_buf = NULL;
}
#endif
}
-13
View File
@@ -231,25 +231,12 @@ struct __attribute__((__packed__)) osd_op_rw_t
uint32_t len;
// flags
// OSD_OP_RETURN_CHAIN for chained reads: return parent number in chain for each block
// read_chain size comes after bitmap, takes 0 bytes / 1 byte / 2 byte / 4 byte per each block,
// depending on the number of parent inodes (0 parents = 0 bytes, up to 255 parents = 1 byte, etc)
uint32_t flags;
// inode metadata revision for chained reads
uint64_t meta_revision;
// object version for atomic "CAS" (compare-and-set) writes
// writes and deletes fail with -EINTR if object version differs from (version-1)
uint64_t version;
static inline size_t chain_info_bytes(size_t chain_size)
{
if (chain_size <= 1)
return 0;
if (chain_size <= 256)
return 1;
if (chain_size <= 65536)
return 2;
return 4;
}
};
struct __attribute__((__packed__)) osd_reply_rw_t
+4
View File
@@ -1,7 +1,9 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details)
#ifdef WITH_OPENSSL
#include <openssl/rand.h>
#endif
#include <ctype.h>
#include "cli.h"
@@ -626,12 +628,14 @@ std::function<bool(cli_result_t &)> cli_tool_t::start_create(json11::Json cfg)
if (!cfg["enc_key"].is_null())
{
image_creator->set_key = true;
#ifdef WITH_OPENSSL
if (image_creator->enc_key == "random")
{
uint8_t newkey[64];
RAND_bytes(newkey, 64);
image_creator->enc_key = tohexstr(newkey, 64);
}
#endif
else
{
image_creator->enc_key = cfg["enc_key"].string_value();
-2
View File
@@ -286,8 +286,6 @@ struct rm_inode_t
.data = data,
};
}
// Wakeup callers (otherwise they wake up only on next loop())
parent->ringloop->wakeup();
}
in_continue = false;
}
+14 -14
View File
@@ -96,7 +96,7 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
if (inode_it->second.parent_id == cur_op->req.rw.inode ||
inode_it->second.parent_id == inode_it->second.num ||
chain_size > st_cli.inode_config.size() ||
chain_size > UINT32_MAX)
chain_size > 255)
{
printf("Inode %ju from pool %u has too many parents, returning EINVAL in response to read\n",
INODE_NO_POOL(cur_op->req.rw.inode), INODE_POOL(cur_op->req.rw.inode));
@@ -111,7 +111,7 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
// Add the original inode
chain_size++;
chain_info_len = (cur_op->req.rw.flags & OSD_OP_RETURN_CHAIN
? osd_op_rw_t::chain_info_bytes(chain_size) * (cur_op->req.rw.len / bs_bitmap_granularity)
? (cur_op->req.rw.len / bs_bitmap_granularity)
: 0);
}
}
@@ -130,7 +130,9 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
stripe_count * clean_entry_bitmap_size +
// - 'missing' flags for chained reads
(pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 0 : pg_it->second.pg_size)
)
) +
// read chain info
chain_info_len
);
void *data_buf = (uint8_t*)op_data + sizeof(osd_primary_op_data_t);
op_data->pg_num = pg_num;
@@ -138,7 +140,6 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
op_data->oid = oid;
op_data->stripes = (osd_rmw_stripe_t*)data_buf;
op_data->stripe_count = stripe_count;
op_data->chain_info = NULL;
data_buf = (uint8_t*)data_buf + sizeof(osd_rmw_stripe_t) * stripe_count;
cur_op->op_data = op_data;
if (cur_op->req.hdr.opcode != OSD_OP_SCRUB)
@@ -146,17 +147,10 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
split_stripes(pg_data_size, bs_block_size, (uint32_t)(cur_op->req.rw.offset - oid.stripe), cur_op->req.rw.len, op_data->stripes);
// Resulting bitmaps have to survive op_data and be freed with the op itself
assert(!cur_op->bitmap_buf);
cur_op->bitmap_buf = (uint8_t*)calloc_or_die(1, clean_entry_bitmap_size*stripe_count + chain_info_len);
uint8_t *buf = cur_op->bitmap_buf;
cur_op->bitmap_buf = calloc_or_die(1, clean_entry_bitmap_size * stripe_count);
for (int i = 0; i < stripe_count; i++)
{
op_data->stripes[i].bmp_buf = buf;
buf += clean_entry_bitmap_size;
if (i == pg_data_size-1 && chain_info_len)
{
op_data->chain_info = buf;
buf += chain_info_len;
}
op_data->stripes[i].bmp_buf = (uint8_t*)cur_op->bitmap_buf + clean_entry_bitmap_size * i;
}
}
op_data->chain_size = chain_size;
@@ -170,6 +164,11 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
data_buf = (uint8_t*)data_buf + chain_size * stripe_count * clean_entry_bitmap_size;
op_data->missing_flags = (uint8_t*)data_buf;
data_buf = (uint8_t*)data_buf + chain_size * (pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 0 : pg_it->second.pg_size);
if (chain_info_len)
{
op_data->chain_info = (uint8_t*)data_buf;
data_buf = (uint8_t*)data_buf + chain_info_len;
}
// Copy chain
int chain_num = 0;
op_data->read_chain[chain_num] = cur_op->req.rw.inode;
@@ -320,7 +319,6 @@ resume_2:
}
cur_op->reply.rw.version = op_data->fact_ver;
cur_op->reply.rw.bitmap_len = (pg ? pg->pg_data_size : 1) * clean_entry_bitmap_size;
cur_op->bitmap = op_data->stripes[0].bmp_buf;
if (op_data->degraded)
{
// Reconstruct missing stripes
@@ -333,6 +331,7 @@ resume_2:
{
reconstruct_stripes_ec(stripes, pg->pg_size, pg->pg_data_size, clean_entry_bitmap_size);
}
cur_op->iov.push_back(op_data->stripes[0].bmp_buf, cur_op->reply.rw.bitmap_len);
for (int role = 0; role < pg->pg_size; role++)
{
if (stripes[role].req_end != 0)
@@ -347,6 +346,7 @@ resume_2:
}
else
{
cur_op->iov.push_back(op_data->stripes[0].bmp_buf, cur_op->reply.rw.bitmap_len);
cur_op->iov.push_back(cur_op->buf, cur_op->req.rw.len);
}
finish_op(cur_op, cur_op->req.rw.len);
+1 -1
View File
@@ -56,7 +56,7 @@ struct osd_primary_op_data_t
int chain_size;
osd_chain_read_t *chain_reads;
int chain_read_count;
void *chain_info;
uint8_t *chain_info;
};
};
};
+3 -10
View File
@@ -582,10 +582,11 @@ void osd_t::send_chained_read_results(pg_t *pg, osd_op_t *cur_op)
}
}
// Send bitmap
cur_op->bitmap = op_data->stripes[0].bmp_buf;
cur_op->reply.rw.bitmap_len = (pg ? pg->pg_data_size : 1) * clean_entry_bitmap_size;
cur_op->iov.push_back(op_data->stripes[0].bmp_buf, cur_op->reply.rw.bitmap_len);
if (cur_op->req.rw.flags & OSD_OP_RETURN_CHAIN)
{
cur_op->iov.push_back(op_data->chain_info, (cur_op->req.rw.len / bs_bitmap_granularity));
cur_op->reply.rw.bitmap_len += (cur_op->req.rw.len / bs_bitmap_granularity);
}
// And finally compose the result
@@ -595,7 +596,6 @@ void osd_t::send_chained_read_results(pg_t *pg, osd_op_t *cur_op)
int prev = (cur_op->req.rw.offset - op_data->oid.stripe) / bs_bitmap_granularity;
int end = prev + cur_op->req.rw.len/bs_bitmap_granularity;
int cur = prev;
size_t key_index_bytes = osd_op_rw_t::chain_info_bytes(op_data->chain_size);
while (cur <= end)
{
bool has_bit = false;
@@ -607,14 +607,7 @@ void osd_t::send_chained_read_results(pg_t *pg, osd_op_t *cur_op)
if (has_bit)
{
if (op_data->chain_info)
{
if (key_index_bytes == 1)
((uint8_t*)op_data->chain_info)[cur] = pos;
else if (key_index_bytes == 2)
((uint16_t*)op_data->chain_info)[cur] = pos;
else
((uint32_t*)op_data->chain_info)[cur] = pos;
}
op_data->chain_info[cur] = pos;
break;
}
}
+1 -1
View File
@@ -413,7 +413,7 @@ void osd_t::submit_scrub_subops(osd_op_t *cur_op)
}
}
assert(!cur_op->bitmap_buf);
cur_op->bitmap_buf = (uint8_t*)calloc_or_die(1, clean_entry_bitmap_size * op_data->stripe_count);
cur_op->bitmap_buf = calloc_or_die(1, clean_entry_bitmap_size * op_data->stripe_count);
for (int i = 0; i < op_data->stripe_count; i++)
{
op_data->stripes[i].bmp_buf = (uint8_t*)cur_op->bitmap_buf + clean_entry_bitmap_size * i;
+8
View File
@@ -62,6 +62,14 @@ target_link_libraries(test_cas
vitastor_client
)
# http_hello
add_executable(http_hello
http_hello.cpp
)
target_link_libraries(http_hello
vitastor_client
)
# test_crc32
add_executable(test_crc32
test_crc32.cpp
+61
View File
@@ -0,0 +1,61 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdexcept>
#include "http_client.h"
#include "ringloop.h"
#include "epoll_manager.h"
#include "addr_util.h"
int main(int narg, char *args[])
{
ring_consumer_t looper;
ring_loop_t *ringloop = new ring_loop_t(RINGLOOP_DEFAULT_SIZE);
epoll_manager_t *epmgr = new epoll_manager_t(ringloop);
// Accept new connections
int listen_fd = create_and_bind_socket("0.0.0.0", 8085, 128, NULL);
fcntl(listen_fd, F_SETFL, fcntl(listen_fd, F_GETFL, 0) | O_NONBLOCK);
std::string error;
auto http_ctx = http_context_init(epmgr->tfd, "", "", "", false, error);
epmgr->set_fd_handler(listen_fd, false, [http_ctx](int listen_fd, int events)
{
sockaddr_storage addr;
socklen_t peer_addr_size = sizeof(addr);
int peer_fd;
while ((peer_fd = accept(listen_fd, (sockaddr*)&addr, &peer_addr_size)) >= 0)
{
assert(peer_fd != 0);
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK);
int one = 1;
setsockopt(peer_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
auto co = http_init(http_ctx);
http_serve(co, peer_fd, (http_options_t){}, [co](http_message_t *msg)
{
if (msg->eof)
{
http_destroy(co);
return;
}
http_reply(co, "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Length: 13\r\n\r\nHello, world!");
});
}
});
while (true)
{
ringloop->loop();
ringloop->wait();
}
delete epmgr;
delete ringloop;
return 0;
}
+6
View File
@@ -1,7 +1,9 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details)
#ifdef WITH_OPENSSL
#include <openssl/rand.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -554,6 +556,7 @@ void test_writeback_merge()
printf("[ok] writeback merge test\n");
}
#ifdef WITH_OPENSSL
void test_msgr_encrypt()
{
const size_t sz = 1048576;
@@ -722,6 +725,7 @@ void test_msgr_decrypt_chain()
free(src);
printf("[ok] msgr aes-xts chained decrypt\n");
}
#endif
void test_vault()
{
@@ -790,8 +794,10 @@ int main(int narg, char *args[])
test2();
test_writeback();
test_writeback_merge();
#ifdef WITH_OPENSSL
test_msgr_encrypt();
test_msgr_decrypt_chain();
#endif
test_vault();
return 0;
}
+1 -2
View File
@@ -1893,8 +1893,7 @@ void test_big_intent_csums()
heap.finish_recheck();
auto mod = heap.get_recheck_modified_blocks();
assert(mod.size() == 1);
assert(mod[0] == 0);
assert(mod.size() == 0);
// read object 1 - big_intent should be there
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
-19
View File
@@ -27,7 +27,6 @@ ETCD_COUNT=${ETCD_COUNT:-1}
ANTIETCD=${ANTIETCD}
USE_RAMDISK=${USE_RAMDISK}
ETCD_SCHEME=${ETCD_SCHEME:-http}
OSD_TLS=${OSD_TLS}
RAMDISK=/run/user/$(id -u)
findmnt $RAMDISK >/dev/null || (sudo mkdir -p $RAMDISK && sudo mount -t tmpfs tmpfs $RAMDISK)
@@ -125,24 +124,6 @@ VITASTOR_CFG='"etcd_address":"'$ETCD_URL'"'"$VITASTOR_CFG"
if [[ "$ETCD_SCHEME" = "https" ]]; then
VITASTOR_CFG="$VITASTOR_CFG"',"etcd_ca":"'$(pwd)'/testdata/etcd.crt"'
fi
if [[ "$OSD_TLS" = "1" ]]; then
cd ./testdata
openssl req -days 3650 -x509 -new -newkey rsa:4096 -nodes -keyout client_ca.key -out client_ca.crt \
-subj '/C=RU/ST=Russia/L=Moscow/O=VitastorClientCA'
openssl req -days 3650 -x509 -new -newkey rsa:4096 -nodes -keyout osd.key -out osd.crt \
-subj '/C=RU/ST=Russia/L=Moscow/O=VitastorOSD' -addext "extendedKeyUsage = serverAuth, clientAuth"
openssl req -subj '/CN=test' -nodes -new -keyout cli.key -out cli.csr -addext "extendedKeyUsage = clientAuth"
openssl x509 -req -days 3650 -CA client_ca.crt -CAkey client_ca.key -CAcreateserial -in cli.csr -out cli.crt
rm cli.csr
cd $(dirname $0)/..
VITASTOR_CFG="$VITASTOR_CFG"',"osd_tls_cert":"'$(pwd)'/testdata/osd.crt"'
VITASTOR_CFG="$VITASTOR_CFG"',"osd_tls_key":"'$(pwd)'/testdata/osd.key"'
VITASTOR_CFG="$VITASTOR_CFG"',"osd_tls_ca":"'$(pwd)'/testdata/osd.crt"'
VITASTOR_CFG="$VITASTOR_CFG"',"client_tls_ca":"'$(pwd)'/testdata/client_ca.crt"'
VITASTOR_CFG="$VITASTOR_CFG"',"tls_cert":"'$(pwd)'/testdata/cli.crt"'
VITASTOR_CFG="$VITASTOR_CFG"',"tls_key":"'$(pwd)'/testdata/cli.key"'
fi
VITASTOR_CFG="$VITASTOR_CFG"',"test_osd_aes_key":"'$(openssl rand -hex 32)'"'
echo "{$VITASTOR_CFG}" > ./testdata/vitastor.conf
VITASTOR_CFG=./testdata/vitastor.conf
VITASTOR_CLI="build/src/cmd/vitastor-cli --config_path $VITASTOR_CFG"