3 // Copyright 2020 gRPC authors.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <grpc/support/port_platform.h>
21 #include "src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h"
24 #include <type_traits>
26 #include "absl/strings/str_cat.h"
28 #include <grpc/support/string_util.h>
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"
38 const char* kMeshCaPlugin = "meshCA";
43 // GoogleMeshCaCertificateProviderFactory::Config
46 const char* GoogleMeshCaCertificateProviderFactory::Config::name() const {
50 std::string GoogleMeshCaCertificateProviderFactory::Config::ToString() const {
51 // TODO(yashykt): To be filled
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
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)) {
72 "https://www.googleapis.com/auth/cloud-platform"; // default
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,
86 ParseJsonObjectField(sts_service, "actor_token_type",
87 &sts_config_.actor_token_type, &error_list_sts_service,
89 return error_list_sts_service;
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));
106 return error_list_call_credentials;
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
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."));
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));
137 return error_list_google_grpc;
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));
154 if (!ParseJsonObjectFieldAsDuration(grpc_service, "timeout", &timeout_,
155 &error_list_grpc_services, false)) {
156 timeout_ = 10 * 1000; // 10sec default
158 return error_list_grpc_services;
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,
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"));
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"));
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));
192 return error_list_server;
195 RefCountedPtr<GoogleMeshCaCertificateProviderFactory::Config>
196 GoogleMeshCaCertificateProviderFactory::Config::Parse(const Json& config_json,
197 grpc_error** error) {
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.");
205 std::vector<grpc_error*> error_list;
206 const Json::Object* server = nullptr;
207 if (ParseJsonObjectField(config_json.object_value(), "server", &server,
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));
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
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
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."));
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
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.
242 if (!error_list.empty()) {
243 *error = GRPC_ERROR_CREATE_FROM_VECTOR(
244 "Error parsing google Mesh CA config", &error_list);
251 // GoogleMeshCaCertificateProviderFactory
254 const char* GoogleMeshCaCertificateProviderFactory::name() const {
255 return kMeshCaPlugin;
258 RefCountedPtr<CertificateProviderFactory::Config>
259 GoogleMeshCaCertificateProviderFactory::CreateCertificateProviderConfig(
260 const Json& config_json, grpc_error** error) {
261 return GoogleMeshCaCertificateProviderFactory::Config::Parse(config_json,
265 } // namespace grpc_core