xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/crl_provider_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2023 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include <gtest/gtest.h>
23 
24 #include "absl/status/statusor.h"
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/string_view.h"
27 #include "absl/synchronization/notification.h"
28 
29 #include <grpc/grpc_crl_provider.h>
30 #include <grpc/grpc_security.h>
31 #include <grpc/support/log.h>
32 #include <grpcpp/channel.h>
33 #include <grpcpp/client_context.h>
34 #include <grpcpp/create_channel.h>
35 #include <grpcpp/security/credentials.h>
36 #include <grpcpp/security/server_credentials.h>
37 #include <grpcpp/security/tls_certificate_provider.h>
38 #include <grpcpp/security/tls_certificate_verifier.h>
39 #include <grpcpp/security/tls_credentials_options.h>
40 #include <grpcpp/server.h>
41 #include <grpcpp/server_builder.h>
42 #include <grpcpp/support/channel_arguments.h>
43 #include <grpcpp/support/status.h>
44 
45 #include "src/cpp/client/secure_credentials.h"
46 #include "src/proto/grpc/testing/echo_messages.pb.h"
47 #include "test/core/util/port.h"
48 #include "test/core/util/test_config.h"
49 #include "test/core/util/tls_utils.h"
50 #include "test/cpp/end2end/test_service_impl.h"
51 
52 // CRL Providers not supported for <1.1
53 #if OPENSSL_VERSION_NUMBER >= 0x10100000
54 namespace grpc {
55 namespace testing {
56 namespace {
57 
58 const char* kRootPath = "test/core/tsi/test_creds/crl_data/ca.pem";
59 const char* kRevokedKeyPath = "test/core/tsi/test_creds/crl_data/revoked.key";
60 const char* kRevokedCertPath = "test/core/tsi/test_creds/crl_data/revoked.pem";
61 const char* kValidKeyPath = "test/core/tsi/test_creds/crl_data/valid.key";
62 const char* kValidCertPath = "test/core/tsi/test_creds/crl_data/valid.pem";
63 const char* kRootCrlPath = "test/core/tsi/test_creds/crl_data/crls/current.crl";
64 const char* kCrlDirectoryPath =
65     "test/core/tsi/test_creds/crl_data/crl_provider_test_dir/";
66 constexpr char kMessage[] = "Hello";
67 
68 // This test must be at the top of the file because the
69 // DirectoryReloaderCrlProvider gets the default event engine on construction.
70 // To get the default event engine, grpc_init must have been called, otherwise a
71 // segfault occurs. This test checks that no segfault occurs while getting the
72 // default event engine during the construction of a
73 // DirectoryReloaderCrlProvider. `grpc_init` is global state, so if another test
74 // runs first, then this test could pass because of another test modifying the
75 // global state
TEST(DirectoryReloaderCrlProviderTestNoFixture,Construction)76 TEST(DirectoryReloaderCrlProviderTestNoFixture, Construction) {
77   auto provider = grpc_core::experimental::CreateDirectoryReloaderCrlProvider(
78       kCrlDirectoryPath, std::chrono::seconds(60), nullptr);
79   ASSERT_TRUE(provider.ok()) << provider.status();
80 }
81 
82 class CrlProviderTest : public ::testing::Test {
83  protected:
RunServer(absl::Notification * notification,absl::string_view server_key,absl::string_view server_cert)84   void RunServer(absl::Notification* notification, absl::string_view server_key,
85                  absl::string_view server_cert) {
86     experimental::IdentityKeyCertPair key_cert_pair;
87     std::string root = grpc_core::testing::GetFileContents(kRootPath);
88     key_cert_pair.private_key = server_key.data();
89     key_cert_pair.certificate_chain = server_cert.data();
90     std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs;
91     identity_key_cert_pairs.emplace_back(key_cert_pair);
92     auto certificate_provider =
93         std::make_shared<experimental::StaticDataCertificateProvider>(
94             root, identity_key_cert_pairs);
95     grpc::experimental::TlsServerCredentialsOptions options(
96         certificate_provider);
97     options.watch_root_certs();
98     options.set_root_cert_name("root");
99     options.watch_identity_key_cert_pairs();
100     options.set_identity_cert_name("identity");
101     options.set_cert_request_type(
102         GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
103     auto server_credentials = grpc::experimental::TlsServerCredentials(options);
104     GPR_ASSERT(server_credentials.get() != nullptr);
105 
106     grpc::ServerBuilder builder;
107     TestServiceImpl service_;
108 
109     builder.AddListeningPort(server_addr_, server_credentials);
110     builder.RegisterService("foo.test.google.fr", &service_);
111     server_ = builder.BuildAndStart();
112     notification->Notify();
113     server_->Wait();
114   }
115 
TearDown()116   void TearDown() override {
117     if (server_ != nullptr) {
118       server_->Shutdown();
119       server_thread_->join();
120       delete server_thread_;
121     }
122   }
123 
124   TestServiceImpl service_;
125   std::unique_ptr<Server> server_ = nullptr;
126   std::thread* server_thread_ = nullptr;
127   std::string server_addr_;
128 };
129 
DoRpc(const std::string & server_addr,const experimental::TlsChannelCredentialsOptions & tls_options,bool expect_success)130 void DoRpc(const std::string& server_addr,
131            const experimental::TlsChannelCredentialsOptions& tls_options,
132            bool expect_success) {
133   ChannelArguments channel_args;
134   channel_args.SetSslTargetNameOverride("foo.test.google.fr");
135   std::shared_ptr<Channel> channel = grpc::CreateCustomChannel(
136       server_addr, grpc::experimental::TlsCredentials(tls_options),
137       channel_args);
138 
139   auto stub = grpc::testing::EchoTestService::NewStub(channel);
140   grpc::testing::EchoRequest request;
141   grpc::testing::EchoResponse response;
142   request.set_message(kMessage);
143   ClientContext context;
144   context.set_deadline(grpc_timeout_seconds_to_deadline(/*time_s=*/10));
145   grpc::Status result = stub->Echo(&context, request, &response);
146   if (expect_success) {
147     EXPECT_TRUE(result.ok());
148     if (!result.ok()) {
149       gpr_log(GPR_ERROR, "%s, %s", result.error_message().c_str(),
150               result.error_details().c_str());
151     }
152     EXPECT_EQ(response.message(), kMessage);
153   } else {
154     EXPECT_FALSE(result.ok());
155   }
156 }
157 
TEST_F(CrlProviderTest,CrlProviderValidStaticProvider)158 TEST_F(CrlProviderTest, CrlProviderValidStaticProvider) {
159   server_addr_ = absl::StrCat("localhost:",
160                               std::to_string(grpc_pick_unused_port_or_die()));
161   absl::Notification notification;
162   std::string server_key = grpc_core::testing::GetFileContents(kValidKeyPath);
163   std::string server_cert = grpc_core::testing::GetFileContents(kValidCertPath);
164   server_thread_ = new std::thread(
165       [&]() { RunServer(&notification, server_key, server_cert); });
166   notification.WaitForNotification();
167 
168   std::string root_cert = grpc_core::testing::GetFileContents(kRootPath);
169   std::string client_key = grpc_core::testing::GetFileContents(kValidKeyPath);
170   std::string client_cert = grpc_core::testing::GetFileContents(kValidCertPath);
171   experimental::IdentityKeyCertPair key_cert_pair;
172   key_cert_pair.private_key = client_key;
173   key_cert_pair.certificate_chain = client_cert;
174   std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs;
175   identity_key_cert_pairs.emplace_back(key_cert_pair);
176   auto certificate_provider =
177       std::make_shared<experimental::StaticDataCertificateProvider>(
178           root_cert, identity_key_cert_pairs);
179   grpc::experimental::TlsChannelCredentialsOptions options;
180   options.set_certificate_provider(certificate_provider);
181   options.watch_root_certs();
182   options.set_root_cert_name("root");
183   options.watch_identity_key_cert_pairs();
184   options.set_identity_cert_name("identity");
185   std::string root_crl = grpc_core::testing::GetFileContents(kRootCrlPath);
186 
187   absl::StatusOr<std::shared_ptr<grpc_core::experimental::CrlProvider>>
188       provider = grpc_core::experimental::CreateStaticCrlProvider({root_crl});
189   ASSERT_TRUE(provider.ok());
190 
191   options.set_crl_provider(*provider);
192   options.set_check_call_host(false);
193   auto verifier = std::make_shared<experimental::NoOpCertificateVerifier>();
194   options.set_certificate_verifier(verifier);
195 
196   DoRpc(server_addr_, options, true);
197 }
198 
TEST_F(CrlProviderTest,CrlProviderRevokedServer)199 TEST_F(CrlProviderTest, CrlProviderRevokedServer) {
200   server_addr_ = absl::StrCat("localhost:",
201                               std::to_string(grpc_pick_unused_port_or_die()));
202   absl::Notification notification;
203   std::string server_key = grpc_core::testing::GetFileContents(kRevokedKeyPath);
204   std::string server_cert =
205       grpc_core::testing::GetFileContents(kRevokedCertPath);
206   server_thread_ = new std::thread(
207       [&]() { RunServer(&notification, server_key, server_cert); });
208   notification.WaitForNotification();
209 
210   std::string root_cert = grpc_core::testing::GetFileContents(kRootPath);
211   std::string client_key = grpc_core::testing::GetFileContents(kValidKeyPath);
212   std::string client_cert = grpc_core::testing::GetFileContents(kValidCertPath);
213   experimental::IdentityKeyCertPair key_cert_pair;
214   key_cert_pair.private_key = client_key;
215   key_cert_pair.certificate_chain = client_cert;
216   std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs;
217   identity_key_cert_pairs.emplace_back(key_cert_pair);
218   auto certificate_provider =
219       std::make_shared<experimental::StaticDataCertificateProvider>(
220           root_cert, identity_key_cert_pairs);
221   grpc::experimental::TlsChannelCredentialsOptions options;
222   options.set_certificate_provider(certificate_provider);
223   options.watch_root_certs();
224   options.set_root_cert_name("root");
225   options.watch_identity_key_cert_pairs();
226   options.set_identity_cert_name("identity");
227   std::string root_crl = grpc_core::testing::GetFileContents(kRootCrlPath);
228 
229   absl::StatusOr<std::shared_ptr<grpc_core::experimental::CrlProvider>>
230       provider = grpc_core::experimental::CreateStaticCrlProvider({root_crl});
231   ASSERT_TRUE(provider.ok());
232 
233   options.set_crl_provider(*provider);
234   options.set_check_call_host(false);
235   auto verifier = std::make_shared<experimental::NoOpCertificateVerifier>();
236   options.set_certificate_verifier(verifier);
237 
238   DoRpc(server_addr_, options, false);
239 }
240 
TEST_F(CrlProviderTest,CrlProviderValidReloaderProvider)241 TEST_F(CrlProviderTest, CrlProviderValidReloaderProvider) {
242   server_addr_ = absl::StrCat("localhost:",
243                               std::to_string(grpc_pick_unused_port_or_die()));
244   absl::Notification notification;
245   std::string server_key = grpc_core::testing::GetFileContents(kValidKeyPath);
246   std::string server_cert = grpc_core::testing::GetFileContents(kValidCertPath);
247   server_thread_ = new std::thread(
248       [&]() { RunServer(&notification, server_key, server_cert); });
249   notification.WaitForNotification();
250 
251   std::string root_cert = grpc_core::testing::GetFileContents(kRootPath);
252   std::string client_key = grpc_core::testing::GetFileContents(kValidKeyPath);
253   std::string client_cert = grpc_core::testing::GetFileContents(kValidCertPath);
254   experimental::IdentityKeyCertPair key_cert_pair;
255   key_cert_pair.private_key = client_key;
256   key_cert_pair.certificate_chain = client_cert;
257   std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs;
258   identity_key_cert_pairs.emplace_back(key_cert_pair);
259   auto certificate_provider =
260       std::make_shared<experimental::StaticDataCertificateProvider>(
261           root_cert, identity_key_cert_pairs);
262   grpc::experimental::TlsChannelCredentialsOptions options;
263   options.set_certificate_provider(certificate_provider);
264   options.watch_root_certs();
265   options.set_root_cert_name("root");
266   options.watch_identity_key_cert_pairs();
267   options.set_identity_cert_name("identity");
268 
269   absl::StatusOr<std::shared_ptr<grpc_core::experimental::CrlProvider>>
270       provider = grpc_core::experimental::CreateDirectoryReloaderCrlProvider(
271           kCrlDirectoryPath, std::chrono::seconds(60), nullptr);
272   ASSERT_TRUE(provider.ok());
273 
274   options.set_crl_provider(*provider);
275   options.set_check_call_host(false);
276   auto verifier = std::make_shared<experimental::NoOpCertificateVerifier>();
277   options.set_certificate_verifier(verifier);
278 
279   DoRpc(server_addr_, options, true);
280 }
281 
282 }  // namespace
283 }  // namespace testing
284 }  // namespace grpc
285 
286 #endif  // OPENSSL_VERSION_NUMBER >= 0x10100000
287 
main(int argc,char ** argv)288 int main(int argc, char** argv) {
289   grpc::testing::TestEnvironment env(&argc, argv);
290   ::testing::InitGoogleTest(&argc, argv);
291   int ret = RUN_ALL_TESTS();
292   return ret;
293 }
294