1 //
2 // Copyright 2020 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include <grpc/grpc.h>
18 #include <grpc/grpc_crl_provider.h>
19 #include <grpc/grpc_security.h>
20 #include <grpcpp/security/server_credentials.h>
21 #include <grpcpp/security/tls_credentials_options.h>
22 #include <grpcpp/security/tls_crl_provider.h>
23 #include <gtest/gtest.h>
24
25 #include <memory>
26
27 #include "absl/log/check.h"
28 #include "test/core/test_util/test_config.h"
29 #include "test/core/test_util/tls_utils.h"
30 #include "test/cpp/util/tls_test_utils.h"
31
32 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
33 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
34 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
35 #define CRL_DIR_PATH "test/core/tsi/test_creds/crl_data/crls"
36 #define MALFORMED_CERT_PATH "src/core/tsi/test_creds/malformed-cert.pem"
37
38 namespace {
39
40 constexpr const char* kRootCertName = "root_cert_name";
41 constexpr const char* kRootCertContents = "root_cert_contents";
42 constexpr const char* kIdentityCertName = "identity_cert_name";
43 constexpr const char* kIdentityCertPrivateKey = "identity_private_key";
44 constexpr const char* kIdentityCertContents = "identity_cert_contents";
45
46 using ::grpc::experimental::CreateStaticCrlProvider;
47 using ::grpc::experimental::ExternalCertificateVerifier;
48 using ::grpc::experimental::FileWatcherCertificateProvider;
49 using ::grpc::experimental::NoOpCertificateVerifier;
50 using ::grpc::experimental::StaticDataCertificateProvider;
51 using ::grpc::experimental::TlsServerCredentials;
52 using ::grpc::experimental::TlsServerCredentialsOptions;
53 using ::grpc_core::testing::GetFileContents;
54
55 } // namespace
56
57 namespace grpc {
58 namespace testing {
59 namespace {
60
TEST(CredentialsTest,TlsServerCredentialsWithStaticDataCertificateProviderLoadingRootAndIdentity)61 TEST(
62 CredentialsTest,
63 TlsServerCredentialsWithStaticDataCertificateProviderLoadingRootAndIdentity) {
64 experimental::IdentityKeyCertPair key_cert_pair;
65 key_cert_pair.private_key = kIdentityCertPrivateKey;
66 key_cert_pair.certificate_chain = kIdentityCertContents;
67 std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs;
68 identity_key_cert_pairs.emplace_back(key_cert_pair);
69 auto certificate_provider = std::make_shared<StaticDataCertificateProvider>(
70 kRootCertContents, identity_key_cert_pairs);
71 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
72 options.watch_root_certs();
73 options.set_root_cert_name(kRootCertName);
74 options.watch_identity_key_cert_pairs();
75 options.set_identity_cert_name(kIdentityCertName);
76 options.set_cert_request_type(
77 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
78 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
79 CHECK_NE(server_credentials.get(), nullptr);
80 }
81
82 // ServerCredentials should always have identity credential presented.
83 // Otherwise gRPC stack will fail.
TEST(CredentialsTest,TlsServerCredentialsWithStaticDataCertificateProviderLoadingIdentityOnly)84 TEST(CredentialsTest,
85 TlsServerCredentialsWithStaticDataCertificateProviderLoadingIdentityOnly) {
86 experimental::IdentityKeyCertPair key_cert_pair;
87 key_cert_pair.private_key = kIdentityCertPrivateKey;
88 key_cert_pair.certificate_chain = kIdentityCertContents;
89 std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs;
90 // Adding two key_cert_pair(s) should still work.
91 identity_key_cert_pairs.emplace_back(key_cert_pair);
92 identity_key_cert_pairs.emplace_back(key_cert_pair);
93 auto certificate_provider =
94 std::make_shared<StaticDataCertificateProvider>(identity_key_cert_pairs);
95 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
96 options.watch_identity_key_cert_pairs();
97 options.set_identity_cert_name(kIdentityCertName);
98 options.set_cert_request_type(
99 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
100 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
101 CHECK_NE(server_credentials.get(), nullptr);
102 }
103
TEST(CredentialsTest,TlsServerCredentialsWithFileWatcherCertificateProviderLoadingRootAndIdentity)104 TEST(
105 CredentialsTest,
106 TlsServerCredentialsWithFileWatcherCertificateProviderLoadingRootAndIdentity) {
107 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
108 SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
109 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
110 options.watch_root_certs();
111 options.set_root_cert_name(kRootCertName);
112 options.watch_identity_key_cert_pairs();
113 options.set_identity_cert_name(kIdentityCertName);
114 options.set_cert_request_type(
115 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
116 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
117 CHECK_NE(server_credentials.get(), nullptr);
118 }
119
TEST(CredentialsTest,StaticDataCertificateProviderValidationSuccessWithAllCredentials)120 TEST(CredentialsTest,
121 StaticDataCertificateProviderValidationSuccessWithAllCredentials) {
122 std::string root_certificates = GetFileContents(CA_CERT_PATH);
123 experimental::IdentityKeyCertPair key_cert_pair;
124 key_cert_pair.private_key = GetFileContents(SERVER_KEY_PATH);
125 key_cert_pair.certificate_chain = GetFileContents(SERVER_CERT_PATH);
126 StaticDataCertificateProvider provider(root_certificates, {key_cert_pair});
127 EXPECT_EQ(provider.ValidateCredentials(), absl::OkStatus());
128 }
129
TEST(CredentialsTest,StaticDataCertificateProviderWithMalformedRoot)130 TEST(CredentialsTest, StaticDataCertificateProviderWithMalformedRoot) {
131 std::string root_certificates = GetFileContents(MALFORMED_CERT_PATH);
132 experimental::IdentityKeyCertPair key_cert_pair;
133 key_cert_pair.private_key = GetFileContents(SERVER_KEY_PATH);
134 key_cert_pair.certificate_chain = GetFileContents(SERVER_CERT_PATH);
135 StaticDataCertificateProvider provider(root_certificates, {key_cert_pair});
136 EXPECT_EQ(provider.ValidateCredentials(),
137 absl::FailedPreconditionError("Invalid PEM."));
138 }
139
TEST(CredentialsTest,FileWatcherCertificateProviderValidationSuccessWithAllCredentials)140 TEST(CredentialsTest,
141 FileWatcherCertificateProviderValidationSuccessWithAllCredentials) {
142 FileWatcherCertificateProvider provider(SERVER_KEY_PATH, SERVER_CERT_PATH,
143 CA_CERT_PATH, 1);
144 EXPECT_EQ(provider.ValidateCredentials(), absl::OkStatus());
145 }
146
TEST(CredentialsTest,FileWatcherCertificateProviderWithMalformedRoot)147 TEST(CredentialsTest, FileWatcherCertificateProviderWithMalformedRoot) {
148 FileWatcherCertificateProvider provider(SERVER_KEY_PATH, SERVER_CERT_PATH,
149 MALFORMED_CERT_PATH, 1);
150 EXPECT_EQ(provider.ValidateCredentials(),
151 absl::FailedPreconditionError("Invalid PEM."));
152 }
153
TEST(CredentialsTest,TlsServerCredentialsWithCrlChecking)154 TEST(CredentialsTest, TlsServerCredentialsWithCrlChecking) {
155 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
156 SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
157 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
158 options.watch_root_certs();
159 options.set_root_cert_name(kRootCertName);
160 options.watch_identity_key_cert_pairs();
161 options.set_identity_cert_name(kIdentityCertName);
162 options.set_cert_request_type(
163 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
164 options.set_crl_directory(CRL_DIR_PATH);
165 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
166 CHECK_NE(server_credentials.get(), nullptr);
167 }
168
169 // ServerCredentials should always have identity credential presented.
170 // Otherwise gRPC stack will fail.
TEST(CredentialsTest,TlsServerCredentialsWithFileWatcherCertificateProviderLoadingIdentityOnly)171 TEST(
172 CredentialsTest,
173 TlsServerCredentialsWithFileWatcherCertificateProviderLoadingIdentityOnly) {
174 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
175 SERVER_KEY_PATH, SERVER_CERT_PATH, 1);
176 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
177 options.watch_identity_key_cert_pairs();
178 options.set_identity_cert_name(kIdentityCertName);
179 options.set_cert_request_type(
180 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
181 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
182 CHECK_NE(server_credentials.get(), nullptr);
183 }
184
TEST(CredentialsTest,TlsServerCredentialsWithSyncExternalVerifier)185 TEST(CredentialsTest, TlsServerCredentialsWithSyncExternalVerifier) {
186 auto verifier =
187 ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
188 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
189 SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
190 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
191 options.watch_root_certs();
192 options.set_root_cert_name(kRootCertName);
193 options.watch_identity_key_cert_pairs();
194 options.set_identity_cert_name(kIdentityCertName);
195 options.set_cert_request_type(
196 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
197 options.set_certificate_verifier(verifier);
198 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
199 CHECK_NE(server_credentials.get(), nullptr);
200 }
201
TEST(CredentialsTest,TlsServerCredentialsWithAsyncExternalVerifier)202 TEST(CredentialsTest, TlsServerCredentialsWithAsyncExternalVerifier) {
203 auto verifier =
204 ExternalCertificateVerifier::Create<AsyncCertificateVerifier>(true);
205 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
206 SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
207 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
208 options.watch_root_certs();
209 options.set_root_cert_name(kRootCertName);
210 options.watch_identity_key_cert_pairs();
211 options.set_identity_cert_name(kIdentityCertName);
212 options.set_cert_request_type(
213 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
214 options.set_certificate_verifier(verifier);
215 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
216 CHECK_NE(server_credentials.get(), nullptr);
217 }
218
TEST(CredentialsTest,TlsServerCredentialsWithCrlProvider)219 TEST(CredentialsTest, TlsServerCredentialsWithCrlProvider) {
220 auto provider = experimental::CreateStaticCrlProvider({});
221 ASSERT_TRUE(provider.ok());
222 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
223 SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
224 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
225 options.set_crl_provider(*provider);
226 auto channel_credentials = grpc::experimental::TlsServerCredentials(options);
227 CHECK_NE(channel_credentials.get(), nullptr);
228 }
229
TEST(CredentialsTest,TlsServerCredentialsWithCrlProviderAndDirectory)230 TEST(CredentialsTest, TlsServerCredentialsWithCrlProviderAndDirectory) {
231 auto provider = experimental::CreateStaticCrlProvider({});
232 ASSERT_TRUE(provider.ok());
233 auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
234 SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
235 grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
236 options.set_crl_directory(CRL_DIR_PATH);
237 options.set_crl_provider(*provider);
238 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
239 // TODO(gtcooke94) - behavior might change to make this return nullptr in
240 // the future
241 CHECK_NE(server_credentials, nullptr);
242 }
243
TEST(CredentialsTest,TlsCredentialsOptionsDoesNotLeak)244 TEST(CredentialsTest, TlsCredentialsOptionsDoesNotLeak) {
245 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
246 TlsServerCredentialsOptions options(provider);
247 (void)options;
248 }
249
TEST(CredentialsTest,MultipleOptionsOneCertificateProviderDoesNotLeak)250 TEST(CredentialsTest, MultipleOptionsOneCertificateProviderDoesNotLeak) {
251 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
252 TlsServerCredentialsOptions options_1(provider);
253 (void)options_1;
254 TlsServerCredentialsOptions options_2(provider);
255 (void)options_2;
256 }
257
TEST(CredentialsTest,MultipleOptionsOneCertificateVerifierDoesNotLeak)258 TEST(CredentialsTest, MultipleOptionsOneCertificateVerifierDoesNotLeak) {
259 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
260 auto verifier = std::make_shared<NoOpCertificateVerifier>();
261 TlsServerCredentialsOptions options_1(provider);
262 options_1.set_certificate_verifier(verifier);
263 TlsServerCredentialsOptions options_2(provider);
264 options_2.set_certificate_verifier(verifier);
265 }
266
TEST(CredentialsTest,MultipleOptionsOneCrlProviderDoesNotLeak)267 TEST(CredentialsTest, MultipleOptionsOneCrlProviderDoesNotLeak) {
268 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
269 auto crl_provider = CreateStaticCrlProvider(/*crls=*/{});
270 EXPECT_TRUE(crl_provider.ok());
271 TlsServerCredentialsOptions options_1(provider);
272 options_1.set_crl_provider(*crl_provider);
273 TlsServerCredentialsOptions options_2(provider);
274 options_2.set_crl_provider(*crl_provider);
275 }
276
TEST(CredentialsTest,TlsServerCredentialsDoesNotLeak)277 TEST(CredentialsTest, TlsServerCredentialsDoesNotLeak) {
278 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
279 TlsServerCredentialsOptions options(provider);
280 auto server_creds = TlsServerCredentials(options);
281 EXPECT_NE(server_creds, nullptr);
282 }
283
TEST(CredentialsTest,MultipleServerCredentialsOneOptionsDoesNotLeak)284 TEST(CredentialsTest, MultipleServerCredentialsOneOptionsDoesNotLeak) {
285 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
286 TlsServerCredentialsOptions options(provider);
287 auto server_creds_1 = TlsServerCredentials(options);
288 EXPECT_NE(server_creds_1, nullptr);
289 auto server_creds_2 = TlsServerCredentials(options);
290 EXPECT_NE(server_creds_2, nullptr);
291 }
292
TEST(CredentialsTest,MultipleServerCredentialsOneCertificateVerifierDoesNotLeak)293 TEST(CredentialsTest,
294 MultipleServerCredentialsOneCertificateVerifierDoesNotLeak) {
295 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
296 TlsServerCredentialsOptions options(provider);
297 auto verifier = std::make_shared<NoOpCertificateVerifier>();
298 options.set_certificate_verifier(verifier);
299 auto server_creds_1 = TlsServerCredentials(options);
300 EXPECT_NE(server_creds_1, nullptr);
301 auto server_creds_2 = TlsServerCredentials(options);
302 EXPECT_NE(server_creds_2, nullptr);
303 }
304
TEST(CredentialsTest,MultipleServerCredentialsOneCrlProviderDoesNotLeak)305 TEST(CredentialsTest, MultipleServerCredentialsOneCrlProviderDoesNotLeak) {
306 auto provider = std::make_shared<StaticDataCertificateProvider>("root-pem");
307 TlsServerCredentialsOptions options(provider);
308 auto crl_provider = CreateStaticCrlProvider(/*crls=*/{});
309 EXPECT_TRUE(crl_provider.ok());
310 options.set_crl_provider(*crl_provider);
311 auto server_creds_1 = TlsServerCredentials(options);
312 EXPECT_NE(server_creds_1, nullptr);
313 auto server_creds_2 = TlsServerCredentials(options);
314 EXPECT_NE(server_creds_2, nullptr);
315 }
316
TEST(CredentialsTest,TlsServerCredentialsWithGoodMinMaxTlsVersions)317 TEST(CredentialsTest, TlsServerCredentialsWithGoodMinMaxTlsVersions) {
318 grpc::experimental::TlsServerCredentialsOptions options(
319 /*certificate_provider=*/nullptr);
320 options.set_min_tls_version(grpc_tls_version::TLS1_2);
321 options.set_max_tls_version(grpc_tls_version::TLS1_3);
322 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
323 EXPECT_NE(server_credentials, nullptr);
324 }
325
TEST(CredentialsTest,TlsServerCredentialsWithBadMinMaxTlsVersions)326 TEST(CredentialsTest, TlsServerCredentialsWithBadMinMaxTlsVersions) {
327 grpc::experimental::TlsServerCredentialsOptions options(
328 /*certificate_provider=*/nullptr);
329 options.set_min_tls_version(grpc_tls_version::TLS1_3);
330 options.set_max_tls_version(grpc_tls_version::TLS1_2);
331 auto server_credentials = grpc::experimental::TlsServerCredentials(options);
332 EXPECT_EQ(server_credentials, nullptr);
333 }
334
335 } // namespace
336 } // namespace testing
337 } // namespace grpc
338
main(int argc,char ** argv)339 int main(int argc, char** argv) {
340 ::testing::InitGoogleTest(&argc, argv);
341 grpc::testing::TestEnvironment env(&argc, argv);
342 int ret = RUN_ALL_TESTS();
343 return ret;
344 }
345