Skip to content

Commit 9c197a3

Browse files
craig[bot]marc
andcommitted
Merge #25850
25850: libroach: add basic encryption stats. r=bdarnell a=mberhault New endpoint: `/_status/stores` which for now only returns the store ID and encryption stats. The encryption stats is a serialized protobuf containing active key information (but not the key itself). This will be handled by CCL UI code since it needs access to CCL protos. Release note: None Co-authored-by: marc <marc@cockroachlabs.com>
2 parents 972967b + 8d2ae81 commit 9c197a3

File tree

28 files changed

+2222
-470
lines changed

28 files changed

+2222
-470
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ CPP_PROTOS := $(filter %/roachpb/metadata.proto %/roachpb/data.proto %/roachpb/i
10171017
CPP_HEADERS := $(subst $(PKG_ROOT),$(CPP_PROTO_ROOT),$(CPP_PROTOS:%.proto=%.pb.h))
10181018
CPP_SOURCES := $(subst $(PKG_ROOT),$(CPP_PROTO_ROOT),$(CPP_PROTOS:%.proto=%.pb.cc))
10191019

1020-
CPP_PROTOS_CCL := $(filter %/ccl/baseccl/encryption_options.proto %/ccl/storageccl/engineccl/enginepbccl/key_registry.proto,$(GO_PROTOS))
1020+
CPP_PROTOS_CCL := $(filter %/ccl/baseccl/encryption_options.proto %/ccl/storageccl/engineccl/enginepbccl/key_registry.proto %/ccl/storageccl/engineccl/enginepbccl/stats.proto,$(GO_PROTOS))
10211021
CPP_HEADERS_CCL := $(subst $(PKG_ROOT),$(CPP_PROTO_CCL_ROOT),$(CPP_PROTOS_CCL:%.proto=%.pb.h))
10221022
CPP_SOURCES_CCL := $(subst $(PKG_ROOT),$(CPP_PROTO_CCL_ROOT),$(CPP_PROTOS_CCL:%.proto=%.pb.cc))
10231023

c-deps/libroach/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ add_library(roachccl
6565
ccl/key_manager.cc
6666
protosccl/ccl/baseccl/encryption_options.pb.cc
6767
protosccl/ccl/storageccl/engineccl/enginepbccl/key_registry.pb.cc
68+
protosccl/ccl/storageccl/engineccl/enginepbccl/stats.pb.cc
6869
)
6970
target_include_directories(roachccl
7071
PRIVATE .. # CryptoPP headers are directly in the directory. Include .. to be able to include <cryptopp/....h>

c-deps/libroach/batch.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ DBStatus DBBatch::GetStats(DBStatsResult* stats) { return FmtStatus("unsupported
513513

514514
DBString DBBatch::GetCompactionStats() { return ToDBString("unsupported"); }
515515

516+
DBStatus DBBatch::GetEnvStats(DBEnvStatsResult* stats) { return FmtStatus("unsupported"); }
517+
516518
DBStatus DBBatch::EnvWriteFile(DBSlice path, DBSlice contents) { return FmtStatus("unsupported"); }
517519

518520
DBStatus DBBatch::EnvOpenFile(DBSlice path, rocksdb::WritableFile** file) {
@@ -598,6 +600,8 @@ DBStatus DBWriteOnlyBatch::GetStats(DBStatsResult* stats) { return FmtStatus("un
598600

599601
DBString DBWriteOnlyBatch::GetCompactionStats() { return ToDBString("unsupported"); }
600602

603+
DBStatus DBWriteOnlyBatch::GetEnvStats(DBEnvStatsResult* stats) { return FmtStatus("unsupported"); }
604+
601605
DBStatus DBWriteOnlyBatch::EnvWriteFile(DBSlice path, DBSlice contents) {
602606
return FmtStatus("unsupported");
603607
}

c-deps/libroach/batch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct DBBatch : public DBEngine {
4040
virtual DBIterator* NewIter(rocksdb::ReadOptions*);
4141
virtual DBStatus GetStats(DBStatsResult* stats);
4242
virtual DBString GetCompactionStats();
43+
virtual DBStatus GetEnvStats(DBEnvStatsResult* stats);
4344
virtual DBStatus EnvWriteFile(DBSlice path, DBSlice contents);
4445
virtual DBStatus EnvOpenFile(DBSlice path, rocksdb::WritableFile** file);
4546
virtual DBStatus EnvReadFile(DBSlice path, DBSlice* contents);
@@ -67,6 +68,7 @@ struct DBWriteOnlyBatch : public DBEngine {
6768
virtual DBIterator* NewIter(rocksdb::ReadOptions*);
6869
virtual DBStatus GetStats(DBStatsResult* stats);
6970
virtual DBString GetCompactionStats();
71+
virtual DBString GetEnvStats(DBEnvStatsResult* stats);
7072
virtual DBStatus EnvWriteFile(DBSlice path, DBSlice contents);
7173
virtual DBStatus EnvOpenFile(DBSlice path, rocksdb::WritableFile** file);
7274
virtual DBStatus EnvReadFile(DBSlice path, DBSlice* contents);

c-deps/libroach/ccl/db.cc

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,52 @@
2121
#include "../rocksdbutils/env_encryption.h"
2222
#include "../status.h"
2323
#include "ccl/baseccl/encryption_options.pb.h"
24+
#include "ccl/storageccl/engineccl/enginepbccl/stats.pb.h"
2425
#include "ctr_stream.h"
2526
#include "key_manager.h"
2627

2728
using namespace cockroach;
2829

2930
namespace cockroach {
3031

32+
class CCLEnvStatsHandler : public EnvStatsHandler {
33+
public:
34+
explicit CCLEnvStatsHandler(KeyManager* store_key_manager, KeyManager* data_key_manager)
35+
: store_key_manager_(store_key_manager), data_key_manager_(data_key_manager) {}
36+
virtual ~CCLEnvStatsHandler() {}
37+
38+
virtual rocksdb::Status GetEncryptionStats(std::string* serialized_stats) override {
39+
enginepbccl::EncryptionStatus enc_status;
40+
41+
bool has_stats = false;
42+
if (this->store_key_manager_ != nullptr) {
43+
has_stats = true;
44+
// Transfer ownership of new key info to status proto, this frees any previous value.
45+
enc_status.set_allocated_active_store_key(store_key_manager_->CurrentKeyInfo().release());
46+
}
47+
48+
if (this->data_key_manager_ != nullptr) {
49+
has_stats = true;
50+
// Transfer ownership of new key info to status proto, this frees any previous value.
51+
enc_status.set_allocated_active_data_key(data_key_manager_->CurrentKeyInfo().release());
52+
}
53+
54+
if (!has_stats) {
55+
return rocksdb::Status::OK();
56+
}
57+
58+
if (!enc_status.SerializeToString(serialized_stats)) {
59+
return rocksdb::Status::InvalidArgument("failed to serialize encryption status");
60+
}
61+
return rocksdb::Status::OK();
62+
}
63+
64+
private:
65+
// KeyManagers are needed to get key information but are not owned by the StatsHandler.
66+
KeyManager* store_key_manager_;
67+
KeyManager* data_key_manager_;
68+
};
69+
3170
// DBOpenHook parses the extra_options field of DBOptions and initializes encryption objects if
3271
// needed.
3372
rocksdb::Status DBOpenHook(const std::string& db_dir, const DBOptions db_opts,
@@ -98,12 +137,16 @@ rocksdb::Status DBOpenHook(const std::string& db_dir, const DBOptions db_opts,
98137
std::unique_ptr<enginepbccl::KeyInfo> store_key = store_key_manager->CurrentKeyInfo();
99138
assert(store_key != nullptr);
100139

101-
// Generate a new data key if needed by giving the active store key info to the data key manager.
140+
// Generate a new data key if needed by giving the active store key info to the data key
141+
// manager.
102142
status = data_key_manager->SetActiveStoreKey(std::move(store_key));
103143
if (!status.ok()) {
104144
return status;
105145
}
106146

147+
// Everything's ok: initialize a stats handler.
148+
env_mgr->SetStatsHandler(new CCLEnvStatsHandler(store_key_manager, data_key_manager));
149+
107150
return rocksdb::Status::OK();
108151
}
109152

c-deps/libroach/ccl/db_test.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "../db.h"
1010
#include "../testutils.h"
11+
#include "ccl/baseccl/encryption_options.pb.h"
12+
#include "ccl/storageccl/engineccl/enginepbccl/stats.pb.h"
1113

1214
using namespace cockroach;
1315

@@ -30,3 +32,49 @@ TEST(LibroachCCL, DBOpenHook) {
3032
db_opts.extra_options = ToDBSlice("blah");
3133
EXPECT_ERR(DBOpenHook("", db_opts, nullptr), "failed to parse extra options");
3234
}
35+
36+
TEST(Libroach, DBOpen) {
37+
{
38+
// Empty options: no encryption.
39+
DBOptions db_opts = defaultDBOptions();
40+
DBEngine* db;
41+
db_opts.use_file_registry = true;
42+
43+
EXPECT_STREQ(DBOpen(&db, DBSlice(), db_opts).data, NULL);
44+
DBEnvStatsResult stats;
45+
EXPECT_STREQ(DBGetEnvStats(db, &stats).data, NULL);
46+
EXPECT_STREQ(stats.encryption_status.data, NULL);
47+
48+
DBClose(db);
49+
}
50+
{
51+
// Encryption enabled.
52+
DBOptions db_opts = defaultDBOptions();
53+
DBEngine* db;
54+
db_opts.use_file_registry = true;
55+
56+
// Enable encryption, but plaintext only, that's enough to get stats going.
57+
cockroach::ccl::baseccl::EncryptionOptions enc_opts;
58+
enc_opts.set_key_source(cockroach::ccl::baseccl::KeyFiles);
59+
enc_opts.mutable_key_files()->set_current_key("plain");
60+
enc_opts.mutable_key_files()->set_old_key("plain");
61+
62+
std::string tmpstr;
63+
ASSERT_TRUE(enc_opts.SerializeToString(&tmpstr));
64+
db_opts.extra_options = ToDBSlice(tmpstr);
65+
66+
EXPECT_STREQ(DBOpen(&db, DBSlice(), db_opts).data, NULL);
67+
DBEnvStatsResult stats;
68+
EXPECT_STREQ(DBGetEnvStats(db, &stats).data, NULL);
69+
EXPECT_STRNE(stats.encryption_status.data, NULL);
70+
71+
// Now parse the status protobuf.
72+
cockroach::ccl::storageccl::engineccl::enginepbccl::EncryptionStatus enc_status;
73+
ASSERT_TRUE(
74+
enc_status.ParseFromArray(stats.encryption_status.data, stats.encryption_status.len));
75+
EXPECT_STREQ(enc_status.active_store_key().key_id().c_str(), "plain");
76+
EXPECT_STREQ(enc_status.active_data_key().key_id().c_str(), "plain");
77+
78+
DBClose(db);
79+
}
80+
}

c-deps/libroach/db.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,8 @@ DBStatus DBGetStats(DBEngine* db, DBStatsResult* stats) { return db->GetStats(st
636636

637637
DBString DBGetCompactionStats(DBEngine* db) { return db->GetCompactionStats(); }
638638

639+
DBStatus DBGetEnvStats(DBEngine* db, DBEnvStatsResult* stats) { return db->GetEnvStats(stats); }
640+
639641
DBSSTable* DBGetSSTables(DBEngine* db, int* n) { return db->GetSSTables(n); }
640642

641643
DBString DBGetUserProperties(DBEngine* db) { return db->GetUserProperties(); }

c-deps/libroach/db_test.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "db.h"
1616
#include "include/libroach.h"
17+
#include "status.h"
1718
#include "testutils.h"
1819

1920
using namespace cockroach;
@@ -30,3 +31,15 @@ TEST(Libroach, DBOpenHook) {
3031
EXPECT_ERR(DBOpenHook("", db_opts, nullptr),
3132
"DBOptions has extra_options, but OSS code cannot handle them");
3233
}
34+
35+
TEST(Libroach, DBOpen) {
36+
DBOptions db_opts = defaultDBOptions();
37+
DBEngine* db;
38+
39+
EXPECT_STREQ(DBOpen(&db, DBSlice(), db_opts).data, NULL);
40+
DBEnvStatsResult stats;
41+
EXPECT_STREQ(DBGetEnvStats(db, &stats).data, NULL);
42+
EXPECT_STREQ(stats.encryption_status.data, NULL);
43+
44+
DBClose(db);
45+
}

c-deps/libroach/engine.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,24 @@ DBString DBImpl::GetCompactionStats() {
204204
return ToDBString(tmp);
205205
}
206206

207+
DBStatus DBImpl::GetEnvStats(DBEnvStatsResult* stats) {
208+
// Always initialize the field to the empty string.
209+
stats->encryption_status = DBString();
210+
211+
if (this->env_mgr->env_stats_handler == nullptr) {
212+
return kSuccess;
213+
}
214+
215+
std::string encryption_status;
216+
auto status = this->env_mgr->env_stats_handler->GetEncryptionStats(&encryption_status);
217+
if (!status.ok()) {
218+
return ToDBStatus(status);
219+
}
220+
221+
stats->encryption_status = ToDBString(encryption_status);
222+
return kSuccess;
223+
}
224+
207225
// EnvWriteFile writes the given data as a new "file" in the given engine.
208226
DBStatus DBImpl::EnvWriteFile(DBSlice path, DBSlice contents) {
209227
rocksdb::Status s;

c-deps/libroach/engine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct DBEngine {
4141
virtual DBIterator* NewIter(rocksdb::ReadOptions*) = 0;
4242
virtual DBStatus GetStats(DBStatsResult* stats) = 0;
4343
virtual DBString GetCompactionStats() = 0;
44+
virtual DBString GetEnvStats(DBEnvStatsResult* stats) = 0;
4445
virtual DBStatus EnvWriteFile(DBSlice path, DBSlice contents) = 0;
4546
virtual DBStatus EnvOpenFile(DBSlice path, rocksdb::WritableFile** file) = 0;
4647
virtual DBStatus EnvReadFile(DBSlice path, DBSlice* contents) = 0;
@@ -83,6 +84,7 @@ struct DBImpl : public DBEngine {
8384
virtual DBIterator* NewIter(rocksdb::ReadOptions*);
8485
virtual DBStatus GetStats(DBStatsResult* stats);
8586
virtual DBString GetCompactionStats();
87+
virtual DBStatus GetEnvStats(DBEnvStatsResult* stats);
8688
virtual DBStatus EnvWriteFile(DBSlice path, DBSlice contents);
8789
virtual DBStatus EnvOpenFile(DBSlice path, rocksdb::WritableFile** file);
8890
virtual DBStatus EnvReadFile(DBSlice path, DBSlice* contents);

0 commit comments

Comments
 (0)