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