YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/tserver/encrypted_sstable-test.cc
Line
Count
Source
1
// Copyright (c) Yugabyte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include <glog/logging.h>
15
#include <gtest/gtest.h>
16
17
#include "yb/gutil/stringprintf.h"
18
19
#include "yb/encryption/encrypted_file.h"
20
#include "yb/encryption/encryption_util.h"
21
#include "yb/encryption/header_manager.h"
22
#include "yb/encryption/header_manager_impl.h"
23
#include "yb/encryption/universe_key_manager.h"
24
25
#include "yb/rocksdb/db/dbformat.h"
26
#include "yb/rocksdb/table/block_based_table_factory.h"
27
#include "yb/rocksdb/table/internal_iterator.h"
28
#include "yb/rocksdb/table/table_builder.h"
29
#include "yb/rocksdb/util/file_reader_writer.h"
30
31
#include "yb/rocksutil/rocksdb_encrypted_file_factory.h"
32
33
#include "yb/tserver/universe_key_test_util.h"
34
35
#include "yb/util/path_util.h"
36
#include "yb/util/status.h"
37
#include "yb/util/test_util.h"
38
39
using namespace std::literals;
40
41
using yb::tserver::GenerateTestUniverseKeyManager;
42
43
DECLARE_int64(encryption_counter_min);
44
DECLARE_int64(encryption_counter_max);
45
DECLARE_bool(TEST_encryption_use_openssl_compatible_counter_overflow);
46
47
namespace yb {
48
namespace enterprise {
49
50
namespace {
51
52
40.4M
std::string GetKey(int i) {
53
40.4M
  return StringPrintf("key%09dSSSSSSSS", i);
54
40.4M
}
55
56
40.4M
std::string GetValue(int i) {
57
40.4M
  return Format("value%d", i);
58
40.4M
}
59
60
}  // anonymous namespace
61
62
class EncryptedSSTableTest : public YBTest, public testing::WithParamInterface<bool> {
63
 protected:
64
  void CounterOverflow(
65
      int num_keys, int64_t initial_counter);
66
};
67
68
INSTANTIATE_TEST_CASE_P(
69
    UseOpensslCompatibleCounterOverflow, EncryptedSSTableTest, ::testing::Bool());
70
71
void EncryptedSSTableTest::CounterOverflow(
72
4
    int num_keys, int64_t initial_counter) {
73
4
  FLAGS_encryption_counter_min = initial_counter;
74
4
  FLAGS_encryption_counter_max = initial_counter;
75
4
  FLAGS_TEST_encryption_use_openssl_compatible_counter_overflow = GetParam();
76
77
4
  string test_dir;
78
4
  ASSERT_OK(Env::Default()->GetTestDirectory(&test_dir));
79
80
4
  rocksdb::Options opts;
81
4
  const rocksdb::ImmutableCFOptions imoptions(opts);
82
4
  auto ikc = std::make_shared<rocksdb::InternalKeyComparator>(opts.comparator);
83
4
  std::vector<std::unique_ptr<rocksdb::IntTblPropCollectorFactory> >
84
4
    block_based_table_factories;
85
4
  rocksdb::CompressionOptions compression_opts;
86
4
  rocksdb::TableBuilderOptions table_builder_options(
87
4
      imoptions,
88
4
      ikc,
89
4
      block_based_table_factories,
90
4
      rocksdb::CompressionType::kSnappyCompression,
91
4
      compression_opts,
92
4
      /* skip_filters */ false);
93
94
4
  rocksdb::TableReaderOptions table_reader_options(
95
4
      imoptions,
96
4
      rocksdb::EnvOptions(),
97
4
      ikc,
98
4
      /*skip_filters=*/ false);
99
100
4
  auto universe_key_manager = GenerateTestUniverseKeyManager();
101
102
4
  auto header_manager = DefaultHeaderManager(universe_key_manager.get());
103
4
  auto env = yb::NewRocksDBEncryptedEnv(std::move(header_manager));
104
105
4
  auto file_name = JoinPathSegments(test_dir, "test-file");
106
107
4
  std::unique_ptr<rocksdb::WritableFile> base_file;
108
4
  ASSERT_OK(env->NewWritableFile(file_name, &base_file, rocksdb::EnvOptions()));
109
4
  rocksdb::WritableFileWriter base_writer(std::move(base_file), rocksdb::EnvOptions(),
110
4
      /* suspender */ nullptr);
111
112
4
  string data_file_name = file_name + ".sblock.0";
113
4
  std::unique_ptr<rocksdb::WritableFile> data_file;
114
4
  ASSERT_OK(env->NewWritableFile(data_file_name, &data_file, rocksdb::EnvOptions()));
115
4
  rocksdb::WritableFileWriter data_writer(std::move(data_file), rocksdb::EnvOptions(),
116
4
      /* suspender */ nullptr);
117
118
4
  rocksdb::BlockBasedTableFactory blk_based_tbl_factory;
119
4
  auto table_builder = std::unique_ptr<rocksdb::TableBuilder>(
120
4
      blk_based_tbl_factory.NewTableBuilder(table_builder_options, 0, &base_writer, &data_writer));
121
122
20.2M
  for (int i = 0; i < num_keys; ++i) {
123
20.2M
    string key = GetKey(i);
124
20.2M
    table_builder->Add(key, GetValue(i));
125
20.2M
  }
126
4
  ASSERT_OK(table_builder->Finish());
127
4
  LOG(INFO) << "Wrote a file of total size " << table_builder->TotalFileSize()
128
4
      << ", base file size: " << table_builder->BaseFileSize();
129
4
  ASSERT_OK(base_writer.Flush());
130
4
  ASSERT_OK(data_writer.Flush());
131
4
  ASSERT_OK(base_writer.Close());
132
4
  ASSERT_OK(data_writer.Close());
133
134
4
  std::unique_ptr<rocksdb::RandomAccessFile> random_access_file;
135
4
  ASSERT_OK(env->NewRandomAccessFile(file_name, &random_access_file, rocksdb::EnvOptions()));
136
4
  auto base_file_size = ASSERT_RESULT(random_access_file->Size());
137
4
  ASSERT_EQ(base_file_size, table_builder->BaseFileSize());
138
139
4
  std::unique_ptr<rocksdb::RandomAccessFile> random_access_data_file;
140
4
  ASSERT_OK(env->NewRandomAccessFile(
141
4
      data_file_name, &random_access_data_file, rocksdb::EnvOptions()));
142
4
  auto data_file_reader = std::make_unique<rocksdb::RandomAccessFileReader>(
143
4
      std::move(random_access_data_file), env.get());
144
145
4
  auto* eraf = down_cast<encryption::EncryptedRandomAccessFile*>(random_access_file.get());
146
4
  auto* eraf_data = down_cast<encryption::EncryptedRandomAccessFile*>(random_access_file.get());
147
148
4
  ASSERT_TRUE(eraf != nullptr);
149
4
  ASSERT_TRUE(eraf_data != nullptr);
150
4
  ASSERT_EQ(0, eraf->TEST_GetNumOverflowWorkarounds());
151
4
  ASSERT_EQ(0, eraf_data->TEST_GetNumOverflowWorkarounds());
152
153
4
  size_t raw_size = ASSERT_RESULT(Env::Default()->GetFileSize(file_name));
154
4
  LOG(INFO) << "Raw file size: " << raw_size;
155
156
4
  auto random_access_file_reader = std::make_unique<rocksdb::RandomAccessFileReader>(
157
4
      std::move(random_access_file));
158
159
4
  std::unique_ptr<rocksdb::TableReader> table_reader;
160
161
4
  ASSERT_OK(blk_based_tbl_factory.NewTableReader(
162
4
      table_reader_options, std::move(random_access_file_reader),
163
4
      base_file_size,
164
4
      &table_reader,
165
4
      rocksdb::DataIndexLoadMode::PRELOAD_ON_OPEN,
166
4
      rocksdb::PrefetchFilter::YES));
167
168
4
  table_reader->SetDataFileReader(std::move(data_file_reader));
169
170
4
  auto it = std::unique_ptr<rocksdb::InternalIterator>(
171
4
      table_reader->NewIterator(rocksdb::ReadOptions()));
172
4
  it->SeekToFirst();
173
4
  int i = 0;
174
20.2M
  while (it->Valid()) {
175
20.2M
    ASSERT_EQ(it->key(), GetKey(i));
176
20.2M
    ASSERT_EQ(it->value(), GetValue(i));
177
20.2M
    i++;
178
20.2M
    it->Next();
179
20.2M
  }
180
4
  ASSERT_EQ(num_keys, i);
181
4
  ASSERT_GE(eraf->TEST_GetNumOverflowWorkarounds(), 0);
182
4
  ASSERT_GE(eraf_data->TEST_GetNumOverflowWorkarounds(), 0);
183
4
}
184
185
2
TEST_P(EncryptedSSTableTest, CounterOverflow10MKeys) {
186
  // Note that only three zeros are there in the end of the initial counter below. We are trying to
187
  // get a counter that is 65536 bytes (4096 encryption blocks) away from overflow.
188
2
  CounterOverflow(10 * 1000 * 1000, 0xfffff000);
189
2
}
190
191
2
TEST_P(EncryptedSSTableTest, CounterOverflow100000Keys) {
192
  // This test fails if meta block checksums are not being verified.
193
  // https://github.com/yugabyte/yugabyte-db/issues/3974
194
2
  CounterOverflow(100 * 1000, 0xffffff00);
195
2
}
196
197
} // namespace enterprise
198
} // namespace yb