/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 | 904 | string DefaultCertsDir(const string& root_dir) { |
67 | 904 | return JoinPathSegments(root_dir, "certs"); |
68 | 904 | } |
69 | | |
70 | | } // namespace |
71 | | |
72 | 17.0k | string DefaultRootDir(const FsManager& fs_manager) { |
73 | 17.0k | return DirName(fs_manager.GetRaftGroupMetadataDir()); |
74 | 17.0k | } |
75 | | |
76 | 904 | string DefaultCertsDir(const FsManager& fs_manager) { |
77 | 904 | return DefaultCertsDir(DefaultRootDir(fs_manager)); |
78 | 904 | } |
79 | | |
80 | | Result<std::unique_ptr<rpc::SecureContext>> SetupSecureContext( |
81 | | const std::string& hosts, const FsManager& fs_manager, SecureContextType type, |
82 | 16.1k | rpc::MessengerBuilder* builder) { |
83 | 16.1k | std::vector<HostPort> host_ports; |
84 | 16.1k | RETURN_NOT_OK(HostPort::ParseStrings(hosts, 0, &host_ports)); |
85 | | |
86 | 16.1k | return server::SetupSecureContext( |
87 | 16.1k | DefaultRootDir(fs_manager), host_ports[0].host(), type, builder); |
88 | 16.1k | } |
89 | | |
90 | | Result<std::unique_ptr<rpc::SecureContext>> SetupSecureContext( |
91 | | const std::string& root_dir, const std::string& name, |
92 | 16.1k | SecureContextType type, rpc::MessengerBuilder* builder) { |
93 | 16.1k | return SetupSecureContext(std::string(), root_dir, name, type, builder); |
94 | 16.1k | } |
95 | | |
96 | | void ApplyCompressedStream( |
97 | 16.1k | rpc::MessengerBuilder* builder, const rpc::StreamFactoryPtr lower_layer_factory) { |
98 | 16.1k | if (!FLAGS_enable_stream_compression) { |
99 | 0 | return; |
100 | 0 | } |
101 | 16.1k | builder->SetListenProtocol(rpc::CompressedStreamProtocol()); |
102 | 16.1k | auto parent_mem_tracker = builder->last_used_parent_mem_tracker(); |
103 | 16.1k | auto buffer_tracker = MemTracker::FindOrCreateTracker( |
104 | 16.1k | -1, "Compressed Read Buffer", parent_mem_tracker); |
105 | 16.1k | builder->AddStreamFactory( |
106 | 16.1k | rpc::CompressedStreamProtocol(), |
107 | 16.1k | rpc::CompressedStreamFactory(std::move(lower_layer_factory), buffer_tracker)); |
108 | 16.1k | } |
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 | 16.1k | SecureContextType type, rpc::MessengerBuilder* builder) { |
113 | 11.5k | auto use = type == SecureContextType::kInternal ? FLAGS_use_node_to_node_encryption |
114 | 4.54k | : FLAGS_use_client_to_server_encryption; |
115 | 16.1k | LOG(INFO) << __func__ << ": " << type << ", " << use; |
116 | 16.1k | if (!use) { |
117 | 16.0k | ApplyCompressedStream(builder, rpc::TcpStream::Factory()); |
118 | 16.0k | return nullptr; |
119 | 16.0k | } |
120 | | |
121 | 75 | std::string dir; |
122 | 75 | if (!cert_dir.empty()) { |
123 | 0 | dir = cert_dir; |
124 | 75 | } else if (type == SecureContextType::kExternal) { |
125 | 27 | dir = FLAGS_certs_for_client_dir; |
126 | 27 | } |
127 | 75 | if (dir.empty()) { |
128 | 72 | dir = FLAGS_certs_dir; |
129 | 72 | } |
130 | 75 | if (dir.empty()) { |
131 | 0 | dir = DefaultCertsDir(root_dir); |
132 | 0 | } |
133 | | |
134 | 75 | UseClientCerts use_client_certs = UseClientCerts::kFalse; |
135 | 75 | std::string required_uid; |
136 | 75 | if (type == SecureContextType::kInternal) { |
137 | 48 | use_client_certs = UseClientCerts(FLAGS_node_to_node_encryption_use_client_certificates); |
138 | 48 | required_uid = FLAGS_node_to_node_encryption_required_uid; |
139 | 48 | } |
140 | 75 | auto context = VERIFY_RESULT(CreateSecureContext(dir, use_client_certs, name, required_uid)); |
141 | 75 | ApplySecureContext(context.get(), builder); |
142 | 75 | return context; |
143 | 75 | } |
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 | 75 | const std::string& required_uid) { |
148 | | |
149 | 75 | LOG(INFO) << "Certs directory: " << certs_dir << ", node name: " << node_name; |
150 | | |
151 | 75 | auto result = std::make_unique<rpc::SecureContext>(); |
152 | 75 | faststring data; |
153 | 75 | RETURN_NOT_OK(result->AddCertificateAuthorityFile(JoinPathSegments(certs_dir, "ca.crt"))); |
154 | | |
155 | 75 | if (!node_name.empty()) { |
156 | 75 | RETURN_NOT_OK(ReadFileToString( |
157 | 75 | Env::Default(), JoinPathSegments(certs_dir, Format(FLAGS_key_file_pattern, node_name)), |
158 | 75 | &data)); |
159 | 75 | RETURN_NOT_OK(result->UsePrivateKey(data)); |
160 | | |
161 | 75 | RETURN_NOT_OK(ReadFileToString( |
162 | 75 | Env::Default(), JoinPathSegments(certs_dir, Format(FLAGS_cert_file_pattern, node_name)), |
163 | 75 | &data)); |
164 | 75 | RETURN_NOT_OK(result->UseCertificate(data)); |
165 | 75 | } |
166 | | |
167 | 75 | if (use_client_certs) { |
168 | 24 | result->set_require_client_certificate(true); |
169 | 24 | result->set_use_client_certificate(true); |
170 | 24 | } |
171 | | |
172 | 75 | result->set_required_uid(required_uid); |
173 | | |
174 | 75 | return result; |
175 | 75 | } |
176 | | |
177 | 75 | void ApplySecureContext(const rpc::SecureContext* context, rpc::MessengerBuilder* builder) { |
178 | 75 | auto parent_mem_tracker = builder->last_used_parent_mem_tracker(); |
179 | 75 | auto buffer_tracker = MemTracker::FindOrCreateTracker( |
180 | 75 | -1, "Encrypted Read Buffer", parent_mem_tracker); |
181 | | |
182 | 75 | auto secure_stream_factory = rpc::SecureStreamFactory( |
183 | 75 | rpc::TcpStream::Factory(), buffer_tracker, context); |
184 | 75 | builder->SetListenProtocol(rpc::SecureStreamProtocol()); |
185 | 75 | builder->AddStreamFactory(rpc::SecureStreamProtocol(), secure_stream_factory); |
186 | 75 | ApplyCompressedStream(builder, secure_stream_factory); |
187 | 75 | } |
188 | | |
189 | | } // namespace server |
190 | | } // namespace yb |