YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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