• 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 <grpc/support/port_platform.h>
20 
21 #include "src/core/ext/xds/file_watcher_certificate_provider_factory.h"
22 
23 #include "absl/strings/str_format.h"
24 #include "absl/strings/str_join.h"
25 
26 #include "src/core/ext/xds/certificate_provider_registry.h"
27 #include "src/core/lib/json/json_util.h"
28 
29 namespace grpc_core {
30 
31 namespace {
32 
33 const char* kFileWatcherPlugin = "file_watcher";
34 
35 }  // namespace
36 
37 //
38 // FileWatcherCertificateProviderFactory::Config
39 //
40 
name() const41 const char* FileWatcherCertificateProviderFactory::Config::name() const {
42   return kFileWatcherPlugin;
43 }
44 
ToString() const45 std::string FileWatcherCertificateProviderFactory::Config::ToString() const {
46   std::vector<std::string> parts;
47   parts.push_back("{");
48   if (!identity_cert_file_.empty()) {
49     parts.push_back(
50         absl::StrFormat("certificate_file=\"%s\", ", identity_cert_file_));
51   }
52   if (!identity_cert_file_.empty()) {
53     parts.push_back(
54         absl::StrFormat("private_key_file=\"%s\", ", private_key_file_));
55   }
56   if (!identity_cert_file_.empty()) {
57     parts.push_back(
58         absl::StrFormat("ca_certificate_file=\"%s\", ", root_cert_file_));
59   }
60   parts.push_back(
61       absl::StrFormat("refresh_interval=%ldms}", refresh_interval_ms_));
62   return absl::StrJoin(parts, "");
63 }
64 
65 RefCountedPtr<FileWatcherCertificateProviderFactory::Config>
Parse(const Json & config_json,grpc_error ** error)66 FileWatcherCertificateProviderFactory::Config::Parse(const Json& config_json,
67                                                      grpc_error** error) {
68   auto config = MakeRefCounted<FileWatcherCertificateProviderFactory::Config>();
69   if (config_json.type() != Json::Type::OBJECT) {
70     *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
71         "error:config type should be OBJECT.");
72     return nullptr;
73   }
74   std::vector<grpc_error*> error_list;
75   ParseJsonObjectField(config_json.object_value(), "certificate_file",
76                        &config->identity_cert_file_, &error_list, false);
77   ParseJsonObjectField(config_json.object_value(), "private_key_file",
78                        &config->private_key_file_, &error_list, false);
79   if (config->identity_cert_file_.empty() !=
80       config->private_key_file_.empty()) {
81     error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
82         "fields \"certificate_file\" and \"private_key_file\" must be both set "
83         "or both unset."));
84   }
85   ParseJsonObjectField(config_json.object_value(), "ca_certificate_file",
86                        &config->root_cert_file_, &error_list, false);
87   if (config->identity_cert_file_.empty() && config->root_cert_file_.empty()) {
88     error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
89         "At least one of \"certificate_file\" and \"ca_certificate_file\" must "
90         "be specified."));
91   }
92   if (!ParseJsonObjectFieldAsDuration(
93           config_json.object_value(), "refresh_interval",
94           &config->refresh_interval_ms_, &error_list, false)) {
95     config->refresh_interval_ms_ = 10 * 60 * 1000;  // 10 minutes default
96   }
97   if (!error_list.empty()) {
98     *error = GRPC_ERROR_CREATE_FROM_VECTOR(
99         "Error parsing file watcher certificate provider config", &error_list);
100     return nullptr;
101   }
102   return config;
103 }
104 
105 //
106 // FileWatcherCertificateProviderFactory
107 //
108 
name() const109 const char* FileWatcherCertificateProviderFactory::name() const {
110   return kFileWatcherPlugin;
111 }
112 
113 RefCountedPtr<CertificateProviderFactory::Config>
CreateCertificateProviderConfig(const Json & config_json,grpc_error ** error)114 FileWatcherCertificateProviderFactory::CreateCertificateProviderConfig(
115     const Json& config_json, grpc_error** error) {
116   return FileWatcherCertificateProviderFactory::Config::Parse(config_json,
117                                                               error);
118 }
119 
120 RefCountedPtr<grpc_tls_certificate_provider>
CreateCertificateProvider(RefCountedPtr<CertificateProviderFactory::Config> config)121 FileWatcherCertificateProviderFactory::CreateCertificateProvider(
122     RefCountedPtr<CertificateProviderFactory::Config> config) {
123   if (config->name() != name()) {
124     gpr_log(GPR_ERROR, "Wrong config type Actual:%s vs Expected:%s",
125             config->name(), name());
126     return nullptr;
127   }
128   auto* file_watcher_config =
129       static_cast<FileWatcherCertificateProviderFactory::Config*>(config.get());
130   return MakeRefCounted<FileWatcherCertificateProvider>(
131       file_watcher_config->private_key_file(),
132       file_watcher_config->identity_cert_file(),
133       file_watcher_config->root_cert_file(),
134       file_watcher_config->refresh_interval_ms() / GPR_MS_PER_SEC);
135 }
136 
FileWatcherCertificateProviderInit()137 void FileWatcherCertificateProviderInit() {
138   CertificateProviderRegistry::RegisterCertificateProviderFactory(
139       absl::make_unique<FileWatcherCertificateProviderFactory>());
140 }
141 
FileWatcherCertificateProviderShutdown()142 void FileWatcherCertificateProviderShutdown() {}
143 
144 }  // namespace grpc_core
145