/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 |