Imported Upstream version 1.34.0
[platform/upstream/grpc.git] / src / core / ext / xds / google_mesh_ca_certificate_provider_factory.cc
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/google_mesh_ca_certificate_provider_factory.h"
22
23 #include <sstream>
24 #include <type_traits>
25
26 #include "absl/strings/str_cat.h"
27
28 #include <grpc/support/string_util.h>
29
30 #include "src/core/lib/gpr/string.h"
31 #include "src/core/lib/iomgr/error.h"
32 #include "src/core/lib/json/json_util.h"
33
34 namespace grpc_core {
35
36 namespace {
37
38 const char* kMeshCaPlugin = "meshCA";
39
40 }  // namespace
41
42 //
43 // GoogleMeshCaCertificateProviderFactory::Config
44 //
45
46 const char* GoogleMeshCaCertificateProviderFactory::Config::name() const {
47   return kMeshCaPlugin;
48 }
49
50 std::string GoogleMeshCaCertificateProviderFactory::Config::ToString() const {
51   // TODO(yashykt): To be filled
52   return "{}";
53 }
54
55 std::vector<grpc_error*>
56 GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectStsService(
57     const Json::Object& sts_service) {
58   std::vector<grpc_error*> error_list_sts_service;
59   if (!ParseJsonObjectField(sts_service, "token_exchange_service_uri",
60                             &sts_config_.token_exchange_service_uri,
61                             &error_list_sts_service, false)) {
62     sts_config_.token_exchange_service_uri =
63         "securetoken.googleapis.com";  // default
64   }
65   ParseJsonObjectField(sts_service, "resource", &sts_config_.resource,
66                        &error_list_sts_service, false);
67   ParseJsonObjectField(sts_service, "audience", &sts_config_.audience,
68                        &error_list_sts_service, false);
69   if (!ParseJsonObjectField(sts_service, "scope", &sts_config_.scope,
70                             &error_list_sts_service, false)) {
71     sts_config_.scope =
72         "https://www.googleapis.com/auth/cloud-platform";  // default
73   }
74   ParseJsonObjectField(sts_service, "requested_token_type",
75                        &sts_config_.requested_token_type,
76                        &error_list_sts_service, false);
77   ParseJsonObjectField(sts_service, "subject_token_path",
78                        &sts_config_.subject_token_path,
79                        &error_list_sts_service);
80   ParseJsonObjectField(sts_service, "subject_token_type",
81                        &sts_config_.subject_token_type,
82                        &error_list_sts_service);
83   ParseJsonObjectField(sts_service, "actor_token_path",
84                        &sts_config_.actor_token_path, &error_list_sts_service,
85                        false);
86   ParseJsonObjectField(sts_service, "actor_token_type",
87                        &sts_config_.actor_token_type, &error_list_sts_service,
88                        false);
89   return error_list_sts_service;
90 }
91
92 std::vector<grpc_error*>
93 GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectCallCredentials(
94     const Json::Object& call_credentials) {
95   std::vector<grpc_error*> error_list_call_credentials;
96   const Json::Object* sts_service = nullptr;
97   if (ParseJsonObjectField(call_credentials, "sts_service", &sts_service,
98                            &error_list_call_credentials)) {
99     std::vector<grpc_error*> error_list_sts_service =
100         ParseJsonObjectStsService(*sts_service);
101     if (!error_list_sts_service.empty()) {
102       error_list_call_credentials.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
103           "field:sts_service", &error_list_sts_service));
104     }
105   }
106   return error_list_call_credentials;
107 }
108
109 std::vector<grpc_error*>
110 GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGoogleGrpc(
111     const Json::Object& google_grpc) {
112   std::vector<grpc_error*> error_list_google_grpc;
113   if (!ParseJsonObjectField(google_grpc, "target_uri", &endpoint_,
114                             &error_list_google_grpc, false)) {
115     endpoint_ = "meshca.googleapis.com";  // Default target
116   }
117   const Json::Array* call_credentials_array = nullptr;
118   if (ParseJsonObjectField(google_grpc, "call_credentials",
119                            &call_credentials_array, &error_list_google_grpc)) {
120     if (call_credentials_array->size() != 1) {
121       error_list_google_grpc.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
122           "field:call_credentials error:Need exactly one entry."));
123     } else {
124       const Json::Object* call_credentials = nullptr;
125       if (ExtractJsonType((*call_credentials_array)[0], "call_credentials[0]",
126                           &call_credentials, &error_list_google_grpc)) {
127         std::vector<grpc_error*> error_list_call_credentials =
128             ParseJsonObjectCallCredentials(*call_credentials);
129         if (!error_list_call_credentials.empty()) {
130           error_list_google_grpc.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
131               "field:call_credentials", &error_list_call_credentials));
132         }
133       }
134     }
135   }
136
137   return error_list_google_grpc;
138 }
139
140 std::vector<grpc_error*>
141 GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGrpcServices(
142     const Json::Object& grpc_service) {
143   std::vector<grpc_error*> error_list_grpc_services;
144   const Json::Object* google_grpc = nullptr;
145   if (ParseJsonObjectField(grpc_service, "google_grpc", &google_grpc,
146                            &error_list_grpc_services)) {
147     std::vector<grpc_error*> error_list_google_grpc =
148         ParseJsonObjectGoogleGrpc(*google_grpc);
149     if (!error_list_google_grpc.empty()) {
150       error_list_grpc_services.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
151           "field:google_grpc", &error_list_google_grpc));
152     }
153   }
154   if (!ParseJsonObjectFieldAsDuration(grpc_service, "timeout", &timeout_,
155                                       &error_list_grpc_services, false)) {
156     timeout_ = 10 * 1000;  // 10sec default
157   }
158   return error_list_grpc_services;
159 }
160
161 std::vector<grpc_error*>
162 GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectServer(
163     const Json::Object& server) {
164   std::vector<grpc_error*> error_list_server;
165   std::string api_type;
166   if (ParseJsonObjectField(server, "api_type", &api_type, &error_list_server,
167                            false)) {
168     if (api_type != "GRPC") {
169       error_list_server.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
170           "field:api_type error:Only GRPC is supported"));
171     }
172   }
173   const Json::Array* grpc_services = nullptr;
174   if (ParseJsonObjectField(server, "grpc_services", &grpc_services,
175                            &error_list_server)) {
176     if (grpc_services->size() != 1) {
177       error_list_server.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
178           "field:grpc_services error:Need exactly one entry"));
179     } else {
180       const Json::Object* grpc_service = nullptr;
181       if (ExtractJsonType((*grpc_services)[0], "grpc_services[0]",
182                           &grpc_service, &error_list_server)) {
183         std::vector<grpc_error*> error_list_grpc_services =
184             ParseJsonObjectGrpcServices(*grpc_service);
185         if (!error_list_grpc_services.empty()) {
186           error_list_server.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
187               "field:grpc_services", &error_list_grpc_services));
188         }
189       }
190     }
191   }
192   return error_list_server;
193 }
194
195 RefCountedPtr<GoogleMeshCaCertificateProviderFactory::Config>
196 GoogleMeshCaCertificateProviderFactory::Config::Parse(const Json& config_json,
197                                                       grpc_error** error) {
198   auto config =
199       MakeRefCounted<GoogleMeshCaCertificateProviderFactory::Config>();
200   if (config_json.type() != Json::Type::OBJECT) {
201     *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
202         "error:config type should be OBJECT.");
203     return nullptr;
204   }
205   std::vector<grpc_error*> error_list;
206   const Json::Object* server = nullptr;
207   if (ParseJsonObjectField(config_json.object_value(), "server", &server,
208                            &error_list)) {
209     std::vector<grpc_error*> error_list_server =
210         config->ParseJsonObjectServer(*server);
211     if (!error_list_server.empty()) {
212       error_list.push_back(
213           GRPC_ERROR_CREATE_FROM_VECTOR("field:server", &error_list_server));
214     }
215   }
216   if (!ParseJsonObjectFieldAsDuration(
217           config_json.object_value(), "certificate_lifetime",
218           &config->certificate_lifetime_, &error_list, false)) {
219     config->certificate_lifetime_ = 24 * 60 * 60 * 1000;  // 24hrs default
220   }
221   if (!ParseJsonObjectFieldAsDuration(
222           config_json.object_value(), "renewal_grace_period",
223           &config->renewal_grace_period_, &error_list, false)) {
224     config->renewal_grace_period_ = 12 * 60 * 60 * 1000;  // 12hrs default
225   }
226   std::string key_type;
227   if (ParseJsonObjectField(config_json.object_value(), "key_type", &key_type,
228                            &error_list, false)) {
229     if (key_type != "RSA") {
230       error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
231           "field:key_type error:Only RSA is supported."));
232     }
233   }
234   if (!ParseJsonObjectField(config_json.object_value(), "key_size",
235                             &config->key_size_, &error_list, false)) {
236     config->key_size_ = 2048;  // default 2048 bit key size
237   }
238   if (!ParseJsonObjectField(config_json.object_value(), "location",
239                             &config->location_, &error_list, false)) {
240     // GCE/GKE Metadata server needs to be contacted to get the value.
241   }
242   if (!error_list.empty()) {
243     *error = GRPC_ERROR_CREATE_FROM_VECTOR(
244         "Error parsing google Mesh CA config", &error_list);
245     return nullptr;
246   }
247   return config;
248 }
249
250 //
251 // GoogleMeshCaCertificateProviderFactory
252 //
253
254 const char* GoogleMeshCaCertificateProviderFactory::name() const {
255   return kMeshCaPlugin;
256 }
257
258 RefCountedPtr<CertificateProviderFactory::Config>
259 GoogleMeshCaCertificateProviderFactory::CreateCertificateProviderConfig(
260     const Json& config_json, grpc_error** error) {
261   return GoogleMeshCaCertificateProviderFactory::Config::Parse(config_json,
262                                                                error);
263 }
264
265 }  // namespace grpc_core