YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
5.45k
    : universe_keys_(std::make_unique<encryption::UniverseKeysPB>()) {}
39
40
Status EncryptionManager::AddUniverseKeys(
41
18
    const AddUniverseKeysRequestPB* req, AddUniverseKeysResponsePB* resp) {
42
18
  {
43
18
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
44
18
    for (const auto& entry : req->universe_keys().map()) {
45
18
      (*universe_keys_->mutable_map())[entry.first] = entry.second;
46
18
    }
47
18
  }
48
18
  LOG(INFO) << "After AddUniverseKeys, key ids in memory: " << UniverseKeyIdsString();
49
18
  return Status::OK();
50
18
}
51
52
53
Status EncryptionManager::GetUniverseKeyRegistry(const GetUniverseKeyRegistryRequestPB* req,
54
9.16k
                                                 GetUniverseKeyRegistryResponsePB* resp) {
55
9.16k
  {
56
9.16k
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
57
9.16k
    *resp->mutable_universe_keys() = *universe_keys_;
58
9.16k
  }
59
9.16k
  LOG(INFO) << "Responding to GetUniverseKeyRegistry request with key ids: "
60
9.16k
            << UniverseKeyIdsString();
61
9.16k
  return Status::OK();
62
9.16k
}
63
64
Status EncryptionManager::HasUniverseKeyInMemory(
65
36
    const HasUniverseKeyInMemoryRequestPB* req, HasUniverseKeyInMemoryResponsePB* resp) {
66
36
  bool has_key;
67
36
  {
68
36
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
69
36
    has_key = universe_keys_->map().count(req->version_id()) != 0;
70
36
  }
71
36
  resp->set_has_key(has_key);
72
36
  LOG(INFO) << Format("For universe key $0, has key: $1", req->version_id(), has_key);
73
36
  return Status::OK();
74
36
}
75
76
Status EncryptionManager::ChangeEncryptionInfo(const ChangeEncryptionInfoRequestPB* req,
77
6
                                               EncryptionInfoPB* encryption_info) {
78
6
  std::string old_universe_key;
79
6
  std::string new_universe_key;
80
6
  std::string new_key_version_id;
81
82
6
  if (encryption_info->encryption_enabled()) {
83
3
    old_universe_key = VERIFY_RESULT(GetLatestUniverseKey(encryption_info));
84
3
  }
85
86
6
  if (req->encryption_enabled()) {
87
6
    new_universe_key = VERIFY_RESULT(GetUniverseKeyFromRotateRequest(req));
88
6
    new_key_version_id = req->has_version_id()
89
6
        ? req->version_id()
90
0
        : to_string(boost::uuids::random_generator()());
91
6
  }
92
93
6
  RETURN_NOT_OK(enterprise::RotateUniverseKey(Slice(old_universe_key), Slice(new_universe_key),
94
6
                                              new_key_version_id, req->encryption_enabled(),
95
6
                                              encryption_info));
96
97
6
  if (req->has_key_path()) {
98
0
    encryption_info->set_key_path(req->key_path());
99
0
  }
100
6
  encryption_info->set_key_in_memory(req->in_memory());
101
102
6
  LOG(INFO) << "Finished ChangeEncryptionInfo with key id " << new_key_version_id;
103
6
  return Status::OK();
104
6
}
105
106
Status EncryptionManager::IsEncryptionEnabled(const EncryptionInfoPB& encryption_info,
107
6
                                              IsEncryptionEnabledResponsePB* resp) {
108
6
  resp->set_encryption_enabled(encryption_info.encryption_enabled());
109
6
  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
6
  auto universe_key = VERIFY_RESULT(GetLatestUniverseKey(&encryption_info));
115
6
  auto decrypted_registry =
116
6
      VERIFY_RESULT(enterprise::DecryptUniverseKeyRegistry(
117
6
          encryption_info.universe_key_registry_encoded(), Slice(universe_key)));
118
6
  auto universe_key_registry =
119
6
      VERIFY_RESULT(pb_util::ParseFromSlice<encryption::UniverseKeyRegistryPB>(decrypted_registry));
120
121
6
  resp->set_key_id(universe_key_registry.latest_version_id());
122
6
  LOG(INFO) << Format("Cluster encrypted with key $0", resp->key_id());
123
124
6
  return Status::OK();
125
6
}
126
127
CHECKED_STATUS EncryptionManager::FillHeartbeatResponseEncryption(
128
3
    const EncryptionInfoPB& encryption_info, TSHeartbeatResponsePB* resp) {
129
3
  Slice decrypted_registry(encryption_info.universe_key_registry_encoded());
130
3
  std::string decrypted;
131
3
  if (encryption_info.encryption_enabled()) {
132
3
    auto res = GetLatestUniverseKey(&encryption_info);
133
3
    if (!res.ok()) {
134
0
      LOG(WARNING) << "Leader master does not have universe key.";
135
0
      return Status::OK();
136
0
    }
137
3
    decrypted = VERIFY_RESULT(enterprise::DecryptUniverseKeyRegistry(decrypted_registry, *res));
138
3
    decrypted_registry = Slice(decrypted);
139
3
  }
140
141
3
  auto registry = VERIFY_RESULT(pb_util::ParseFromSlice<encryption::UniverseKeyRegistryPB>(
142
3
      decrypted_registry));
143
3
  resp->mutable_universe_key_registry()->CopyFrom(registry);
144
3
  return Status::OK();
145
3
}
146
147
void EncryptionManager::PopulateUniverseKeys(
148
9.16k
      const encryption::UniverseKeysPB& universe_key_registry) {
149
9.16k
  std::lock_guard<simple_spinlock> l(universe_key_mutex_);
150
0
  for (const auto& entry : universe_key_registry.map()) {
151
0
    (*universe_keys_->mutable_map())[entry.first] = entry.second;
152
0
  }
153
9.16k
}
154
155
Result<std::string> EncryptionManager::GetLatestUniverseKey(
156
12
    const EncryptionInfoPB* encryption_info) {
157
12
  return GetKeyFromParams(encryption_info->key_in_memory(),
158
12
                          encryption_info->key_path(),
159
12
                          encryption_info->latest_version_id());
160
12
}
161
162
Result<std::string> EncryptionManager::GetUniverseKeyFromRotateRequest(
163
6
    const ChangeEncryptionInfoRequestPB* req) {
164
6
  return GetKeyFromParams(req->in_memory(), req->key_path(), req->version_id());
165
6
}
166
167
9.18k
std::string EncryptionManager::UniverseKeyIdsString() {
168
9.18k
  std::string key_ids;
169
9.18k
  bool first = true;
170
9.18k
  std::lock_guard<simple_spinlock> l(universe_key_mutex_);
171
27
  for (const auto& p : universe_keys_->map()) {
172
27
    if (first) {
173
18
      first = false;
174
9
    } else {
175
9
      key_ids += ", ";
176
9
    }
177
27
    key_ids += p.first;
178
27
  }
179
9.18k
  return key_ids;
180
9.18k
}
181
182
Result<std::string> EncryptionManager::GetKeyFromParams(
183
18
    bool in_memory, const std::string& key_path, const std::string& version_id) {
184
18
  if (in_memory) {
185
18
    std::lock_guard<simple_spinlock> l(universe_key_mutex_);
186
18
    const auto& it = universe_keys_->map().find(version_id);
187
18
    if (it == universe_keys_->map().end()) {
188
0
      return STATUS_SUBSTITUTE(NotFound, "Could not find key with version $0", version_id);
189
0
    }
190
18
    return it->second;
191
18
  }
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