YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/master/encryption_manager.cc
Line
Count
Source (jump to first uncovered line)
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 "yb/master/encryption_manager.h"
15
16
#include <boost/uuid/random_generator.hpp>
17
#include <boost/uuid/uuid_io.hpp>
18
19
#include "yb/encryption/encryption.pb.h"
20
21
#include "yb/master/master_encryption.pb.h"
22
#include "yb/master/master_cluster.pb.h"
23
#include "yb/master/master_heartbeat.pb.h"
24
#include "yb/master/master_replication.pb.h"
25
#include "yb/master/universe_key_registry_service.h"
26
27
#include "yb/util/env.h"
28
#include "yb/util/pb_util.h"
29
#include "yb/util/result.h"
30
#include "yb/util/status_format.h"
31
32
using namespace std::chrono_literals;
33
34
namespace yb {
35
namespace master {
36
37
EncryptionManager::EncryptionManager()
38
8.07k
    : universe_keys_(std::make_unique<encryption::UniverseKeysPB>()) {}
39
40
Status EncryptionManager::AddUniverseKeys(
41
51
    const AddUniverseKeysRequestPB* req, AddUniverseKeysResponsePB* resp) {
42
51
  {
43
51
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
44
51
    for (const auto& entry : req->universe_keys().map()) {
45
51
      (*universe_keys_->mutable_map())[entry.first] = entry.second;
46
51
    }
47
51
  }
48
51
  LOG(INFO) << "After AddUniverseKeys, key ids in memory: " << UniverseKeyIdsString();
49
51
  return Status::OK();
50
51
}
51
52
53
Status EncryptionManager::GetUniverseKeyRegistry(const GetUniverseKeyRegistryRequestPB* req,
54
12.7k
                                                 GetUniverseKeyRegistryResponsePB* resp) {
55
12.7k
  {
56
12.7k
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
57
12.7k
    *resp->mutable_universe_keys() = *universe_keys_;
58
12.7k
  }
59
12.7k
  LOG(INFO) << "Responding to GetUniverseKeyRegistry request with key ids: "
60
12.7k
            << UniverseKeyIdsString();
61
12.7k
  return Status::OK();
62
12.7k
}
63
64
Status EncryptionManager::HasUniverseKeyInMemory(
65
69
    const HasUniverseKeyInMemoryRequestPB* req, HasUniverseKeyInMemoryResponsePB* resp) {
66
69
  bool has_key;
67
69
  {
68
69
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
69
69
    has_key = universe_keys_->map().count(req->version_id()) != 0;
70
69
  }
71
69
  resp->set_has_key(has_key);
72
69
  LOG(INFO) << Format("For universe key $0, has key: $1", req->version_id(), has_key);
73
69
  return Status::OK();
74
69
}
75
76
Status EncryptionManager::ChangeEncryptionInfo(const ChangeEncryptionInfoRequestPB* req,
77
17
                                               EncryptionInfoPB* encryption_info) {
78
17
  std::string old_universe_key;
79
17
  std::string new_universe_key;
80
17
  std::string new_key_version_id;
81
82
17
  if (encryption_info->encryption_enabled()) {
83
3
    old_universe_key = VERIFY_RESULT(GetLatestUniverseKey(encryption_info));
84
3
  }
85
86
17
  if (req->encryption_enabled()) {
87
17
    new_universe_key = VERIFY_RESULT(GetUniverseKeyFromRotateRequest(req));
88
17
    new_key_version_id = req->has_version_id()
89
17
        ? req->version_id()
90
17
        : 
to_string(boost::uuids::random_generator()())0
;
91
17
  }
92
93
17
  RETURN_NOT_OK(enterprise::RotateUniverseKey(Slice(old_universe_key), Slice(new_universe_key),
94
17
                                              new_key_version_id, req->encryption_enabled(),
95
17
                                              encryption_info));
96
97
17
  if (req->has_key_path()) {
98
0
    encryption_info->set_key_path(req->key_path());
99
0
  }
100
17
  encryption_info->set_key_in_memory(req->in_memory());
101
102
17
  LOG(INFO) << "Finished ChangeEncryptionInfo with key id " << new_key_version_id;
103
17
  return Status::OK();
104
17
}
105
106
Status EncryptionManager::IsEncryptionEnabled(const EncryptionInfoPB& encryption_info,
107
17
                                              IsEncryptionEnabledResponsePB* resp) {
108
17
  resp->set_encryption_enabled(encryption_info.encryption_enabled());
109
17
  if (!encryption_info.encryption_enabled()) {
110
0
    return Status::OK();
111
0
  }
112
113
  // Decrypt the universe key registry to get the latest version id.
114
17
  auto universe_key = VERIFY_RESULT(GetLatestUniverseKey(&encryption_info));
115
0
  auto decrypted_registry =
116
17
      VERIFY_RESULT(enterprise::DecryptUniverseKeyRegistry(
117
17
          encryption_info.universe_key_registry_encoded(), Slice(universe_key)));
118
0
  auto universe_key_registry =
119
17
      VERIFY_RESULT(pb_util::ParseFromSlice<encryption::UniverseKeyRegistryPB>(decrypted_registry));
120
121
0
  resp->set_key_id(universe_key_registry.latest_version_id());
122
17
  LOG(INFO) << Format("Cluster encrypted with key $0", resp->key_id());
123
124
17
  return Status::OK();
125
17
}
126
127
CHECKED_STATUS EncryptionManager::FillHeartbeatResponseEncryption(
128
46
    const EncryptionInfoPB& encryption_info, TSHeartbeatResponsePB* resp) {
129
46
  Slice decrypted_registry(encryption_info.universe_key_registry_encoded());
130
46
  std::string decrypted;
131
46
  if (encryption_info.encryption_enabled()) {
132
46
    auto res = GetLatestUniverseKey(&encryption_info);
133
46
    if (!res.ok()) {
134
0
      LOG(WARNING) << "Leader master does not have universe key.";
135
0
      return Status::OK();
136
0
    }
137
46
    decrypted = VERIFY_RESULT(enterprise::DecryptUniverseKeyRegistry(decrypted_registry, *res));
138
0
    decrypted_registry = Slice(decrypted);
139
46
  }
140
141
46
  auto registry = VERIFY_RESULT(pb_util::ParseFromSlice<encryption::UniverseKeyRegistryPB>(
142
46
      decrypted_registry));
143
0
  resp->mutable_universe_key_registry()->CopyFrom(registry);
144
46
  return Status::OK();
145
46
}
146
147
void EncryptionManager::PopulateUniverseKeys(
148
12.7k
      const encryption::UniverseKeysPB& universe_key_registry) {
149
12.7k
  std::lock_guard<simple_spinlock> l(universe_key_mutex_);
150
12.7k
  for (const auto& entry : universe_key_registry.map()) {
151
0
    (*universe_keys_->mutable_map())[entry.first] = entry.second;
152
0
  }
153
12.7k
}
154
155
Result<std::string> EncryptionManager::GetLatestUniverseKey(
156
66
    const EncryptionInfoPB* encryption_info) {
157
66
  return GetKeyFromParams(encryption_info->key_in_memory(),
158
66
                          encryption_info->key_path(),
159
66
                          encryption_info->latest_version_id());
160
66
}
161
162
Result<std::string> EncryptionManager::GetUniverseKeyFromRotateRequest(
163
17
    const ChangeEncryptionInfoRequestPB* req) {
164
17
  return GetKeyFromParams(req->in_memory(), req->key_path(), req->version_id());
165
17
}
166
167
12.8k
std::string EncryptionManager::UniverseKeyIdsString() {
168
12.8k
  std::string key_ids;
169
12.8k
  bool first = true;
170
12.8k
  std::lock_guard<simple_spinlock> l(universe_key_mutex_);
171
12.8k
  for (const auto& p : universe_keys_->map()) {
172
60
    if (first) {
173
51
      first = false;
174
51
    } else {
175
9
      key_ids += ", ";
176
9
    }
177
60
    key_ids += p.first;
178
60
  }
179
12.8k
  return key_ids;
180
12.8k
}
181
182
Result<std::string> EncryptionManager::GetKeyFromParams(
183
83
    bool in_memory, const std::string& key_path, const std::string& version_id) {
184
83
  if (in_memory) {
185
83
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
186
83
    const auto& it = universe_keys_->map().find(version_id);
187
83
    if (it == universe_keys_->map().end()) {
188
0
      return STATUS_SUBSTITUTE(NotFound, "Could not find key with version $0", version_id);
189
0
    }
190
83
    return it->second;
191
83
  }
192
193
0
  faststring contents;
194
0
  RETURN_NOT_OK(ReadFileToString(Env::Default(), key_path, &contents));
195
0
  return contents.ToString();
196
0
}
197
198
} // namespace master
199
} // namespace yb