• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2020 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 
19 #include "src/core/xds/grpc/file_watcher_certificate_provider_factory.h"
20 
21 #include <grpc/grpc.h>
22 
23 #include <utility>
24 
25 #include "absl/status/status.h"
26 #include "absl/status/statusor.h"
27 #include "absl/strings/str_format.h"
28 #include "gtest/gtest.h"
29 #include "src/core/util/json/json_reader.h"
30 #include "test/core/test_util/test_config.h"
31 
32 namespace grpc_core {
33 namespace testing {
34 namespace {
35 
36 const char* kIdentityCertFile = "/path/to/identity_cert_file";
37 const char* kPrivateKeyFile = "/path/to/private_key_file";
38 const char* kRootCertFile = "/path/to/root_cert_file";
39 const int kRefreshInterval = 400;
40 
41 absl::StatusOr<RefCountedPtr<FileWatcherCertificateProviderFactory::Config>>
ParseConfig(absl::string_view json_string)42 ParseConfig(absl::string_view json_string) {
43   auto json = JsonParse(json_string);
44   if (!json.ok()) return json.status();
45   ValidationErrors errors;
46   auto config =
47       FileWatcherCertificateProviderFactory().CreateCertificateProviderConfig(
48           *json, JsonArgs(), &errors);
49   if (!errors.ok()) {
50     return errors.status(absl::StatusCode::kInvalidArgument,
51                          "validation errors");
52   }
53   return config.TakeAsSubclass<FileWatcherCertificateProviderFactory::Config>();
54 }
55 
TEST(FileWatcherConfigTest,Basic)56 TEST(FileWatcherConfigTest, Basic) {
57   std::string json_str = absl::StrFormat(
58       "{"
59       "  \"certificate_file\": \"%s\","
60       "  \"private_key_file\": \"%s\","
61       "  \"ca_certificate_file\": \"%s\","
62       "  \"refresh_interval\": \"%ds\""
63       "}",
64       kIdentityCertFile, kPrivateKeyFile, kRootCertFile, kRefreshInterval);
65   auto config = ParseConfig(json_str);
66   ASSERT_TRUE(config.ok()) << config.status();
67   EXPECT_EQ((*config)->identity_cert_file(), kIdentityCertFile);
68   EXPECT_EQ((*config)->private_key_file(), kPrivateKeyFile);
69   EXPECT_EQ((*config)->root_cert_file(), kRootCertFile);
70   EXPECT_EQ((*config)->refresh_interval(), Duration::Seconds(kRefreshInterval));
71 }
72 
TEST(FileWatcherConfigTest,DefaultRefreshInterval)73 TEST(FileWatcherConfigTest, DefaultRefreshInterval) {
74   std::string json_str = absl::StrFormat(
75       "{"
76       "  \"certificate_file\": \"%s\","
77       "  \"private_key_file\": \"%s\","
78       "  \"ca_certificate_file\": \"%s\""
79       "}",
80       kIdentityCertFile, kPrivateKeyFile, kRootCertFile);
81   auto config = ParseConfig(json_str);
82   ASSERT_TRUE(config.ok()) << config.status();
83   EXPECT_EQ((*config)->identity_cert_file(), kIdentityCertFile);
84   EXPECT_EQ((*config)->private_key_file(), kPrivateKeyFile);
85   EXPECT_EQ((*config)->root_cert_file(), kRootCertFile);
86   EXPECT_EQ((*config)->refresh_interval(), Duration::Seconds(600));
87 }
88 
TEST(FileWatcherConfigTest,OnlyRootCertificatesFileProvided)89 TEST(FileWatcherConfigTest, OnlyRootCertificatesFileProvided) {
90   std::string json_str = absl::StrFormat(
91       "{"
92       "  \"ca_certificate_file\": \"%s\""
93       "}",
94       kRootCertFile);
95   auto config = ParseConfig(json_str);
96   ASSERT_TRUE(config.ok()) << config.status();
97   EXPECT_EQ((*config)->identity_cert_file(), "");
98   EXPECT_EQ((*config)->private_key_file(), "");
99   EXPECT_EQ((*config)->root_cert_file(), kRootCertFile);
100   EXPECT_EQ((*config)->refresh_interval(), Duration::Seconds(600));
101 }
102 
TEST(FileWatcherConfigTest,OnlyIdentityCertificatesAndPrivateKeyProvided)103 TEST(FileWatcherConfigTest, OnlyIdentityCertificatesAndPrivateKeyProvided) {
104   std::string json_str = absl::StrFormat(
105       "{"
106       "  \"certificate_file\": \"%s\","
107       "  \"private_key_file\": \"%s\""
108       "}",
109       kIdentityCertFile, kPrivateKeyFile);
110   auto config = ParseConfig(json_str);
111   ASSERT_TRUE(config.ok()) << config.status();
112   EXPECT_EQ((*config)->identity_cert_file(), kIdentityCertFile);
113   EXPECT_EQ((*config)->private_key_file(), kPrivateKeyFile);
114   EXPECT_EQ((*config)->root_cert_file(), "");
115   EXPECT_EQ((*config)->refresh_interval(), Duration::Seconds(600));
116 }
117 
TEST(FileWatcherConfigTest,WrongTypes)118 TEST(FileWatcherConfigTest, WrongTypes) {
119   const char* json_str =
120       "{"
121       "  \"certificate_file\": 123,"
122       "  \"private_key_file\": 123,"
123       "  \"ca_certificate_file\": 123,"
124       "  \"refresh_interval\": 123"
125       "}";
126   auto config = ParseConfig(json_str);
127   EXPECT_EQ(config.status().message(),
128             "validation errors: ["
129             "field:ca_certificate_file error:is not a string; "
130             "field:certificate_file error:is not a string; "
131             "field:private_key_file error:is not a string; "
132             "field:refresh_interval error:is not a string]")
133       << config.status();
134 }
135 
TEST(FileWatcherConfigTest,IdentityCertProvidedButPrivateKeyMissing)136 TEST(FileWatcherConfigTest, IdentityCertProvidedButPrivateKeyMissing) {
137   std::string json_str = absl::StrFormat(
138       "{"
139       "  \"certificate_file\": \"%s\""
140       "}",
141       kIdentityCertFile);
142   auto config = ParseConfig(json_str);
143   EXPECT_EQ(config.status().message(),
144             "validation errors: ["
145             "field: error:fields \"certificate_file\" and "
146             "\"private_key_file\" must be both set or both unset]")
147       << config.status();
148 }
149 
TEST(FileWatcherConfigTest,PrivateKeyProvidedButIdentityCertMissing)150 TEST(FileWatcherConfigTest, PrivateKeyProvidedButIdentityCertMissing) {
151   std::string json_str = absl::StrFormat(
152       "{"
153       "  \"ca_certificate_file\": \"%s\","
154       "  \"private_key_file\": \"%s\""
155       "}",
156       kRootCertFile, kPrivateKeyFile);
157   auto config = ParseConfig(json_str);
158   EXPECT_EQ(config.status().message(),
159             "validation errors: ["
160             "field: error:fields \"certificate_file\" and "
161             "\"private_key_file\" must be both set or both unset]")
162       << config.status();
163 }
164 
TEST(FileWatcherConfigTest,EmptyJsonObject)165 TEST(FileWatcherConfigTest, EmptyJsonObject) {
166   std::string json_str = "{}";
167   auto config = ParseConfig(json_str);
168   EXPECT_EQ(config.status().message(),
169             "validation errors: ["
170             "field: error:at least one of \"certificate_file\" and "
171             "\"ca_certificate_file\" must be specified]")
172       << config.status();
173 }
174 
175 }  // namespace
176 }  // namespace testing
177 }  // namespace grpc_core
178 
main(int argc,char ** argv)179 int main(int argc, char** argv) {
180   ::testing::InitGoogleTest(&argc, argv);
181   grpc::testing::TestEnvironment env(&argc, argv);
182   grpc_init();
183   auto result = RUN_ALL_TESTS();
184   grpc_shutdown();
185   return result;
186 }
187