• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "src/core/lib/security/credentials/call_creds_util.h"
18 
19 #include <grpc/support/port_platform.h>
20 #include <grpc/support/string_util.h>
21 #include <string.h>
22 
23 #include "absl/log/check.h"
24 #include "absl/log/log.h"
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/string_view.h"
27 #include "src/core/lib/security/context/security_context.h"
28 #include "src/core/lib/security/security_connector/security_connector.h"
29 #include "src/core/lib/transport/metadata_batch.h"
30 #include "src/core/util/ref_counted_ptr.h"
31 
32 namespace grpc_core {
33 
34 namespace {
35 
36 struct ServiceUrlAndMethod {
37   std::string service_url;
38   absl::string_view method_name;
39 };
40 
MakeServiceUrlAndMethod(const ClientMetadataHandle & initial_metadata,const grpc_call_credentials::GetRequestMetadataArgs * args)41 ServiceUrlAndMethod MakeServiceUrlAndMethod(
42     const ClientMetadataHandle& initial_metadata,
43     const grpc_call_credentials::GetRequestMetadataArgs* args) {
44   DCHECK(initial_metadata->get_pointer(HttpPathMetadata()) != nullptr);
45   auto service =
46       initial_metadata->get_pointer(HttpPathMetadata())->as_string_view();
47   auto last_slash = service.find_last_of('/');
48   absl::string_view method_name;
49   if (last_slash == absl::string_view::npos) {
50     LOG(ERROR) << "No '/' found in fully qualified method name";
51     service = "";
52     method_name = "";
53   } else if (last_slash == 0) {
54     method_name = "";
55   } else {
56     method_name = service.substr(last_slash + 1);
57     service = service.substr(0, last_slash);
58   }
59   DCHECK(initial_metadata->get_pointer(HttpAuthorityMetadata()) != nullptr);
60   auto host_and_port =
61       initial_metadata->get_pointer(HttpAuthorityMetadata())->as_string_view();
62   absl::string_view url_scheme = args->security_connector->url_scheme();
63   if (url_scheme == GRPC_SSL_URL_SCHEME) {
64     // Remove the port if it is 443.
65     auto port_delimiter = host_and_port.find_last_of(':');
66     if (port_delimiter != absl::string_view::npos &&
67         host_and_port.substr(port_delimiter + 1) == "443") {
68       host_and_port = host_and_port.substr(0, port_delimiter);
69     }
70   }
71   return ServiceUrlAndMethod{
72       absl::StrCat(url_scheme, "://", host_and_port, service), method_name};
73 }
74 
75 }  // namespace
76 
MakeJwtServiceUrl(const ClientMetadataHandle & initial_metadata,const grpc_call_credentials::GetRequestMetadataArgs * args)77 std::string MakeJwtServiceUrl(
78     const ClientMetadataHandle& initial_metadata,
79     const grpc_call_credentials::GetRequestMetadataArgs* args) {
80   return MakeServiceUrlAndMethod(initial_metadata, args).service_url;
81 }
82 
MakePluginAuthMetadataContext(const ClientMetadataHandle & initial_metadata,const grpc_call_credentials::GetRequestMetadataArgs * args)83 grpc_auth_metadata_context MakePluginAuthMetadataContext(
84     const ClientMetadataHandle& initial_metadata,
85     const grpc_call_credentials::GetRequestMetadataArgs* args) {
86   auto fields = MakeServiceUrlAndMethod(initial_metadata, args);
87   grpc_auth_metadata_context ctx;
88   memset(&ctx, 0, sizeof(ctx));
89   ctx.channel_auth_context = args->auth_context != nullptr
90                                  ? args->auth_context->Ref().release()
91                                  : nullptr;
92   ctx.service_url = gpr_strdup(fields.service_url.c_str());
93   ctx.method_name = gpr_strdup(std::string(fields.method_name).c_str());
94   return ctx;
95 }
96 
97 }  // namespace grpc_core
98