/Users/deen/code/yugabyte-db/ent/src/yb/server/secure.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/server/secure.h" |
15 | | |
16 | | #include "yb/fs/fs_manager.h" |
17 | | |
18 | | #include "yb/rpc/compressed_stream.h" |
19 | | #include "yb/rpc/messenger.h" |
20 | | #include "yb/rpc/secure_stream.h" |
21 | | #include "yb/rpc/tcp_stream.h" |
22 | | |
23 | | #include "yb/util/env.h" |
24 | | #include "yb/util/format.h" |
25 | | #include "yb/util/net/net_util.h" |
26 | | #include "yb/util/path_util.h" |
27 | | #include "yb/util/result.h" |
28 | | |
29 | | DEFINE_bool(use_node_to_node_encryption, false, "Use node to node encryption."); |
30 | | |
31 | | DEFINE_bool(node_to_node_encryption_use_client_certificates, false, |
32 | | "Should client certificates be sent and verified for encrypted node to node " |
33 | | "communication."); |
34 | | |
35 | | DEFINE_string(node_to_node_encryption_required_uid, "", |
36 | | "Allow only certificates with specified uid. Empty to allow any."); |
37 | | |
38 | | DEFINE_string(certs_dir, "", |
39 | | "Directory that contains certificate authority, private key and certificates for " |
40 | | "this server. By default 'certs' subdir in data folder is used."); |
41 | | |
42 | | DEFINE_bool(use_client_to_server_encryption, false, "Use client to server encryption"); |
43 | | |
44 | | DEFINE_string(certs_for_client_dir, "", |
45 | | "Directory that contains certificate authority, private key and certificates for " |
46 | | "this server that should be used for client to server communications. " |
47 | | "When empty, the same dir as for server to server communications is used."); |
48 | | |
49 | | DEFINE_string(cert_node_filename, "", |
50 | | "The file name that will be used in the names of the node " |
51 | | "certificates and keys. These files will be named : " |
52 | | "'node.{cert_node_filename}.{key|crt}'. " |
53 | | "If this flag is not set, then --server_broadcast_addresses will be " |
54 | | "used if it is set, and if not, --rpc_bind_addresses will be used."); |
55 | | |
56 | | DEFINE_string(key_file_pattern, "node.$0.key", "Pattern used for key file"); |
57 | | |
58 | | DEFINE_string(cert_file_pattern, "node.$0.crt", "Pattern used for certificate file"); |
59 | | |
60 | | DEFINE_bool(enable_stream_compression, true, "Whether it is allowed to use stream compression."); |
61 | | |
62 | | namespace yb { |
63 | | namespace server { |
64 | | namespace { |
65 | | |
66 | 1.97k | string DefaultCertsDir(const string& root_dir) { |
67 | 1.97k | return JoinPathSegments(root_dir, "certs"); |
68 | 1.97k | } |
69 | | |
70 | | } // namespace |
71 | | |
72 | 25.4k | string DefaultRootDir(const FsManager& fs_manager) { |
73 | 25.4k | return DirName(fs_manager.GetRaftGroupMetadataDir()); |
74 | 25.4k | } |
75 | | |
76 | 1.97k | string DefaultCertsDir(const FsManager& fs_manager) { |
77 | 1.97k | return DefaultCertsDir(DefaultRootDir(fs_manager)); |
78 | 1.97k | } |
79 | | |
80 | | Result<std::unique_ptr<rpc::SecureContext>> SetupSecureContext( |
81 | | const std::string& hosts, const FsManager& fs_manager, SecureContextType type, |
82 | 23.4k | rpc::MessengerBuilder* builder) { |
83 | 23.4k | std::vector<HostPort> host_ports; |
84 | 23.4k | RETURN_NOT_OK(HostPort::ParseStrings(hosts, 0, &host_ports)); |
85 | | |
86 | 23.4k | return server::SetupSecureContext( |
87 | 23.4k | DefaultRootDir(fs_manager), host_ports[0].host(), type, builder); |
88 | 23.4k | } |
89 | | |
90 | | Result<std::unique_ptr<rpc::SecureContext>> SetupSecureContext( |
91 | | const std::string& root_dir, const std::string& name, |
92 | 23.4k | SecureContextType type, rpc::MessengerBuilder* builder) { |
93 | 23.4k | return SetupSecureContext(std::string(), root_dir, name, type, builder); |
94 | 23.4k | } |
95 | | |
96 | | void ApplyCompressedStream( |
97 | 23.4k | rpc::MessengerBuilder* builder, const rpc::StreamFactoryPtr lower_layer_factory) { |
98 | 23.4k | if (!FLAGS_enable_stream_compression) { |
99 | 0 | return; |
100 | 0 | } |
101 | 23.4k | builder->SetListenProtocol(rpc::CompressedStreamProtocol()); |
102 | 23.4k | auto parent_mem_tracker = builder->last_used_parent_mem_tracker(); |
103 | 23.4k | auto buffer_tracker = MemTracker::FindOrCreateTracker( |
104 | 23.4k | -1, "Compressed Read Buffer", parent_mem_tracker); |
105 | 23.4k | builder->AddStreamFactory( |
106 | 23.4k | rpc::CompressedStreamProtocol(), |
107 | 23.4k | rpc::CompressedStreamFactory(std::move(lower_layer_factory), buffer_tracker)); |
108 | 23.4k | } |
109 | | |
110 | | Result<std::unique_ptr<rpc::SecureContext>> SetupSecureContext( |
111 | | const std::string& cert_dir, const std::string& root_dir, const std::string& name, |
112 | 23.4k | SecureContextType type, rpc::MessengerBuilder* builder) { |
113 | 23.4k | auto use = type == SecureContextType::kInternal ? FLAGS_use_node_to_node_encryption17.3k |
114 | 23.4k | : FLAGS_use_client_to_server_encryption6.11k ; |
115 | 23.4k | LOG(INFO) << __func__ << ": " << type << ", " << use; |
116 | 23.4k | if (!use) { |
117 | 23.2k | ApplyCompressedStream(builder, rpc::TcpStream::Factory()); |
118 | 23.2k | return nullptr; |
119 | 23.2k | } |
120 | | |
121 | 181 | std::string dir; |
122 | 181 | if (!cert_dir.empty()) { |
123 | 0 | dir = cert_dir; |
124 | 181 | } else if (type == SecureContextType::kExternal) { |
125 | 45 | dir = FLAGS_certs_for_client_dir; |
126 | 45 | } |
127 | 181 | if (dir.empty()) { |
128 | 178 | dir = FLAGS_certs_dir; |
129 | 178 | } |
130 | 181 | if (dir.empty()) { |
131 | 0 | dir = DefaultCertsDir(root_dir); |
132 | 0 | } |
133 | | |
134 | 181 | UseClientCerts use_client_certs = UseClientCerts::kFalse; |
135 | 181 | std::string required_uid; |
136 | 181 | if (type == SecureContextType::kInternal) { |
137 | 136 | use_client_certs = UseClientCerts(FLAGS_node_to_node_encryption_use_client_certificates); |
138 | 136 | required_uid = FLAGS_node_to_node_encryption_required_uid; |
139 | 136 | } |
140 | 181 | auto context = VERIFY_RESULT(CreateSecureContext(dir, use_client_certs, name, required_uid)); |
141 | 0 | ApplySecureContext(context.get(), builder); |
142 | 181 | return context; |
143 | 181 | } |
144 | | |
145 | | Result<std::unique_ptr<rpc::SecureContext>> CreateSecureContext( |
146 | | const std::string& certs_dir, UseClientCerts use_client_certs, const std::string& node_name, |
147 | 198 | const std::string& required_uid) { |
148 | | |
149 | 198 | LOG(INFO) << "Certs directory: " << certs_dir << ", node name: " << node_name; |
150 | | |
151 | 198 | auto result = std::make_unique<rpc::SecureContext>(); |
152 | 198 | faststring data; |
153 | 198 | RETURN_NOT_OK(result->AddCertificateAuthorityFile(JoinPathSegments(certs_dir, "ca.crt"))); |
154 | | |
155 | 198 | if (!node_name.empty()) { |
156 | 183 | RETURN_NOT_OK(ReadFileToString( |
157 | 183 | Env::Default(), JoinPathSegments(certs_dir, Format(FLAGS_key_file_pattern, node_name)), |
158 | 183 | &data)); |
159 | 183 | RETURN_NOT_OK(result->UsePrivateKey(data)); |
160 | | |
161 | 183 | RETURN_NOT_OK(ReadFileToString( |
162 | 183 | Env::Default(), JoinPathSegments(certs_dir, Format(FLAGS_cert_file_pattern, node_name)), |
163 | 183 | &data)); |
164 | 183 | RETURN_NOT_OK(result->UseCertificate(data)); |
165 | 183 | } |
166 | | |
167 | 198 | if (use_client_certs) { |
168 | 42 | result->set_require_client_certificate(true); |
169 | 42 | result->set_use_client_certificate(true); |
170 | 42 | } |
171 | | |
172 | 198 | result->set_required_uid(required_uid); |
173 | | |
174 | 198 | return result; |
175 | 198 | } |
176 | | |
177 | 198 | void ApplySecureContext(const rpc::SecureContext* context, rpc::MessengerBuilder* builder) { |
178 | 198 | auto parent_mem_tracker = builder->last_used_parent_mem_tracker(); |
179 | 198 | auto buffer_tracker = MemTracker::FindOrCreateTracker( |
180 | 198 | -1, "Encrypted Read Buffer", parent_mem_tracker); |
181 | | |
182 | 198 | auto secure_stream_factory = rpc::SecureStreamFactory( |
183 | 198 | rpc::TcpStream::Factory(), buffer_tracker, context); |
184 | 198 | builder->SetListenProtocol(rpc::SecureStreamProtocol()); |
185 | 198 | builder->AddStreamFactory(rpc::SecureStreamProtocol(), secure_stream_factory); |
186 | 198 | ApplyCompressedStream(builder, secure_stream_factory); |
187 | 198 | } |
188 | | |
189 | | } // namespace server |
190 | | } // namespace yb |