YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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