• 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 <algorithm>
24 #include <initializer_list>
25 #include <map>
26 #include <memory>
27 #include <vector>
28 
29 #include "absl/strings/str_format.h"
30 #include "absl/strings/str_join.h"
31 
32 #include <grpc/support/log.h>
33 #include <grpc/support/time.h>
34 
35 #include "src/core/lib/config/core_configuration.h"
36 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
37 
38 namespace grpc_core {
39 
40 namespace {
41 
42 constexpr absl::string_view kFileWatcherPlugin = "file_watcher";
43 
44 }  // namespace
45 
46 //
47 // FileWatcherCertificateProviderFactory::Config
48 //
49 
name() const50 absl::string_view FileWatcherCertificateProviderFactory::Config::name() const {
51   return kFileWatcherPlugin;
52 }
53 
ToString() const54 std::string FileWatcherCertificateProviderFactory::Config::ToString() const {
55   std::vector<std::string> parts;
56   parts.push_back("{");
57   if (!identity_cert_file_.empty()) {
58     parts.push_back(
59         absl::StrFormat("certificate_file=\"%s\", ", identity_cert_file_));
60   }
61   if (!identity_cert_file_.empty()) {
62     parts.push_back(
63         absl::StrFormat("private_key_file=\"%s\", ", private_key_file_));
64   }
65   if (!identity_cert_file_.empty()) {
66     parts.push_back(
67         absl::StrFormat("ca_certificate_file=\"%s\", ", root_cert_file_));
68   }
69   parts.push_back(
70       absl::StrFormat("refresh_interval=%ldms}", refresh_interval_.millis()));
71   return absl::StrJoin(parts, "");
72 }
73 
74 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)75 FileWatcherCertificateProviderFactory::Config::JsonLoader(const JsonArgs&) {
76   static const auto* loader =
77       JsonObjectLoader<Config>()
78           .OptionalField("certificate_file", &Config::identity_cert_file_)
79           .OptionalField("private_key_file", &Config::private_key_file_)
80           .OptionalField("ca_certificate_file", &Config::root_cert_file_)
81           .OptionalField("refresh_interval", &Config::refresh_interval_)
82           .Finish();
83   return loader;
84 }
85 
JsonPostLoad(const Json & json,const JsonArgs &,ValidationErrors * errors)86 void FileWatcherCertificateProviderFactory::Config::JsonPostLoad(
87     const Json& json, const JsonArgs& /*args*/, ValidationErrors* errors) {
88   if ((json.object().find("certificate_file") == json.object().end()) !=
89       (json.object().find("private_key_file") == json.object().end())) {
90     errors->AddError(
91         "fields \"certificate_file\" and \"private_key_file\" must be both set "
92         "or both unset");
93   }
94   if ((json.object().find("certificate_file") == json.object().end()) &&
95       (json.object().find("ca_certificate_file") == json.object().end())) {
96     errors->AddError(
97         "at least one of \"certificate_file\" and \"ca_certificate_file\" must "
98         "be specified");
99   }
100 }
101 
102 //
103 // FileWatcherCertificateProviderFactory
104 //
105 
name() const106 absl::string_view FileWatcherCertificateProviderFactory::name() const {
107   return kFileWatcherPlugin;
108 }
109 
110 RefCountedPtr<CertificateProviderFactory::Config>
CreateCertificateProviderConfig(const Json & config_json,const JsonArgs & args,ValidationErrors * errors)111 FileWatcherCertificateProviderFactory::CreateCertificateProviderConfig(
112     const Json& config_json, const JsonArgs& args, ValidationErrors* errors) {
113   return LoadFromJson<RefCountedPtr<Config>>(config_json, args, errors);
114 }
115 
116 RefCountedPtr<grpc_tls_certificate_provider>
CreateCertificateProvider(RefCountedPtr<CertificateProviderFactory::Config> config)117 FileWatcherCertificateProviderFactory::CreateCertificateProvider(
118     RefCountedPtr<CertificateProviderFactory::Config> config) {
119   if (config->name() != name()) {
120     gpr_log(GPR_ERROR, "Wrong config type Actual:%s vs Expected:%s",
121             std::string(config->name()).c_str(), std::string(name()).c_str());
122     return nullptr;
123   }
124   auto* file_watcher_config =
125       static_cast<FileWatcherCertificateProviderFactory::Config*>(config.get());
126   return MakeRefCounted<FileWatcherCertificateProvider>(
127       file_watcher_config->private_key_file(),
128       file_watcher_config->identity_cert_file(),
129       file_watcher_config->root_cert_file(),
130       file_watcher_config->refresh_interval().millis() / GPR_MS_PER_SEC);
131 }
132 
RegisterFileWatcherCertificateProvider(CoreConfiguration::Builder * builder)133 void RegisterFileWatcherCertificateProvider(
134     CoreConfiguration::Builder* builder) {
135   builder->certificate_provider_registry()->RegisterCertificateProviderFactory(
136       std::make_unique<FileWatcherCertificateProviderFactory>());
137 }
138 
139 }  // namespace grpc_core
140