// // Copyright 2022 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "src/core/lib/security/credentials/call_creds_util.h" #include #include "absl/log/log.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include #include #include #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/security_connector/security_connector.h" #include "src/core/lib/transport/metadata_batch.h" namespace grpc_core { namespace { struct ServiceUrlAndMethod { std::string service_url; absl::string_view method_name; }; ServiceUrlAndMethod MakeServiceUrlAndMethod( const ClientMetadataHandle& initial_metadata, const grpc_call_credentials::GetRequestMetadataArgs* args) { auto service = initial_metadata->get_pointer(HttpPathMetadata())->as_string_view(); auto last_slash = service.find_last_of('/'); absl::string_view method_name; if (last_slash == absl::string_view::npos) { LOG(ERROR) << "No '/' found in fully qualified method name"; service = ""; method_name = ""; } else if (last_slash == 0) { method_name = ""; } else { method_name = service.substr(last_slash + 1); service = service.substr(0, last_slash); } auto host_and_port = initial_metadata->get_pointer(HttpAuthorityMetadata())->as_string_view(); absl::string_view url_scheme = args->security_connector->url_scheme(); if (url_scheme == GRPC_SSL_URL_SCHEME) { // Remove the port if it is 443. auto port_delimiter = host_and_port.find_last_of(':'); if (port_delimiter != absl::string_view::npos && host_and_port.substr(port_delimiter + 1) == "443") { host_and_port = host_and_port.substr(0, port_delimiter); } } return ServiceUrlAndMethod{ absl::StrCat(url_scheme, "://", host_and_port, service), method_name}; } } // namespace std::string MakeJwtServiceUrl( const ClientMetadataHandle& initial_metadata, const grpc_call_credentials::GetRequestMetadataArgs* args) { return MakeServiceUrlAndMethod(initial_metadata, args).service_url; } grpc_auth_metadata_context MakePluginAuthMetadataContext( const ClientMetadataHandle& initial_metadata, const grpc_call_credentials::GetRequestMetadataArgs* args) { auto fields = MakeServiceUrlAndMethod(initial_metadata, args); grpc_auth_metadata_context ctx; memset(&ctx, 0, sizeof(ctx)); ctx.channel_auth_context = args->auth_context != nullptr ? args->auth_context->Ref().release() : nullptr; ctx.service_url = gpr_strdup(fields.service_url.c_str()); ctx.method_name = gpr_strdup(std::string(fields.method_name).c_str()); return ctx; } } // namespace grpc_core