1 /*
2 *
3 * Copyright 2018 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/lib/security/security_connector/tls/tls_security_connector.h"
20
21 #include <gmock/gmock.h>
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/log.h>
24 #include <grpc/support/string_util.h>
25 #include <gtest/gtest.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "src/core/lib/iomgr/load_file.h"
30 #include "src/core/tsi/transport_security.h"
31 #include "test/core/util/test_config.h"
32
33 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
34 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
35 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
36
37 namespace {
38
39 enum CredReloadResult { FAIL, SUCCESS, UNCHANGED, ASYNC };
40
SetKeyMaterials(grpc_tls_key_materials_config * config)41 void SetKeyMaterials(grpc_tls_key_materials_config* config) {
42 grpc_slice ca_slice, cert_slice, key_slice;
43 GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
44 grpc_load_file(CA_CERT_PATH, 1, &ca_slice)));
45 GPR_ASSERT(GRPC_LOG_IF_ERROR(
46 "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice)));
47 GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
48 grpc_load_file(SERVER_KEY_PATH, 1, &key_slice)));
49 const char* ca_cert =
50 reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
51 const char* server_cert =
52 reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
53 const char* server_key =
54 reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
55 grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert};
56 const auto* pem_key_cert_pair_ptr = &pem_key_cert_pair;
57 grpc_tls_key_materials_config_set_key_materials(config, ca_cert,
58 &pem_key_cert_pair_ptr, 1);
59 grpc_slice_unref(cert_slice);
60 grpc_slice_unref(key_slice);
61 grpc_slice_unref(ca_slice);
62 }
63
CredReloadSuccess(void *,grpc_tls_credential_reload_arg * arg)64 int CredReloadSuccess(void* /*config_user_data*/,
65 grpc_tls_credential_reload_arg* arg) {
66 SetKeyMaterials(arg->key_materials_config);
67 arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW;
68 return 0;
69 }
70
CredReloadFail(void *,grpc_tls_credential_reload_arg * arg)71 int CredReloadFail(void* /*config_user_data*/,
72 grpc_tls_credential_reload_arg* arg) {
73 arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL;
74 return 0;
75 }
76
CredReloadUnchanged(void *,grpc_tls_credential_reload_arg * arg)77 int CredReloadUnchanged(void* /*config_user_data*/,
78 grpc_tls_credential_reload_arg* arg) {
79 arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
80 return 0;
81 }
82
CredReloadAsync(void *,grpc_tls_credential_reload_arg *)83 int CredReloadAsync(void* /*config_user_data*/,
84 grpc_tls_credential_reload_arg* /*arg*/) {
85 return 1;
86 }
87
88 } // namespace
89
90 namespace grpc {
91 namespace testing {
92
93 class TlsSecurityConnectorTest : public ::testing::Test {
94 protected:
TlsSecurityConnectorTest()95 TlsSecurityConnectorTest() {}
SetUp()96 void SetUp() override {
97 options_ = grpc_tls_credentials_options_create()->Ref();
98 config_ = grpc_tls_key_materials_config_create()->Ref();
99 }
TearDown()100 void TearDown() override { config_->Unref(); }
101 // Set credential reload config in options.
SetOptions(CredReloadResult type)102 void SetOptions(CredReloadResult type) {
103 grpc_tls_credential_reload_config* reload_config = nullptr;
104 switch (type) {
105 case SUCCESS:
106 reload_config = grpc_tls_credential_reload_config_create(
107 nullptr, CredReloadSuccess, nullptr, nullptr);
108 break;
109 case FAIL:
110 reload_config = grpc_tls_credential_reload_config_create(
111 nullptr, CredReloadFail, nullptr, nullptr);
112 break;
113 case UNCHANGED:
114 reload_config = grpc_tls_credential_reload_config_create(
115 nullptr, CredReloadUnchanged, nullptr, nullptr);
116 break;
117 case ASYNC:
118 reload_config = grpc_tls_credential_reload_config_create(
119 nullptr, CredReloadAsync, nullptr, nullptr);
120 break;
121 default:
122 break;
123 }
124 grpc_tls_credentials_options_set_credential_reload_config(options_.get(),
125 reload_config);
126 }
127 // Set key materials config.
SetKeyMaterialsConfig()128 void SetKeyMaterialsConfig() { SetKeyMaterials(config_.get()); }
129 grpc_core::RefCountedPtr<grpc_tls_credentials_options> options_;
130 grpc_core::RefCountedPtr<grpc_tls_key_materials_config> config_;
131 };
132
TEST_F(TlsSecurityConnectorTest,NoKeysAndConfig)133 TEST_F(TlsSecurityConnectorTest, NoKeysAndConfig) {
134 grpc_ssl_certificate_config_reload_status reload_status;
135 grpc_status_code status =
136 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
137 EXPECT_EQ(status, GRPC_STATUS_FAILED_PRECONDITION);
138 options_->Unref();
139 }
140
TEST_F(TlsSecurityConnectorTest,NoKeysAndConfigAsAClient)141 TEST_F(TlsSecurityConnectorTest, NoKeysAndConfigAsAClient) {
142 grpc_ssl_certificate_config_reload_status reload_status;
143 grpc_status_code status =
144 TlsFetchKeyMaterials(config_, *options_, false, &reload_status);
145 EXPECT_EQ(status, GRPC_STATUS_OK);
146 options_->Unref();
147 }
148
TEST_F(TlsSecurityConnectorTest,NoKeySuccessReload)149 TEST_F(TlsSecurityConnectorTest, NoKeySuccessReload) {
150 grpc_ssl_certificate_config_reload_status reload_status;
151 SetOptions(SUCCESS);
152 grpc_status_code status =
153 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
154 EXPECT_EQ(status, GRPC_STATUS_OK);
155 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW);
156 options_->Unref();
157 }
158
TEST_F(TlsSecurityConnectorTest,NoKeyFailReload)159 TEST_F(TlsSecurityConnectorTest, NoKeyFailReload) {
160 grpc_ssl_certificate_config_reload_status reload_status;
161 SetOptions(FAIL);
162 grpc_status_code status =
163 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
164 EXPECT_EQ(status, GRPC_STATUS_INTERNAL);
165 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL);
166 options_->Unref();
167 }
168
TEST_F(TlsSecurityConnectorTest,NoKeyAsyncReload)169 TEST_F(TlsSecurityConnectorTest, NoKeyAsyncReload) {
170 grpc_ssl_certificate_config_reload_status reload_status =
171 GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
172 SetOptions(ASYNC);
173 grpc_status_code status =
174 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
175 EXPECT_EQ(status, GRPC_STATUS_UNIMPLEMENTED);
176 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
177 options_->Unref();
178 }
179
TEST_F(TlsSecurityConnectorTest,NoKeyUnchangedReload)180 TEST_F(TlsSecurityConnectorTest, NoKeyUnchangedReload) {
181 grpc_ssl_certificate_config_reload_status reload_status =
182 GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
183 SetOptions(UNCHANGED);
184 grpc_status_code status =
185 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
186 EXPECT_EQ(status, GRPC_STATUS_OK);
187 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
188 options_->Unref();
189 }
190
TEST_F(TlsSecurityConnectorTest,WithKeyNoReload)191 TEST_F(TlsSecurityConnectorTest, WithKeyNoReload) {
192 grpc_ssl_certificate_config_reload_status reload_status =
193 GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
194 SetKeyMaterialsConfig();
195 grpc_status_code status =
196 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
197 EXPECT_EQ(status, GRPC_STATUS_OK);
198 options_->Unref();
199 }
200
TEST_F(TlsSecurityConnectorTest,WithKeySuccessReload)201 TEST_F(TlsSecurityConnectorTest, WithKeySuccessReload) {
202 grpc_ssl_certificate_config_reload_status reload_status;
203 SetOptions(SUCCESS);
204 SetKeyMaterialsConfig();
205 grpc_status_code status =
206 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
207 EXPECT_EQ(status, GRPC_STATUS_OK);
208 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW);
209 options_->Unref();
210 }
211
TEST_F(TlsSecurityConnectorTest,WithKeyFailReload)212 TEST_F(TlsSecurityConnectorTest, WithKeyFailReload) {
213 grpc_ssl_certificate_config_reload_status reload_status;
214 SetOptions(FAIL);
215 SetKeyMaterialsConfig();
216 grpc_status_code status =
217 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
218 EXPECT_EQ(status, GRPC_STATUS_OK);
219 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL);
220 options_->Unref();
221 }
222
TEST_F(TlsSecurityConnectorTest,WithKeyAsyncReload)223 TEST_F(TlsSecurityConnectorTest, WithKeyAsyncReload) {
224 grpc_ssl_certificate_config_reload_status reload_status =
225 GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
226 SetOptions(ASYNC);
227 SetKeyMaterialsConfig();
228 grpc_status_code status =
229 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
230 EXPECT_EQ(status, GRPC_STATUS_OK);
231 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
232 options_->Unref();
233 }
234
TEST_F(TlsSecurityConnectorTest,WithKeyUnchangedReload)235 TEST_F(TlsSecurityConnectorTest, WithKeyUnchangedReload) {
236 grpc_ssl_certificate_config_reload_status reload_status =
237 GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
238 SetOptions(UNCHANGED);
239 SetKeyMaterialsConfig();
240 grpc_status_code status =
241 TlsFetchKeyMaterials(config_, *options_, true, &reload_status);
242 EXPECT_EQ(status, GRPC_STATUS_OK);
243 EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
244 options_->Unref();
245 }
246
TEST_F(TlsSecurityConnectorTest,CreateChannelSecurityConnectorSuccess)247 TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorSuccess) {
248 SetOptions(SUCCESS);
249 auto cred = std::unique_ptr<grpc_channel_credentials>(
250 grpc_tls_credentials_create(options_.get()));
251 const char* target_name = "some_target";
252 grpc_channel_args* new_args = nullptr;
253 auto connector =
254 cred->create_security_connector(nullptr, target_name, nullptr, &new_args);
255 EXPECT_NE(connector, nullptr);
256 grpc_channel_args_destroy(new_args);
257 }
258
TEST_F(TlsSecurityConnectorTest,CreateChannelSecurityConnectorFailNoTargetName)259 TEST_F(TlsSecurityConnectorTest,
260 CreateChannelSecurityConnectorFailNoTargetName) {
261 SetOptions(SUCCESS);
262 auto cred = std::unique_ptr<grpc_channel_credentials>(
263 grpc_tls_credentials_create(options_.get()));
264 grpc_channel_args* new_args = nullptr;
265 auto connector =
266 cred->create_security_connector(nullptr, nullptr, nullptr, &new_args);
267 EXPECT_EQ(connector, nullptr);
268 }
269
TEST_F(TlsSecurityConnectorTest,CreateChannelSecurityConnectorFailInit)270 TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorFailInit) {
271 SetOptions(FAIL);
272 auto cred = std::unique_ptr<grpc_channel_credentials>(
273 grpc_tls_credentials_create(options_.get()));
274 grpc_channel_args* new_args = nullptr;
275 auto connector =
276 cred->create_security_connector(nullptr, nullptr, nullptr, &new_args);
277 EXPECT_EQ(connector, nullptr);
278 }
279
TEST_F(TlsSecurityConnectorTest,TlsCheckHostNameSuccess)280 TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameSuccess) {
281 const char* target_name = "foo.test.google.fr";
282 tsi_peer peer;
283 GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
284 GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
285 TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, target_name,
286 &peer.properties[0]) == TSI_OK);
287 grpc_error* error = grpc_core::TlsCheckHostName(target_name, &peer);
288 tsi_peer_destruct(&peer);
289 EXPECT_EQ(error, GRPC_ERROR_NONE);
290 GRPC_ERROR_UNREF(error);
291 options_->Unref();
292 }
293
TEST_F(TlsSecurityConnectorTest,TlsCheckHostNameFail)294 TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameFail) {
295 const char* target_name = "foo.test.google.fr";
296 const char* another_name = "bar.test.google.fr";
297 tsi_peer peer;
298 GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
299 GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
300 TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, another_name,
301 &peer.properties[0]) == TSI_OK);
302 grpc_error* error = grpc_core::TlsCheckHostName(target_name, &peer);
303 tsi_peer_destruct(&peer);
304 EXPECT_NE(error, GRPC_ERROR_NONE);
305 GRPC_ERROR_UNREF(error);
306 options_->Unref();
307 }
308
TEST_F(TlsSecurityConnectorTest,CreateServerSecurityConnectorSuccess)309 TEST_F(TlsSecurityConnectorTest, CreateServerSecurityConnectorSuccess) {
310 SetOptions(SUCCESS);
311 auto cred = std::unique_ptr<grpc_server_credentials>(
312 grpc_tls_server_credentials_create(options_.get()));
313 auto connector = cred->create_security_connector();
314 EXPECT_NE(connector, nullptr);
315 }
316
TEST_F(TlsSecurityConnectorTest,CreateServerSecurityConnectorFailInit)317 TEST_F(TlsSecurityConnectorTest, CreateServerSecurityConnectorFailInit) {
318 SetOptions(FAIL);
319 auto cred = std::unique_ptr<grpc_server_credentials>(
320 grpc_tls_server_credentials_create(options_.get()));
321 auto connector = cred->create_security_connector();
322 EXPECT_EQ(connector, nullptr);
323 }
324
325 } // namespace testing
326 } // namespace grpc
327
main(int argc,char ** argv)328 int main(int argc, char** argv) {
329 grpc::testing::TestEnvironment env(argc, argv);
330 ::testing::InitGoogleTest(&argc, argv);
331 grpc_init();
332 int ret = RUN_ALL_TESTS();
333 grpc_shutdown();
334 return ret;
335 }
336